@@ -12,9 +12,11 @@ import (
1212 "github.com/go-viper/mapstructure/v2"
1313 authzV2 "github.com/opentdf/platform/protocol/go/authorization/v2"
1414 authzV2Connect "github.com/opentdf/platform/protocol/go/authorization/v2/authorizationv2connect"
15+ "github.com/opentdf/platform/protocol/go/policy"
1516 otdf "github.com/opentdf/platform/sdk"
1617 "github.com/opentdf/platform/service/internal/access/v2"
1718 "github.com/opentdf/platform/service/logger"
19+ ctxAuth "github.com/opentdf/platform/service/pkg/auth"
1820 "github.com/opentdf/platform/service/pkg/cache"
1921 "github.com/opentdf/platform/service/pkg/serviceregistry"
2022 "go.opentelemetry.io/otel"
@@ -23,6 +25,13 @@ import (
2325 "google.golang.org/protobuf/types/known/wrapperspb"
2426)
2527
28+ var (
29+ ErrFailedToBuildRequestContext = errors .New ("failed to contextualize decision request" )
30+ ErrFailedToInitPDP = errors .New ("failed to create JIT PDP" )
31+ ErrFailedToGetDecision = errors .New ("failed to get decision" )
32+ ErrFailedToGetEntitlements = errors .New ("failed to get entitlements" )
33+ )
34+
2635type Service struct {
2736 sdk * otdf.SDK
2837 config * Config
@@ -138,15 +147,12 @@ func (as *Service) GetEntitlements(ctx context.Context, req *connect.Request[aut
138147 // When authorization service can consume cached policy, switch to the other PDP (process based on policy passed in)
139148 pdp , err := access .NewJustInTimePDP (ctx , as .logger , as .sdk , as .cache )
140149 if err != nil {
141- as .logger .ErrorContext (ctx , "failed to create JIT PDP" , slog .Any ("error" , err ))
142- return nil , connect .NewError (connect .CodeInternal , err )
150+ return nil , statusifyError (ctx , as .logger , errors .Join (ErrFailedToGetEntitlements , ErrFailedToInitPDP , err ))
143151 }
144152
145153 entitlements , err := pdp .GetEntitlements (ctx , entityIdentifier , withComprehensiveHierarchy )
146154 if err != nil {
147- // TODO: any bad request errors that aren't 500s?
148- as .logger .ErrorContext (ctx , "failed to get entitlements" , slog .Any ("error" , err ))
149- return nil , connect .NewError (connect .CodeInternal , err )
155+ return nil , statusifyError (ctx , as .logger , errors .Join (ErrFailedToGetEntitlements , err ))
150156 }
151157 rsp := & authzV2.GetEntitlementsResponse {
152158 Entitlements : entitlements ,
@@ -168,27 +174,34 @@ func (as *Service) GetDecision(ctx context.Context, req *connect.Request[authzV2
168174
169175 pdp , err := access .NewJustInTimePDP (ctx , as .logger , as .sdk , as .cache )
170176 if err != nil {
171- as .logger .ErrorContext (ctx , "failed to create JIT PDP" , slog .Any ("error" , err ))
172- return nil , connect .NewError (connect .CodeInternal , err )
177+ return nil , statusifyError (ctx , as .logger , errors .Join (ErrFailedToInitPDP , err ))
173178 }
174179
175180 request := req .Msg
176181 entityIdentifier := request .GetEntityIdentifier ()
177182 action := request .GetAction ()
178183 resource := request .GetResource ()
184+ fulfillableObligations := request .GetFulfillableObligationFqns ()
179185
180- decisions , permitted , err := pdp . GetDecision (ctx , entityIdentifier , action , [] * authzV2. Resource { resource } )
186+ reqContext , err := as . getDecisionRequestContext (ctx )
181187 if err != nil {
182- as .logger .ErrorContext (ctx , "failed to get decision" , slog .Any ("error" , err ))
183- if errors .Is (err , access .ErrFQNNotFound ) || errors .Is (err , access .ErrDefinitionNotFound ) {
184- return nil , connect .NewError (connect .CodeNotFound , err )
185- }
186- return nil , connect .NewError (connect .CodeInternal , err )
188+ return nil , statusifyError (ctx , as .logger , err )
189+ }
190+
191+ decisions , permitted , err := pdp .GetDecision (
192+ ctx ,
193+ entityIdentifier ,
194+ action ,
195+ []* authzV2.Resource {resource },
196+ reqContext ,
197+ fulfillableObligations ,
198+ )
199+ if err != nil {
200+ return nil , statusifyError (ctx , as .logger , err )
187201 }
188202 resp , err := rollupSingleResourceDecision (permitted , decisions )
189203 if err != nil {
190- as .logger .ErrorContext (ctx , "failed to rollup single-resource decision" , slog .Any ("error" , err ))
191- return nil , connect .NewError (connect .CodeInternal , err )
204+ return nil , statusifyError (ctx , as .logger , err )
192205 }
193206 return connect .NewResponse (resp ), nil
194207}
@@ -206,21 +219,34 @@ func (as *Service) GetDecisionMultiResource(ctx context.Context, req *connect.Re
206219
207220 pdp , err := access .NewJustInTimePDP (ctx , as .logger , as .sdk , as .cache )
208221 if err != nil {
209- return nil , statusifyError (ctx , as .logger , errors .Join (errors . New ( "failed to create JIT PDP" ) , err ))
222+ return nil , statusifyError (ctx , as .logger , errors .Join (ErrFailedToInitPDP , err ))
210223 }
211224 request := req .Msg
212225 entityIdentifier := request .GetEntityIdentifier ()
213226 action := request .GetAction ()
214227 resources := request .GetResources ()
228+ fulfillableObligations := request .GetFulfillableObligationFqns ()
229+
230+ reqContext , err := as .getDecisionRequestContext (ctx )
231+ if err != nil {
232+ return nil , statusifyError (ctx , as .logger , err )
233+ }
215234
216- decisions , allPermitted , err := pdp .GetDecision (ctx , entityIdentifier , action , resources )
235+ decisions , allPermitted , err := pdp .GetDecision (
236+ ctx ,
237+ entityIdentifier ,
238+ action ,
239+ resources ,
240+ reqContext ,
241+ fulfillableObligations ,
242+ )
217243 if err != nil {
218- return nil , statusifyError (ctx , as .logger , errors .Join (errors . New ( "failed to get decision" ) , err ))
244+ return nil , statusifyError (ctx , as .logger , errors .Join (ErrFailedToGetDecision , err ))
219245 }
220246
221247 resourceDecisions , err := rollupMultiResourceDecisions (decisions )
222248 if err != nil {
223- return nil , statusifyError (ctx , as .logger , errors . Join ( errors . New ( "failed to rollup multi-resource decision" ), err ) )
249+ return nil , statusifyError (ctx , as .logger , err )
224250 }
225251
226252 resp := & authzV2.GetDecisionMultiResourceResponse {
@@ -246,27 +272,33 @@ func (as *Service) GetDecisionBulk(ctx context.Context, req *connect.Request[aut
246272
247273 pdp , err := access .NewJustInTimePDP (ctx , as .logger , as .sdk , as .cache )
248274 if err != nil {
249- return nil , statusifyError (ctx , as .logger , errors .Join (errors . New ( "failed to create JIT PDP" ) , err ))
275+ return nil , statusifyError (ctx , as .logger , errors .Join (ErrFailedToInitPDP , err ))
250276 }
251277
252278 multiRequests := req .Msg .GetDecisionRequests ()
253279 decisionResponses := make ([]* authzV2.GetDecisionMultiResourceResponse , len (multiRequests ))
254280
281+ reqContext , err := as .getDecisionRequestContext (ctx )
282+ if err != nil {
283+ return nil , statusifyError (ctx , as .logger , err )
284+ }
285+
255286 // TODO: revisit performance of this loop after introduction of caching and registered resource values within decisioning,
256287 // as the same entity in multiple requests should only be resolved JIT once, not once per request if the same in each.
257288 for idx , request := range multiRequests {
258289 entityIdentifier := request .GetEntityIdentifier ()
259290 action := request .GetAction ()
260291 resources := request .GetResources ()
292+ fulfillableObligations := request .GetFulfillableObligationFqns ()
261293
262- decisions , allPermitted , err := pdp .GetDecision (ctx , entityIdentifier , action , resources )
294+ decisions , allPermitted , err := pdp .GetDecision (ctx , entityIdentifier , action , resources , reqContext , fulfillableObligations )
263295 if err != nil {
264- return nil , statusifyError (ctx , as .logger , errors .Join (errors . New ( "failed to get bulk decision" ) , err ))
296+ return nil , statusifyError (ctx , as .logger , errors .Join (ErrFailedToGetDecision , err ))
265297 }
266298
267299 resourceDecisions , err := rollupMultiResourceDecisions (decisions )
268300 if err != nil {
269- return nil , statusifyError (ctx , as .logger , errors . Join ( errors . New ( "failed to rollup bulk multi-resource decision" ), err ) , slog .Int ("index" , idx ))
301+ return nil , statusifyError (ctx , as .logger , err , slog .Int ("index" , idx ))
270302 }
271303
272304 decisionResponse := & authzV2.GetDecisionMultiResourceResponse {
@@ -283,3 +315,17 @@ func (as *Service) GetDecisionBulk(ctx context.Context, req *connect.Request[aut
283315 }
284316 return connect .NewResponse (rsp ), nil
285317}
318+
319+ // Builds a decision request context out of contextual metadata for the downstream obligation trigger/fulfillment decisioning
320+ func (as * Service ) getDecisionRequestContext (ctx context.Context ) (* policy.RequestContext , error ) {
321+ incoming := true
322+ clientID , err := ctxAuth .GetClientIDFromContext (ctx , incoming )
323+ if err != nil {
324+ return nil , errors .Join (ErrFailedToBuildRequestContext , err )
325+ }
326+ return & policy.RequestContext {
327+ Pep : & policy.PolicyEnforcementPoint {
328+ ClientId : clientID ,
329+ },
330+ }, nil
331+ }
0 commit comments