Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
216 commits
Select commit Hold shift + click to select a range
afe3ad1
feat(authz): GetEntitlementsV2 protos and gencode
jakedoublev Apr 28, 2025
c547edc
fix copilot-flagged comment
jakedoublev Apr 28, 2025
8843729
proto fixes
jakedoublev Apr 29, 2025
65fd691
put back auth service change accidentally committed
jakedoublev Apr 29, 2025
288592d
latest changes
jakedoublev Apr 29, 2025
999a876
draft v2 protos
jakedoublev Apr 29, 2025
50d8436
put back original authz protos
jakedoublev Apr 29, 2025
6993846
Merge branch 'main' into feat/entitle-actions-protos
jakedoublev Apr 30, 2025
88c25d2
undo change to original authn proto file
ryanulit Apr 30, 2025
b3c41f3
rename reg res fqn to use value
ryanulit Apr 30, 2025
13cf017
add entity chain comment
ryanulit Apr 30, 2025
ec22eb2
Merge branch 'main' into feat/entitle-actions-protos
ryanulit Apr 30, 2025
decdd36
Merge branch 'main' into feat/entitle-actions-protos
ryanulit Apr 30, 2025
7e9e22b
rename bulk methods to use same prefix
ryanulit Apr 30, 2025
2364f25
update protos per meeting outcome
jakedoublev Apr 30, 2025
c25a26f
cleanup
jakedoublev Apr 30, 2025
8d3b5ca
Merge branch 'main' into feat/entitle-actions-protos
jakedoublev May 1, 2025
884e39c
wip: new authz library approach considering actions in ABAC decisions
jakedoublev May 2, 2025
4af31a8
WIP
jakedoublev May 2, 2025
fe76f4b
Merge branch 'main' into feat/entitle-actions-protos
jakedoublev May 4, 2025
b9e0d53
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 4, 2025
9c18432
cleanup
jakedoublev May 4, 2025
95bb501
refactoring
jakedoublev May 4, 2025
c7d1082
feat(core): introduce FQN utility library
jakedoublev May 4, 2025
b2b4e90
wait to remove existing utility funcitons until library is consumable
jakedoublev May 4, 2025
19192b5
go work not ready yet
jakedoublev May 4, 2025
a8a10f9
Merge branch 'feat/fqn-lib' into feat/authz-actions
jakedoublev May 5, 2025
38316fc
go.work
jakedoublev May 5, 2025
6490167
WIP
jakedoublev May 5, 2025
03651a8
ERS should take new authv2 entity proto
jakedoublev May 5, 2025
35d6a7c
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 5, 2025
be05e55
cleanup
jakedoublev May 5, 2025
d0d53dd
ERS should handle v2 authorization entity proto
jakedoublev May 5, 2025
f2cb992
WIP
jakedoublev May 5, 2025
fe42878
WIP
jakedoublev May 5, 2025
c545b56
presume FQN is populated in response with upstream PR #2151
jakedoublev May 5, 2025
5dad8b5
Merge remote-tracking branch 'origin' into feat/entitle-actions-protos
jakedoublev May 5, 2025
29db0a3
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 5, 2025
ae761a2
remove rego from new access pdp
jakedoublev May 5, 2025
f4172cc
cleanup
jakedoublev May 5, 2025
999428f
auth v2 service scaffold and versioned registration/sdk
ryanulit May 6, 2025
095d515
add proper deprecated comments
ryanulit May 6, 2025
aade0d6
remove non-proto changes moved to separate branch
ryanulit May 6, 2025
76390ab
Merge remote-tracking branch 'origin' into feat/entitle-actions-protos
jakedoublev May 6, 2025
10fa7a6
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 6, 2025
bfbf58b
rm lib/fqn
jakedoublev May 6, 2025
8833bcb
Merge branch 'main' into feat/entitle-actions-protos
jakedoublev May 7, 2025
b276933
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 7, 2025
3c1fd29
validators
jakedoublev May 7, 2025
1908252
WIP
jakedoublev May 7, 2025
1cbac72
wip
jakedoublev May 7, 2025
a6d66e6
WIP
jakedoublev May 8, 2025
944a7a8
drop scope from GetEntitlements
jakedoublev May 8, 2025
ab1fc4f
comment clarity
jakedoublev May 8, 2025
724c789
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 8, 2025
d7694af
more validators
jakedoublev May 8, 2025
59cf05e
tests for helpers
jakedoublev May 8, 2025
5d06d2f
tests
jakedoublev May 8, 2025
222816c
errors
jakedoublev May 8, 2025
90f689e
cleanup
jakedoublev May 8, 2025
82cc36a
tests for subject mapping evals with actions
jakedoublev May 9, 2025
30fcc04
DRY
jakedoublev May 9, 2025
10fa265
checkpoint
jakedoublev May 9, 2025
571371e
tests and validators
jakedoublev May 9, 2025
852ad4a
types
jakedoublev May 9, 2025
e887caf
renames
jakedoublev May 9, 2025
7b069e9
good tests for rule evaluation with actions
jakedoublev May 9, 2025
120ba08
Merge branch 'main' into feat/entitle-actions-protos
jakedoublev May 9, 2025
58bf849
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 9, 2025
d34d531
test get decisions e2e
jakedoublev May 11, 2025
abe14fa
wip with new tests
jakedoublev May 11, 2025
f9b10fd
wip with new tests
jakedoublev May 11, 2025
3819655
tests with reliance on resource ephemeral IDs
jakedoublev May 12, 2025
d61e56e
merging of entitled actions down the hierarchy tree and get entitleme…
jakedoublev May 12, 2025
308289f
cleanup
jakedoublev May 12, 2025
238ed78
more tests
jakedoublev May 12, 2025
3e65e8c
more tests
jakedoublev May 12, 2025
29b24a6
tests for bugfixes
jakedoublev May 13, 2025
9a9d9f4
quality
jakedoublev May 13, 2025
ec82598
WIP
jakedoublev May 13, 2025
711090c
authorization service calls JIT PDP
jakedoublev May 13, 2025
038cf7d
Merge branch 'main' into feat/entitle-actions-protos
jakedoublev May 13, 2025
f4b8a27
comment
jakedoublev May 13, 2025
6cfb545
update protos
jakedoublev May 13, 2025
8be0ff6
improve protovalidate rules
jakedoublev May 13, 2025
0fdab47
improve protovalidate rules
jakedoublev May 13, 2025
1eed22e
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 13, 2025
de98892
comments and multiresource vs single resource service RPCs
jakedoublev May 13, 2025
be2118d
GetDecisionByTokenMultiResource addition
jakedoublev May 13, 2025
066cb55
deprecated comments
jakedoublev May 13, 2025
899e8f8
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 13, 2025
46afa59
wip
jakedoublev May 13, 2025
f003f41
use v1 messages in v2 authz where it makes sense (token and entity ch…
jakedoublev May 13, 2025
977b506
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 13, 2025
a6578de
wip
jakedoublev May 13, 2025
75b37bd
rm extraneous resource ID
jakedoublev May 13, 2025
c50a138
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 13, 2025
d4444b8
pare back responses, proto comments, better validation
jakedoublev May 13, 2025
b87698d
Merge branch 'feat/entitle-actions-protos' into feat/authz-actions
jakedoublev May 13, 2025
2386bf7
WIP
jakedoublev May 13, 2025
0ddaeea
ERS v2 after PR review discussion
jakedoublev May 13, 2025
62ce30d
feat(core): entityresolutionv2 service engaging auth v2 entity types
jakedoublev May 13, 2025
2317e79
feat(core): auth v2 with breaking changes to auth v1 protos (#2211)
jakedoublev May 14, 2025
8ee0b3b
make no changes at all to authz v1
jakedoublev May 14, 2025
1c5a1a9
proto comments
jakedoublev May 14, 2025
67bc23c
field names
jakedoublev May 14, 2025
1782f18
entity identifier proto name
jakedoublev May 14, 2025
7f50caa
proto comments
jakedoublev May 14, 2025
96d86d7
fix misnumbered index called out by copilot
jakedoublev May 14, 2025
33d98c7
rm empty commits to unchanged proto files
jakedoublev May 14, 2025
33dc394
validation PR suggestion
jakedoublev May 14, 2025
8156172
Merge branch 'feat/entitle-actions-protos' into feat/ers-v2
jakedoublev May 14, 2025
f7c0e93
claims v2
jakedoublev May 14, 2025
a48f091
keycloak v2
jakedoublev May 14, 2025
02fa5a2
lint fixes
jakedoublev May 14, 2025
b62da08
more lint fixes
jakedoublev May 14, 2025
6cd80ce
more lint fixes
jakedoublev May 14, 2025
ee61d6f
add deprecation warning to v1 protos
jakedoublev May 15, 2025
ed406b7
Merge remote-tracking branch 'origin' into feat/entitle-actions-protos
jakedoublev May 15, 2025
ea18fa0
Merge branch 'feat/entitle-actions-protos' into feat/ers-v2
jakedoublev May 15, 2025
57f3137
Merge remote-tracking branch 'origin' into feat/ers-v2
jakedoublev May 15, 2025
5ba5b08
Merge branch 'feat/ers-v2' into feat/authz-actions
jakedoublev May 15, 2025
1dc3e25
do not change any v1 ers logic
jakedoublev May 15, 2025
980c6bd
fix type location
jakedoublev May 15, 2025
efb1d25
access pdp proto/flow updates with newly merged authz, entity, ers pr…
jakedoublev May 15, 2025
5f00564
rm notes code
jakedoublev May 15, 2025
d0c7ba5
rollup tests and implementation fixes
jakedoublev May 15, 2025
c7d3be0
wire up SDK and KAS to new endpoints
jakedoublev May 15, 2025
2b09aac
Merge remote-tracking branch 'origin' into feat/authz-actions
jakedoublev May 15, 2025
004795a
lint fixes
jakedoublev May 16, 2025
c713ef5
more lint fixes
jakedoublev May 16, 2025
6291e60
more lint fixes
jakedoublev May 16, 2025
99fdd31
fix tests
jakedoublev May 16, 2025
176ef8c
fix implementation and tests in authorization_test.go rollup helpers
jakedoublev May 16, 2025
8f7ee9c
lint fix
jakedoublev May 16, 2025
dfd69cb
lint fix
jakedoublev May 16, 2025
2a24b7d
fix logs
jakedoublev May 16, 2025
6e02387
serve authz v2 in service registry
jakedoublev May 16, 2025
2539399
working kas with no attrs locally
jakedoublev May 16, 2025
1a22980
fix service registry tests
jakedoublev May 16, 2025
27ea627
fix resources length in kas canAccess
jakedoublev May 16, 2025
7e57bd5
move entity id prefix for logging to entity.go
jakedoublev May 16, 2025
d1aa8e2
preserve lookup of no-subject-mapping attribute values
jakedoublev May 16, 2025
f200a75
fix helpers
jakedoublev May 16, 2025
f40dcc8
go fmt
jakedoublev May 16, 2025
f4184b9
fix examples
jakedoublev May 16, 2025
4638203
skip environmental entities in decisions flow
jakedoublev May 16, 2025
1bfda7e
Merge remote-tracking branch 'origin' into feat/authz-actions
jakedoublev May 16, 2025
26a978b
fix examples import
jakedoublev May 16, 2025
98ff5b2
use exported constant
jakedoublev May 16, 2025
785a609
better case insensitivity
jakedoublev May 16, 2025
3a1d31f
do not use exported constant in examples
jakedoublev May 16, 2025
4c7bc73
kas is able to skip getDecisions when there are no attributes on TDF
jakedoublev May 16, 2025
e58b5cd
affirmed that get decisions should forgo environment entities
jakedoublev May 16, 2025
be07c1e
case handling fixes
jakedoublev May 16, 2025
538d1f4
evaluate.go go fmt
jakedoublev May 16, 2025
53ddc23
Merge branch 'main' into feat/authz-actions
jakedoublev May 19, 2025
7aa6905
allow service loggers to propagate service versions (differentiating …
jakedoublev May 19, 2025
864ba7d
ensure fixtures in integration test contain the necessary actions on …
jakedoublev May 19, 2025
48f565d
log fix
jakedoublev May 19, 2025
5e26c87
fix all list subject mappings in RT tests
jakedoublev May 19, 2025
53a4a30
fix rollup multi resource decision
jakedoublev May 19, 2025
c7368cc
warn log for kas access pdp ephemeral resource ID missing
jakedoublev May 19, 2025
43147f6
benchmark decision v2
jakedoublev May 19, 2025
32dd65c
improve commented test output clarity
jakedoublev May 19, 2025
a216d61
benchmark v2 endpoint
jakedoublev May 19, 2025
c0c51e5
casbin standard for v2 auth service
jakedoublev May 19, 2025
2bb741c
tweak
jakedoublev May 19, 2025
8766a03
go mod tidy in examples
jakedoublev May 19, 2025
0894678
casbin test fix
jakedoublev May 19, 2025
bae1700
fix benchmark output
jakedoublev May 19, 2025
d8dd5ec
fix rewrap fqn slice performance
jakedoublev May 19, 2025
09e7864
lint fix
jakedoublev May 19, 2025
1a086f8
fix slice indexing
jakedoublev May 19, 2025
a597781
fix multi-resource rollup
jakedoublev May 19, 2025
ab9a853
fix test
jakedoublev May 19, 2025
66d5841
improve rollup tests
jakedoublev May 20, 2025
0238d62
Merge branch 'main' into feat/authz-actions
jakedoublev May 20, 2025
1c9f0ae
Merge branch 'main' into feat/authz-actions
jakedoublev May 20, 2025
677129d
feat(authz): access pdp v2 with actions
jakedoublev May 20, 2025
079f6a0
put back cleanup not needed right now
jakedoublev May 20, 2025
9bf0e60
put back logging changes
jakedoublev May 20, 2025
5cd84cb
cleanup
jakedoublev May 20, 2025
00ead46
improvements
jakedoublev May 20, 2025
2ac9eb1
cleanup
jakedoublev May 20, 2025
fc74ba2
copilot fixes
jakedoublev May 21, 2025
62ec151
error logging suggestions
jakedoublev May 21, 2025
31a4f3a
lint fixes
jakedoublev May 21, 2025
0a94bdd
name errors where they are utilized
jakedoublev May 21, 2025
1d6f488
Merge branch 'feat/access-pdp2' into feat/authz-actions
jakedoublev May 21, 2025
f05f4c7
delete duplicate errors in errors.go
jakedoublev May 21, 2025
94dc733
copilot suggestions
jakedoublev May 21, 2025
1e8392e
gemini comments
jakedoublev May 21, 2025
7a30719
Merge branch 'feat/access-pdp2', remote-tracking branch 'origin' into…
jakedoublev May 21, 2025
593f6eb
Merge branch 'main' into feat/authz-actions
jakedoublev May 21, 2025
dfae101
return errors more effectively if encountering registered resources a…
jakedoublev May 21, 2025
bcf4959
logging suggestions
jakedoublev May 22, 2025
a197bab
spacing
jakedoublev May 22, 2025
dd7fd44
lower case resource attribute FQN at highest level in GetDecision flow
jakedoublev May 22, 2025
4d33515
merge duplicate actions performance
jakedoublev May 22, 2025
8d2eff7
Merge branch 'feat/access-pdp2' into feat/authz-actions
jakedoublev May 22, 2025
98e3cc3
lint fix
jakedoublev May 22, 2025
e1f92d8
error assertions in tests
jakedoublev May 22, 2025
01007b6
lint fix
jakedoublev May 22, 2025
8566fc4
improve validator logic per suggestion
jakedoublev May 22, 2025
e858995
Merge branch 'feat/access-pdp2' into feat/authz-actions
jakedoublev May 22, 2025
be6b36a
only use multiresource decision endpoint if multiple resources
jakedoublev May 22, 2025
2bad9ef
remove massive log
jakedoublev May 22, 2025
d3de07e
improve logs
jakedoublev May 22, 2025
8751910
improve logs
jakedoublev May 22, 2025
c97d09a
lint fix
jakedoublev May 22, 2025
9da164f
Merge remote-tracking branch 'origin' into feat/authz-actions
jakedoublev May 22, 2025
7b2d8ab
put back v1 service changes
jakedoublev May 22, 2025
eae6024
Merge branch 'main' into feat/authz-actions
jakedoublev May 23, 2025
9ff6cd0
Update service/authorization/v2/authorization.go
jakedoublev May 27, 2025
e3f0f3a
create a new resource instance for each iteration in benchmark test
jakedoublev May 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion .github/workflows/checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,19 @@ jobs:
echo "$OUTPUT";
echo "EODECISION"
} >> "$GITHUB_ENV"
- name: run decision v2 benchmark tests
run: |
# Run the benchmark with a specific count (adjust as needed)
OUTPUT=$(./examples/examples benchmark-decision-v2 --count 5000)
echo "--- Decision Benchmark v2 Output ---"
echo "$OUTPUT"
echo "$OUTPUT" >> "$GITHUB_STEP_SUMMARY" # Add to job summary page
# Save the output to an environment variable for the comment step
{
echo "BENCHMARK_DECISION_V2_OUTPUT<<EODECISIONV2"; # Unique delimiter
echo "$OUTPUT";
echo "EODECISIONV2"
} >> "$GITHUB_ENV"
- name: run tdf3 benchmark tests
run: |
OUTPUT=$(./examples/examples benchmark --count=5000 --concurrent=50)
Expand Down Expand Up @@ -292,12 +305,13 @@ jobs:
with:
script: |
const decisionOutput = process.env.BENCHMARK_DECISION_OUTPUT || '## Decision Benchmark Skipped or Failed';
const decisionV2Output = process.env.BENCHMARK_DECISION_V2_OUTPUT || '## Decision Benchmark v2 Skipped or Failed';
const metricsOutput = process.env.BENCHMARK_METRICS_OUTPUT || '## Standard Benchmark Metrics Skipped or Failed';
const bulkOutput = process.env.BENCHMARK_BULK_OUTPUT || '## Bulk Benchmark Skipped or Failed';
const tdf3Output = process.env.BENCHMARK_TDF3_OUTPUT || '## TDF3 Benchmark Skipped or Failed';
const nanoOutput = process.env.BENCHMARK_NANO_OUTPUT || '## Nano Benchmark Skipped or Failed';

const body = `<details><summary>Benchmark results, click to expand</summary>\n\n${decisionOutput}\n\n${bulkOutput}\n\n${tdf3Output}\n\n${nanoOutput}\n\n${metricsOutput}</details>`;
const body = `<details><summary>Benchmark results, click to expand</summary>\n\n${decisionOutput}\n\n${decisionV2Output}\n\n${bulkOutput}\n\n${tdf3Output}\n\n${nanoOutput}\n\n${metricsOutput}</details>`;

github.rest.issues.createComment({
owner: context.repo.owner,
Expand Down
4 changes: 2 additions & 2 deletions examples/cmd/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ func authorizationExamples() error {
}
defer s.Close()

// request decision on "TRANSMIT" Action
// request decision on "read" Action
actions := []*policy.Action{{
Value: &policy.Action_Standard{Standard: policy.Action_STANDARD_ACTION_TRANSMIT},
Name: "read",
}}

// model two groups of entities; user bob and user alice
Expand Down
2 changes: 1 addition & 1 deletion examples/cmd/benchmark_decision.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func runDecisionBenchmark(_ *cobra.Command, _ []string) error {
}

// Print results
fmt.Printf("# Benchmark Results:\n")
fmt.Printf("# Benchmark authorization.GetDecisions Results:\n")
fmt.Printf("| Metric | Value |\n")
fmt.Printf("|-------------------------|------------------------|\n")
if err == nil {
Expand Down
103 changes: 103 additions & 0 deletions examples/cmd/benchmark_decision_v2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//nolint:forbidigo // We use Println here extensively because we are printing markdown.
package cmd

import (
"context"
"fmt"
"strconv"
"time"

authzV2 "github.com/opentdf/platform/protocol/go/authorization/v2"
"github.com/opentdf/platform/protocol/go/entity"
"github.com/opentdf/platform/protocol/go/policy"
"github.com/spf13/cobra"
)

func init() {
benchmarkCmd := &cobra.Command{
Use: "benchmark-decision-v2",
Short: "benchmark authorization.v2.GetDecisionMultiResource",
Long: `A OpenTDF benchmark tool to measure throughput and latency with configurable concurrency for authorization.v2.GetDecisionMultiResource.`,
RunE: runDecisionBenchmarkV2,
}
benchmarkCmd.Flags().IntVar(&config.RequestCount, "count", 100, "Total number of requests") //nolint: mnd // This is output to the help with explanation
ExamplesCmd.AddCommand(benchmarkCmd)
}

func runDecisionBenchmarkV2(_ *cobra.Command, _ []string) error {
// Create new offline client
client, err := newSDK()
if err != nil {
return err
}

var resources []*authzV2.Resource
attrValueFQN := "https://example.com/attr/attr1/value/value1"

for i := range config.RequestCount {
r := &authzV2.Resource{
EphemeralId: "resource-%d" + strconv.Itoa(i),
Resource: &authzV2.Resource_AttributeValues_{
AttributeValues: &authzV2.Resource_AttributeValues{
Fqns: []string{attrValueFQN},
},
},
}
resources = append(resources, r)
}

start := time.Now()
res, err := client.AuthorizationV2.GetDecisionMultiResource(context.Background(), &authzV2.GetDecisionMultiResourceRequest{
Action: &policy.Action{
Name: "read",
},
EntityIdentifier: &authzV2.EntityIdentifier{
Identifier: &authzV2.EntityIdentifier_EntityChain{
EntityChain: &entity.EntityChain{
EphemeralId: "decision-bulk-entity-chain",
Entities: []*entity.Entity{
{
EphemeralId: "jwtentity-0-clientid-opentdf-sdk",
EntityType: &entity.Entity_ClientId{ClientId: "opentdf-public"},
Category: entity.Entity_CATEGORY_ENVIRONMENT,
},
{
EphemeralId: "jwtentity-1-username-sample-user",
EntityType: &entity.Entity_UserName{UserName: "sample-user"},
Category: entity.Entity_CATEGORY_SUBJECT,
},
},
},
},
},
Resources: resources,
})
end := time.Now()
totalTime := end.Sub(start)

numberApproved := 0
numberDenied := 0
if err == nil {
for _, decision := range res.GetResourceDecisions() {
if decision.GetDecision() == authzV2.Decision_DECISION_PERMIT {
numberApproved++
} else {
numberDenied++
}
}
}

// Print results
fmt.Printf("# Benchmark authorization.v2.GetMultiResourceDecision Results:\n")
fmt.Printf("| Metric | Value |\n")
fmt.Printf("|-------------------------|------------------------|\n")
if err == nil {
fmt.Printf("| Approved Decision Requests | %d |\n", numberApproved)
fmt.Printf("| Denied Decision Requests | %d |\n", numberDenied)
} else {
fmt.Printf("| Error | %s |\n", err.Error())
}
fmt.Printf("| Total Time | %s |\n", totalTime)

return nil
}
186 changes: 179 additions & 7 deletions service/authorization/v2/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ package authorization
import (
"context"
"errors"
"fmt"
"log/slog"

"connectrpc.com/connect"
authzV2 "github.com/opentdf/platform/protocol/go/authorization/v2"
authzV2Connect "github.com/opentdf/platform/protocol/go/authorization/v2/authorizationv2connect"
otdf "github.com/opentdf/platform/sdk"
"github.com/opentdf/platform/service/internal/access/v2"
"github.com/opentdf/platform/service/logger"
"github.com/opentdf/platform/service/pkg/serviceregistry"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
"google.golang.org/protobuf/types/known/wrapperspb"
)

type Service struct {
Expand All @@ -36,9 +42,9 @@ func NewRegistration() *serviceregistry.Service[authzV2Connect.AuthorizationServ

logger := srp.Logger

// default ERS endpoint
as.sdk = srp.SDK
as.logger = logger

// if err := srp.RegisterReadinessCheck("authorization", as.IsReady); err != nil {
// logger.Error("failed to register authorization readiness check", slog.String("error", err.Error()))
// }
Expand All @@ -60,21 +66,187 @@ func NewRegistration() *serviceregistry.Service[authzV2Connect.AuthorizationServ
// }

// GetEntitlements for an entity chain
func (as *Service) GetEntitlements(_ context.Context, _ *connect.Request[authzV2.GetEntitlementsRequest]) (*connect.Response[authzV2.GetEntitlementsResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("GetEntitlements not implemented"))
func (as *Service) GetEntitlements(ctx context.Context, req *connect.Request[authzV2.GetEntitlementsRequest]) (*connect.Response[authzV2.GetEntitlementsResponse], error) {
as.logger.DebugContext(ctx, "getting entitlements")

ctx, span := as.Tracer.Start(ctx, "GetEntitlements")
defer span.End()

// Extract trace context from the incoming request
propagator := otel.GetTextMapPropagator()
ctx = propagator.Extract(ctx, propagation.HeaderCarrier(req.Header()))

entityIdentifier := req.Msg.GetEntityIdentifier()
withComprehensiveHierarchy := req.Msg.GetWithComprehensiveHierarchy()

// When authorization service can consume cached policy, switch to the other PDP (process based on policy passed in)
pdp, err := access.NewJustInTimePDP(ctx, as.logger, as.sdk)
if err != nil {
as.logger.ErrorContext(ctx, "failed to create JIT PDP", slog.String("error", err.Error()))
return nil, connect.NewError(connect.CodeInternal, err)
}

entitlements, err := pdp.GetEntitlements(ctx, entityIdentifier, withComprehensiveHierarchy)
if err != nil {
// TODO: any bad request errors that aren't 500s?
as.logger.ErrorContext(ctx, "failed to get entitlements", slog.String("error", err.Error()))
return nil, connect.NewError(connect.CodeInternal, err)
}

rsp := &authzV2.GetEntitlementsResponse{
Entitlements: entitlements,
}

return connect.NewResponse(rsp), nil
}

// GetDecision for an entity chain and an action on a single resource
func (as *Service) GetDecision(_ context.Context, _ *connect.Request[authzV2.GetDecisionRequest]) (*connect.Response[authzV2.GetDecisionResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("GetDecision not implemented"))
func (as *Service) GetDecision(ctx context.Context, req *connect.Request[authzV2.GetDecisionRequest]) (*connect.Response[authzV2.GetDecisionResponse], error) {
as.logger.DebugContext(ctx, "getting decision")

ctx, span := as.Tracer.Start(ctx, "GetDecision")
defer span.End()

// Extract trace context from the incoming request
propagator := otel.GetTextMapPropagator()
ctx = propagator.Extract(ctx, propagation.HeaderCarrier(req.Header()))

pdp, err := access.NewJustInTimePDP(ctx, as.logger, as.sdk)
if err != nil {
as.logger.ErrorContext(ctx, "failed to create JIT PDP", slog.String("error", err.Error()))
return nil, connect.NewError(connect.CodeInternal, err)
}
request := req.Msg
entityIdentifier := request.GetEntityIdentifier()
action := request.GetAction()
resource := request.GetResource()

decisions, permitted, err := pdp.GetDecision(ctx, entityIdentifier, action, []*authzV2.Resource{resource})
if err != nil {
// TODO: any bad request errors that aren't 500s?
as.logger.ErrorContext(ctx, "failed to get decision", slog.String("error", err.Error()))
return nil, connect.NewError(connect.CodeInternal, err)
}
resp, err := rollupSingleResourceDecision(permitted, decisions)
if err != nil {
as.logger.ErrorContext(ctx, "failed to rollup single resource decision", slog.String("error", err.Error()))
return nil, connect.NewError(connect.CodeInternal, err)
}
return connect.NewResponse(resp), nil
}

// GetDecisionMultiResource for an entity chain and action on multiple resources
func (as *Service) GetDecisionMultiResource(_ context.Context, _ *connect.Request[authzV2.GetDecisionMultiResourceRequest]) (*connect.Response[authzV2.GetDecisionMultiResourceResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("GetDecisionMultiResource not implemented"))
func (as *Service) GetDecisionMultiResource(ctx context.Context, req *connect.Request[authzV2.GetDecisionMultiResourceRequest]) (*connect.Response[authzV2.GetDecisionMultiResourceResponse], error) {
as.logger.DebugContext(ctx, "getting decision multi resource")

ctx, span := as.Tracer.Start(ctx, "GetDecisionMultiResource")
defer span.End()

// Extract trace context from the incoming request
propagator := otel.GetTextMapPropagator()
ctx = propagator.Extract(ctx, propagation.HeaderCarrier(req.Header()))

pdp, err := access.NewJustInTimePDP(ctx, as.logger, as.sdk)
if err != nil {
as.logger.ErrorContext(ctx, "failed to create JIT PDP", slog.String("error", err.Error()))
return nil, connect.NewError(connect.CodeInternal, err)
}
request := req.Msg
entityIdentifier := request.GetEntityIdentifier()
action := request.GetAction()
resources := request.GetResources()

decisions, allPermitted, err := pdp.GetDecision(ctx, entityIdentifier, action, resources)
if err != nil {
// TODO: any bad request errors that aren't 500s?
as.logger.ErrorContext(ctx, "failed to get decision", slog.String("error", err.Error()))
return nil, connect.NewError(connect.CodeInternal, err)
}

resourceDecisions, err := rollupMultiResourceDecision(decisions)
if err != nil {
as.logger.ErrorContext(ctx, "failed to rollup multi resource decision", slog.String("error", err.Error()))
return nil, connect.NewError(connect.CodeInternal, err)
}

resp := &authzV2.GetDecisionMultiResourceResponse{
AllPermitted: &wrapperspb.BoolValue{
Value: allPermitted,
},
ResourceDecisions: resourceDecisions,
}

return connect.NewResponse(resp), nil
}

// GetDecisionBulk for multiple requests, each comprising a combination of entity chain, action, and one or more resources
func (as *Service) GetDecisionBulk(_ context.Context, _ *connect.Request[authzV2.GetDecisionBulkRequest]) (*connect.Response[authzV2.GetDecisionBulkResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("GetDecisionBulk not implemented"))
}

// rollupMultiResourceDecision creates a standardized response for multi-resource decisions
// by processing the decisions returned from the PDP.
func rollupMultiResourceDecision(
decisions []*access.Decision,
) ([]*authzV2.ResourceDecision, error) {
if len(decisions) == 0 {
return nil, errors.New("no decisions returned")
}

var resourceDecisions []*authzV2.ResourceDecision

for idx, decision := range decisions {
if decision == nil {
return nil, fmt.Errorf("nil decision at index %d", idx)
}
if len(decision.Results) == 0 {
return nil, errors.New("no decision results returned")
}
for _, result := range decision.Results {
access := authzV2.Decision_DECISION_DENY
if result.Passed {
access = authzV2.Decision_DECISION_PERMIT
}
resourceDecision := &authzV2.ResourceDecision{
Decision: access,
EphemeralResourceId: result.ResourceID,
}
resourceDecisions = append(resourceDecisions, resourceDecision)
}
}

return resourceDecisions, nil
}

// rollupSingleResourceDecision creates a standardized response for a single resource decision
// by processing the decision returned from the PDP.
func rollupSingleResourceDecision(
permitted bool,
decisions []*access.Decision,
) (*authzV2.GetDecisionResponse, error) {
if len(decisions) == 0 {
return nil, errors.New("no decisions returned")
}

decision := decisions[0]
if decision == nil {
return nil, errors.New("nil decision at index 0")
}

if len(decision.Results) == 0 {
return nil, errors.New("no decision results returned")
}

result := decision.Results[0]
access := authzV2.Decision_DECISION_DENY
if permitted {
access = authzV2.Decision_DECISION_PERMIT
}
resourceDecision := &authzV2.ResourceDecision{
Decision: access,
EphemeralResourceId: result.ResourceID,
}
return &authzV2.GetDecisionResponse{
Decision: resourceDecision,
}, nil
}
Loading
Loading