Skip to content

Commit

Permalink
feat: Support constants
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Haines <[email protected]>
  • Loading branch information
haines committed Nov 4, 2024
1 parent b3ada4a commit 203de63
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 43 deletions.
1 change: 1 addition & 0 deletions cerbos/grpc_admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func TestAdminClient(t *testing.T) {
"derived_roles.apatr_common_roles": "derived_roles/common_roles.yaml",
"derived_roles.alpha": "derived_roles/derived_roles_01.yaml",
"derived_roles.beta": "derived_roles/derived_roles_02.yaml",
"export_constants.bazqux": "export_constants/export_constants_01.yaml",
"export_variables.foobar": "export_variables/export_variables_01.yaml",
"principal.donald_duck.vdefault": "principal_policies/policy_02.yaml",
"principal.donald_duck.vdefault/acme": "principal_policies/policy_02_acme.yaml",
Expand Down
121 changes: 120 additions & 1 deletion cerbos/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,21 @@ func (ps *PolicySet) AddDerivedRoles(policies ...*DerivedRoles) *PolicySet {
return ps
}

// AddExportConstants adds the given exported constants to the set.
func (ps *PolicySet) AddExportConstants(policies ...*ExportConstants) *PolicySet {
for _, p := range policies {
if p == nil {
continue
}

if err := ps.add(p); err != nil {
ps.err = multierr.Append(ps.err, fmt.Errorf("failed to add exported constants [%s]: %w", p.Obj.Name, err))
}
}

return ps
}

// AddExportVariables adds the given exported variables to the set.
func (ps *PolicySet) AddExportVariables(policies ...*ExportVariables) *PolicySet {
for _, p := range policies {
Expand Down Expand Up @@ -706,6 +721,7 @@ func NewResourcePolicy(resource, version string) *ResourcePolicy {
Obj: &policyv1.ResourcePolicy{
Resource: resource,
Version: version,
Constants: &policyv1.Constants{Local: make(map[string]*structpb.Value)},
Variables: &policyv1.Variables{Local: make(map[string]string)},
},
}
Expand Down Expand Up @@ -750,6 +766,23 @@ func (rp *ResourcePolicy) AddResourceRules(rules ...*ResourceRule) *ResourcePoli
return rp
}

// WithConstantsImports adds import statements for exported constants.
func (rp *ResourcePolicy) WithConstantsImports(name ...string) *ResourcePolicy {
rp.Obj.Constants.Import = append(rp.Obj.Constants.Import, name...)
return rp
}

// WithConstant adds a constant definition for use in conditions.
// Valid value types are those that can be converted to a [google.protobuf.Value].
//
// [google.protobuf.Value]: https://pkg.go.dev/google.golang.org/protobuf/types/known/structpb#NewValue
func (rp *ResourcePolicy) WithConstant(name string, value any) *ResourcePolicy {
var err error
rp.Obj.Constants.Local[name], err = structpb.NewValue(value)
rp.err = multierr.Append(rp.err, err)
return rp
}

// WithVariablesImports adds import statements for exported variables.
func (rp *ResourcePolicy) WithVariablesImports(name ...string) *ResourcePolicy {
rp.Obj.Variables.Import = append(rp.Obj.Variables.Import, name...)
Expand Down Expand Up @@ -864,6 +897,7 @@ func NewPrincipalPolicy(principal, version string) *PrincipalPolicy {
Obj: &policyv1.PrincipalPolicy{
Principal: principal,
Version: version,
Constants: &policyv1.Constants{Local: make(map[string]*structpb.Value)},
Variables: &policyv1.Variables{Local: make(map[string]string)},
},
}
Expand Down Expand Up @@ -899,6 +933,23 @@ func (pp *PrincipalPolicy) WithVersion(version string) *PrincipalPolicy {
return pp
}

// WithConstantsImports adds import statements for exported constants.
func (pp *PrincipalPolicy) WithConstantsImports(name ...string) *PrincipalPolicy {
pp.Obj.Constants.Import = append(pp.Obj.Constants.Import, name...)
return pp
}

// WithConstant adds a constant definition for use in conditions.
// Valid value types are those that can be converted to a [google.protobuf.Value].
//
// [google.protobuf.Value]: https://pkg.go.dev/google.golang.org/protobuf/types/known/structpb#NewValue
func (pp *PrincipalPolicy) WithConstant(name string, value any) *PrincipalPolicy {
var err error
pp.Obj.Constants.Local[name], err = structpb.NewValue(value)
pp.err = multierr.Append(pp.err, err)
return pp
}

// WithVariablesImports adds import statements for exported variables.
func (pp *PrincipalPolicy) WithVariablesImports(name ...string) *PrincipalPolicy {
pp.Obj.Variables.Import = append(pp.Obj.Variables.Import, name...)
Expand Down Expand Up @@ -996,13 +1047,15 @@ func (pr *PrincipalRule) Validate() error {
// DerivedRoles is a builder for derived roles.
type DerivedRoles struct {
Obj *policyv1.DerivedRoles
err error
}

// NewDerivedRoles creates a new derived roles set with the given name.
func NewDerivedRoles(name string) *DerivedRoles {
return &DerivedRoles{
Obj: &policyv1.DerivedRoles{
Name: name,
Constants: &policyv1.Constants{Local: make(map[string]*structpb.Value)},
Variables: &policyv1.Variables{Local: make(map[string]string)},
},
}
Expand All @@ -1024,6 +1077,23 @@ func (dr *DerivedRoles) addRoleDef(name string, parentRoles []string, comp *poli
return dr
}

// WithConstantsImports adds import statements for exported constants.
func (dr *DerivedRoles) WithConstantsImports(name ...string) *DerivedRoles {
dr.Obj.Constants.Import = append(dr.Obj.Constants.Import, name...)
return dr
}

// WithConstant adds a constant definition for use in conditions.
// Valid value types are those that can be converted to a [google.protobuf.Value].
//
// [google.protobuf.Value]: https://pkg.go.dev/google.golang.org/protobuf/types/known/structpb#NewValue
func (dr *DerivedRoles) WithConstant(name string, value any) *DerivedRoles {
var err error
dr.Obj.Constants.Local[name], err = structpb.NewValue(value)
dr.err = multierr.Append(dr.err, err)
return dr
}

// WithVariablesImports adds import statements for exported variables.
func (dr *DerivedRoles) WithVariablesImports(name ...string) *DerivedRoles {
dr.Obj.Variables.Import = append(dr.Obj.Variables.Import, name...)
Expand All @@ -1038,7 +1108,7 @@ func (dr *DerivedRoles) WithVariable(name, expr string) *DerivedRoles {

// Err returns any errors accumulated during the construction of the derived roles.
func (dr *DerivedRoles) Err() error {
return nil
return dr.err
}

// Validate checks whether the derived roles are valid.
Expand All @@ -1058,6 +1128,55 @@ func (dr *DerivedRoles) build() (*policyv1.Policy, error) {
return p, internal.ValidatePolicy(p)
}

// ExportConstants is a builder for exported constants.
type ExportConstants struct {
Obj *policyv1.ExportConstants
err error
}

// NewExportConstants creates a new exported constants set with the given name.
func NewExportConstants(name string) *ExportConstants {
return &ExportConstants{
Obj: &policyv1.ExportConstants{
Name: name,
Definitions: make(map[string]*structpb.Value),
},
}
}

// AddConstant defines an exported constant with the given name to be the given value.
// Valid value types are those that can be converted to a [google.protobuf.Value].
//
// [google.protobuf.Value]: https://pkg.go.dev/google.golang.org/protobuf/types/known/structpb#NewValue
func (ec *ExportConstants) AddConstant(name string, value any) *ExportConstants {
var err error
ec.Obj.Definitions[name], err = structpb.NewValue(value)
ec.err = multierr.Append(ec.err, err)
return ec
}

// Err returns any errors accumulated during the construction of the exported constants.
func (ec *ExportConstants) Err() error {
return ec.err
}

// Validate checks whether the exported constants are valid.
func (ec *ExportConstants) Validate() error {
_, err := ec.build()
return err
}

func (ec *ExportConstants) build() (*policyv1.Policy, error) {
p := &policyv1.Policy{
ApiVersion: apiVersion,
PolicyType: &policyv1.Policy_ExportConstants{
ExportConstants: ec.Obj,
},
}

return p, internal.ValidatePolicy(p)
}

// ExportVariables is a builder for exported variables.
type ExportVariables struct {
Obj *policyv1.ExportVariables
Expand Down
29 changes: 29 additions & 0 deletions cerbos/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"testing"

"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/structpb"

"github.com/cerbos/cerbos-sdk-go/cerbos"
effectv1 "github.com/cerbos/cerbos/api/genpb/cerbos/effect/v1"
Expand All @@ -19,9 +20,12 @@ import (
const (
actionApprove = "approve"
actionCreate = "create"
constantName = "bar"
constantValue = float64(9000)
id = "XX125"
kind = "leave_request"
derivedRolesName = "my_derived_roles"
exportConstantsName = "my_constants"
exportVariablesName = "my_variables"
ref = "cerbos:///principal.json"
roleName = "employee_that_owns_the_record"
Expand Down Expand Up @@ -65,6 +69,11 @@ func TestBuilders(t *testing.T) {
require.NoError(t, dr.Validate())
cmpDerivedRoles(t, dr)
})
t.Run("ExportConstants", func(t *testing.T) {
ec := newExportConstants(t)
require.NoError(t, ec.Validate())
cmpExportConstants(t, ec)
})
t.Run("ExportVariables", func(t *testing.T) {
ev := newExportVariables(t)
require.NoError(t, ev.Validate())
Expand Down Expand Up @@ -127,6 +136,13 @@ func cmpDerivedRoles(t *testing.T, dr *cerbos.DerivedRoles) {
require.Equal(t, map[string]string{variableName: variableExpr}, dr.Obj.Variables.Local)
}

func cmpExportConstants(t *testing.T, ec *cerbos.ExportConstants) {
t.Helper()

require.Equal(t, exportConstantsName, ec.Obj.Name)
require.Equal(t, map[string]any{constantName: constantValue}, (&structpb.Struct{Fields: ec.Obj.Definitions}).AsMap())
}

func cmpExportVariables(t *testing.T, ev *cerbos.ExportVariables) {
t.Helper()

Expand Down Expand Up @@ -242,11 +258,20 @@ func newDerivedRoles(t *testing.T) *cerbos.DerivedRoles {
t.Helper()

return cerbos.NewDerivedRoles(derivedRolesName).
WithConstantsImports(exportConstantsName).
WithConstant(constantName, constantValue).
WithVariablesImports(exportVariablesName).
WithVariable(variableName, variableExpr).
AddRole(roleName, roles)
}

func newExportConstants(t *testing.T) *cerbos.ExportConstants {
t.Helper()

return cerbos.NewExportConstants(exportConstantsName).
AddConstant(constantName, constantValue)
}

func newExportVariables(t *testing.T) *cerbos.ExportVariables {
t.Helper()

Expand Down Expand Up @@ -280,6 +305,8 @@ func newPrincipalPolicy(t *testing.T) *cerbos.PrincipalPolicy {

return cerbos.NewPrincipalPolicy(principal, version).
WithScope(scope).
WithConstantsImports(exportConstantsName).
WithConstant(constantName, constantValue).
WithVariablesImports(exportVariablesName).
WithVariable(variableName, variableExpr).
AddPrincipalRules(
Expand All @@ -292,6 +319,8 @@ func newResourcePolicy(t *testing.T) *cerbos.ResourcePolicy {

return cerbos.NewResourcePolicy(resource, version).
WithScope(scope).
WithConstantsImports(exportConstantsName).
WithConstant(constantName, constantValue).
WithVariablesImports(exportVariablesName).
WithVariable(variableName, variableExpr)
}
Expand Down
30 changes: 15 additions & 15 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
module github.com/cerbos/cerbos-sdk-go

go 1.22
go 1.22.0

toolchain go1.23.2

require (
github.com/bufbuild/protovalidate-go v0.7.2
github.com/cenkalti/backoff/v4 v4.3.0
github.com/cerbos/cerbos/api/genpb v0.39.0
github.com/cerbos/cerbos/api/genpb v0.39.1-0.20241104095130-b7e5c7703d82
github.com/ghodss/yaml v1.0.0
github.com/google/go-cmp v0.6.0
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0
Expand All @@ -22,25 +22,25 @@ require (
)

require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240920164238-5a7b106cbb87.2 // indirect
dario.cat/mergo v1.0.0 // indirect
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.1-20240920164238-5a7b106cbb87.1 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/containerd/continuity v0.4.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/docker/cli v27.1.1+incompatible // indirect
github.com/docker/docker v27.1.1+incompatible // indirect
github.com/docker/docker v27.2.0+incompatible // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/go-viper/mapstructure/v2 v2.0.0 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/cel-go v0.21.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc v1.0.6 // indirect
Expand All @@ -52,22 +52,22 @@ require (
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/opencontainers/runc v1.1.14 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240917153116-6f2963f01587 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20241011083415-71c992bc3c87 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240924160255-9d4c2d233b61 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit 203de63

Please sign in to comment.