@@ -26,6 +26,7 @@ import (
2626 "github.com/opentdf/platform/service/internal/subjectmappingbuiltin"
2727 "github.com/opentdf/platform/service/logger"
2828 "github.com/opentdf/platform/service/logger/audit"
29+ "github.com/opentdf/platform/service/pkg/config"
2930 "github.com/opentdf/platform/service/pkg/db"
3031 "github.com/opentdf/platform/service/pkg/serviceregistry"
3132 "github.com/opentdf/platform/service/policies"
@@ -39,7 +40,7 @@ var ErrEmptyStringAttribute = errors.New("resource attributes must have at least
3940
4041type AuthorizationService struct { //nolint:revive // AuthorizationService is a valid name for this struct
4142 sdk * otdf.SDK
42- config Config
43+ config * Config
4344 logger * logger.Logger
4445 eval rego.PreparedEvalQuery
4546}
@@ -56,28 +57,81 @@ type CustomRego struct {
5657 Query string `mapstructure:"query" json:"query" default:"data.opentdf.entitlements.attributes"`
5758}
5859
60+ func (as * AuthorizationService ) loadRegoAndBuiltins (cfg * Config ) error {
61+ var (
62+ entitlementRego []byte
63+ err error
64+ )
65+ // Build Rego PreparedEvalQuery
66+ // Load rego from embedded file or custom path
67+ if cfg .Rego .Path != "" {
68+ entitlementRego , err = os .ReadFile (cfg .Rego .Path )
69+ if err != nil {
70+ return fmt .Errorf ("failed to read custom entitlements.rego file: %w" , err )
71+ }
72+ } else {
73+ entitlementRego , err = policies .EntitlementsRego .ReadFile ("entitlements/entitlements.rego" )
74+ if err != nil {
75+ return fmt .Errorf ("failed to read entitlements.rego file: %w" , err )
76+ }
77+ }
78+
79+ // Register builtin
80+ subjectmappingbuiltin .SubjectMappingBuiltin ()
81+
82+ as .eval , err = rego .New (
83+ rego .Query (cfg .Rego .Query ),
84+ rego .Module ("entitlements.rego" , string (entitlementRego )),
85+ rego .StrictBuiltinErrors (true ),
86+ ).PrepareForEval (context .Background ())
87+ if err != nil {
88+ return fmt .Errorf ("failed to prepare entitlements.rego for eval: %w" , err )
89+ }
90+ return nil
91+ }
92+
93+ func OnConfigUpdate (as * AuthorizationService ) serviceregistry.OnConfigUpdateHook {
94+ return func (_ context.Context , cfg config.ServiceConfig ) error {
95+ err := mapstructure .Decode (cfg , as .config )
96+ if err != nil {
97+ return fmt .Errorf ("invalid auth svc cfg [%v] %w" , cfg , err )
98+ }
99+
100+ //nolint:contextcheck // context is not needed here
101+ if err = as .loadRegoAndBuiltins (as .config ); err != nil {
102+ return fmt .Errorf ("failed to load rego and builtins: %w" , err )
103+ }
104+
105+ as .logger .Info ("authorization service config reloaded" )
106+
107+ return nil
108+ }
109+ }
110+
59111func NewRegistration () * serviceregistry.Service [authorizationconnect.AuthorizationServiceHandler ] {
112+ as := new (AuthorizationService )
113+ onUpdateConfig := OnConfigUpdate (as )
114+
60115 return & serviceregistry.Service [authorizationconnect.AuthorizationServiceHandler ]{
61116 ServiceOptions : serviceregistry.ServiceOptions [authorizationconnect.AuthorizationServiceHandler ]{
62117 Namespace : "authorization" ,
63118 ServiceDesc : & authorization .AuthorizationService_ServiceDesc ,
64119 ConnectRPCFunc : authorizationconnect .NewAuthorizationServiceHandler ,
65120 GRPCGatewayFunc : authorization .RegisterAuthorizationServiceHandler ,
121+ OnConfigUpdate : onUpdateConfig ,
66122 RegisterFunc : func (srp serviceregistry.RegistrationParams ) (authorizationconnect.AuthorizationServiceHandler , serviceregistry.HandlerServer ) {
67- var (
68- err error
69- entitlementRego []byte
70- authZCfg = new (Config )
71- )
123+ var authZCfg = new (Config )
72124
73125 logger := srp .Logger
74126
75127 // default ERS endpoint
76- as := & AuthorizationService {sdk : srp .SDK , logger : logger }
128+ as .sdk = srp .SDK
129+ as .logger = logger
77130 if err := srp .RegisterReadinessCheck ("authorization" , as .IsReady ); err != nil {
78131 logger .Error ("failed to register authorization readiness check" , slog .String ("error" , err .Error ()))
79132 }
80133
134+ // Read in config defaults only on first register
81135 if err := defaults .Set (authZCfg ); err != nil {
82136 panic (fmt .Errorf ("failed to set defaults for authorization service config: %w" , err ))
83137 }
@@ -107,36 +161,13 @@ func NewRegistration() *serviceregistry.Service[authorizationconnect.Authorizati
107161 }
108162 }
109163
110- logger .Debug ("authorization service config" , slog .Any ("config" , * authZCfg ))
111-
112- // Build Rego PreparedEvalQuery
113-
114- // Load rego from embedded file or custom path
115- if authZCfg .Rego .Path != "" {
116- entitlementRego , err = os .ReadFile (authZCfg .Rego .Path )
117- if err != nil {
118- panic (fmt .Errorf ("failed to read custom entitlements.rego file: %w" , err ))
119- }
120- } else {
121- entitlementRego , err = policies .EntitlementsRego .ReadFile ("entitlements/entitlements.rego" )
122- if err != nil {
123- panic (fmt .Errorf ("failed to read entitlements.rego file: %w" , err ))
124- }
125- }
126-
127- // Register builtin
128- subjectmappingbuiltin .SubjectMappingBuiltin ()
129-
130- as .eval , err = rego .New (
131- rego .Query (authZCfg .Rego .Query ),
132- rego .Module ("entitlements.rego" , string (entitlementRego )),
133- rego .StrictBuiltinErrors (true ),
134- ).PrepareForEval (context .Background ())
135- if err != nil {
136- panic (fmt .Errorf ("failed to prepare entitlements.rego for eval: %w" , err ))
164+ if err := as .loadRegoAndBuiltins (authZCfg ); err != nil {
165+ logger .Error ("failed to load rego and builtins" , slog .String ("error" , err .Error ()))
166+ panic (fmt .Errorf ("failed to load rego and builtins: %w" , err ))
137167 }
168+ as .config = authZCfg
138169
139- as . config = * authZCfg
170+ logger . Debug ( "authorization service config" )
140171
141172 return as , nil
142173 },
0 commit comments