Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): programmatic setting of authz policy #1769

Merged
merged 10 commits into from
Nov 18, 2024
6 changes: 6 additions & 0 deletions service/internal/auth/authn.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,16 @@ func normalizeURL(o string, u *url.URL) string {
return ou.String()
}

// deprecated
func (a *Authentication) ExtendAuthzDefaultPolicy(policies [][]string) error {
return a.enforcer.ExtendDefaultPolicy(policies)
}

// SetAuthzPolicy sets the policy for the casbin enforcer
func (a *Authentication) SetAuthzPolicy(policy string) error {
return a.enforcer.SetPolicy(policy)
}

// verifyTokenHandler is a http handler that verifies the token
func (a Authentication) MuxHandler(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand Down
12 changes: 12 additions & 0 deletions service/internal/auth/casbin.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ func NewCasbinEnforcer(c CasbinConfig, logger *logger.Logger) (*Enforcer, error)
}, nil
}

// deprecated
// Extend the default policy
func (e *Enforcer) ExtendDefaultPolicy(policies [][]string) error {
if !e.isDefaultPolicy {
Expand Down Expand Up @@ -215,6 +216,17 @@ func (e *Enforcer) ExtendDefaultPolicy(policies [][]string) error {
return nil
}

// SetPolicy sets the policy for the enforcer
func (e *Enforcer) SetPolicy(policy string) error {
a := stringadapter.NewAdapter(policy)
e.SetAdapter(a)
if err := e.LoadPolicy(); err != nil {
return fmt.Errorf("failed to load extended default policy: %w", err)
}
e.isDefaultPolicy = false
return nil
}

// casbinEnforce is a helper function to enforce the policy with casbin
// TODO implement a common type so this can be used for both http and grpc
func (e *Enforcer) Enforce(token jwt.Token, resource, action string) (bool, error) {
Expand Down
59 changes: 59 additions & 0 deletions service/internal/auth/casbin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package auth
import (
"fmt"
"log/slog"
"strings"
"testing"

"github.com/casbin/casbin/v2/model"
Expand Down Expand Up @@ -455,3 +456,61 @@ func (s *AuthnCasbinSuite) Test_ExtendDefaultPolicies_MalformedErrors() {
s.Require().Error(err)
s.Require().ErrorIs(err, ErrPolicyMalformed)
}

func (s *AuthnCasbinSuite) Test_SetPolicy() {
enforcer, err := NewCasbinEnforcer(CasbinConfig{}, logger.CreateTestLogger())
s.Require().NoError(err)

// Org-admin role
err = enforcer.SetPolicy(strings.Join([]string{
"p, role:admin, new.hello.*, *, allow",
"p, role:standard, new.hello.*, read, allow",
"p, role:standard, new.hello.*, write, deny",
}, "\n"))
s.Require().NoError(err)

// unauthorized role
tok := s.newTokWithDefaultClaim(false, false)
allowed, err := enforcer.Enforce(tok, "new.hello.World", "read")
s.Require().Error(err)
s.False(allowed)
allowed, err = enforcer.Enforce(tok, "new.hello.World", "write")
s.Require().Error(err)
s.False(allowed)
allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "read")
s.Require().Error(err)
s.False(allowed)
allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "write")
s.Require().Error(err)
s.False(allowed)

// other roles denied new policy: admin
tok = s.newTokWithDefaultClaim(true, false)
allowed, err = enforcer.Enforce(tok, "new.hello.World", "read")
s.Require().NoError(err)
s.True(allowed)
allowed, err = enforcer.Enforce(tok, "new.hello.World", "write")
s.Require().NoError(err)
s.True(allowed)
allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "read")
s.Require().Error(err)
s.False(allowed)
allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "write")
s.Require().Error(err)
s.False(allowed)

// other roles denied new policy: standard
tok = s.newTokWithDefaultClaim(false, true)
allowed, err = enforcer.Enforce(tok, "new.hello.World", "read")
s.Require().NoError(err)
s.True(allowed)
allowed, err = enforcer.Enforce(tok, "new.hello.World", "write")
s.Require().Error(err)
s.False(allowed)
allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "read")
s.Require().Error(err)
s.False(allowed)
allowed, err = enforcer.Enforce(tok, "new.service.DoSomething", "write")
s.Require().Error(err)
s.False(allowed)
}
19 changes: 18 additions & 1 deletion service/pkg/server/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ type StartConfig struct {
WaitForShutdownSignal bool
PublicRoutes []string
authzDefaultPolicyExtension [][]string
authzPolicy string
extraCoreServices []serviceregistry.IService
extraServices []serviceregistry.IService
}

// Deprecated: Use WithConfigKey
// WithConfigName option sets the configuration name.
func WithConfigName(name string) StartOptions {
return func(c StartConfig) StartConfig {
c.ConfigKey = name
Expand Down Expand Up @@ -58,6 +59,7 @@ func WithPublicRoutes(routes []string) StartOptions {
}
}

// Deprecated: Use WithConfigKey
// WithAuthZDefaultPolicyExtension option allows for extending the default casbin poliy
// Example:
//
Expand All @@ -71,6 +73,21 @@ func WithAuthZDefaultPolicyExtension(policies [][]string) StartOptions {
}
}

// Deprecated: Use WithAuthZPolicy
// WithAuthZPolicy option sets the casbin policy to be used.
// Example:
//
// opentdf.WithAuthZPolicy(strings.Join([]string{
// "p, role:admin, pep*, *, allow",
// "p, role:standard, pep*, read, allow",
// }, "\n")),
func WithAuthZPolicy(policy string) StartOptions {
return func(c StartConfig) StartConfig {
c.authzPolicy = policy
return c
}
}

// WithCoreServices option adds additional core services to the platform
// It takes a variadic parameter of type serviceregistry.Registration, which represents the core services to be added.
func WithCoreServices(services ...serviceregistry.IService) StartOptions {
Expand Down
14 changes: 14 additions & 0 deletions service/pkg/server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ func Start(f ...StartOptions) error {
}
}

// Set the authz policy
if startConfig.authzPolicy != "" {
if otdf.AuthN == nil {
err := errors.New("authn not enabled")
logger.Error("issue setting authz policy", slog.String("error", err.Error()))
return fmt.Errorf("issue setting authz policy: %w", err)
}
err := otdf.AuthN.SetAuthzPolicy(startConfig.authzPolicy)
if err != nil {
logger.Error("issue setting authz policy", slog.String("error", err.Error()))
return fmt.Errorf("issue setting authz policy: %w", err)
}
}

// Initialize the service registry
logger.Debug("initializing service registry")
svcRegistry := serviceregistry.NewServiceRegistry()
Expand Down
Loading