Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion lib/identifier/policyidentifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"regexp"
"strings"
)

var (
Expand Down Expand Up @@ -49,7 +50,7 @@ func Parse[T FullyQualified](identifier string) (T, error) {
parsed any
err error
)

identifier = strings.ToLower(identifier)
// Use type assertion to determine the concrete type and call the appropriate parser
switch any(result).(type) {
case *FullyQualifiedAttribute:
Expand Down
7 changes: 0 additions & 7 deletions service/internal/access/v2/evaluate.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,6 @@ func getResourceDecision(
Fqns: make([]string, 0),
}
for _, aav := range regResValue.GetActionAttributeValues() {
// TODO: DSPX-1295 - revisit this logic -- reg res' are different from attr values since they can be both entity and resource
// and are tied to actions and attribute values
//
// if aav.GetAction().GetName() != action.GetName() {
// continue
// }

aavAttrValueFQN := aav.GetAttributeValue().GetFqn()
if !slices.Contains(resourceAttributeValues.GetFqns(), aavAttrValueFQN) {
resourceAttributeValues.Fqns = append(resourceAttributeValues.Fqns, aavAttrValueFQN)
Expand Down
145 changes: 143 additions & 2 deletions service/internal/access/v2/evaluate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ var (
projectAvengersFQN = createAttrValueFQN(baseNamespace, "project", "avengers")
projectXmenFQN = createAttrValueFQN(baseNamespace, "project", "xmen")
projectFantasicFourFQN = createAttrValueFQN(baseNamespace, "project", "fantasticfour")

// Registered resource values
netRegResValFQN = createRegisteredResourceValueFQN("network", "external")
platRegResValFQN = createRegisteredResourceValueFQN("platform", "internal")
)

var (
Expand Down Expand Up @@ -155,8 +159,53 @@ func (s *EvaluateTestSuite) SetupTest() {
}

// Setup accessible registered resource values map
// TODO: DSPX-1295
s.accessibleRegisteredResourceValues = map[string]*policy.RegisteredResourceValue{}
// Create the registered resource values with action attribute values
s.accessibleRegisteredResourceValues = map[string]*policy.RegisteredResourceValue{
netRegResValFQN: {
Id: "network-registered-res-id",
Value: "external",
ActionAttributeValues: []*policy.RegisteredResourceValue_ActionAttributeValue{
{
Id: "network-action-attr-val-1",
Action: actionRead,
AttributeValue: &policy.Value{
Fqn: levelHighestFQN,
Value: "highest",
},
},
{
Id: "network-action-attr-val-2",
Action: actionCreate,
AttributeValue: &policy.Value{
Fqn: levelMidFQN,
Value: "mid",
},
},
},
},
platRegResValFQN: {
Id: "platform-registered-res-id",
Value: "internal",
ActionAttributeValues: []*policy.RegisteredResourceValue_ActionAttributeValue{
{
Id: "platform-action-attr-val-1",
Action: actionRead,
AttributeValue: &policy.Value{
Fqn: projectAvengersFQN,
Value: "avengers",
},
},
{
Id: "platform-action-attr-val-2",
Action: actionRead,
AttributeValue: &policy.Value{
Fqn: projectJusticeLeagueFQN,
Value: "justiceleague",
},
},
},
},
}
}

func TestEvaluateSuite(t *testing.T) {
Expand Down Expand Up @@ -751,11 +800,14 @@ func (s *EvaluateTestSuite) TestEvaluateResourceAttributeValues() {

// Test cases for getResourceDecision
func (s *EvaluateTestSuite) TestGetResourceDecision() {
nonExistentRegResValueFQN := createRegisteredResourceValueFQN("nonexistent", "value")

tests := []struct {
name string
resource *authz.Resource
entitlements subjectmappingbuiltin.AttributeValueFQNsToActions
expectError bool
expectPass bool
}{
{
name: "attribute values resource",
Expand All @@ -765,18 +817,105 @@ func (s *EvaluateTestSuite) TestGetResourceDecision() {
Fqns: []string{levelMidFQN},
},
},
EphemeralId: "test-attr-values-id-1",
},
entitlements: subjectmappingbuiltin.AttributeValueFQNsToActions{
levelMidFQN: []*policy.Action{actionRead},
},
expectError: false,
expectPass: true,
},
{
name: "registered resource value with all entitlements",
resource: &authz.Resource{
Resource: &authz.Resource_RegisteredResourceValueFqn{
RegisteredResourceValueFqn: netRegResValFQN,
},
EphemeralId: "test-reg-res-id-1",
},
entitlements: subjectmappingbuiltin.AttributeValueFQNsToActions{
levelHighestFQN: []*policy.Action{actionRead},
},
expectError: false,
expectPass: true,
},
{
name: "registered resource value with project values",
resource: &authz.Resource{
Resource: &authz.Resource_RegisteredResourceValueFqn{
RegisteredResourceValueFqn: platRegResValFQN,
},
EphemeralId: "test-reg-res-id-2",
},
entitlements: subjectmappingbuiltin.AttributeValueFQNsToActions{
projectAvengersFQN: []*policy.Action{actionRead},
projectJusticeLeagueFQN: []*policy.Action{actionRead},
},
expectError: false,
expectPass: true,
},
{
name: "registered resource value with missing entitlements",
resource: &authz.Resource{
Resource: &authz.Resource_RegisteredResourceValueFqn{
RegisteredResourceValueFqn: platRegResValFQN,
},
EphemeralId: "test-reg-res-id-3",
},
entitlements: subjectmappingbuiltin.AttributeValueFQNsToActions{
// Missing projectJusticeLeagueFQN
projectAvengersFQN: []*policy.Action{actionRead},
},
expectError: false,
expectPass: false, // Missing entitlement for projectJusticeLeagueFQN
},
{
name: "registered resource value with wrong action",
resource: &authz.Resource{
Resource: &authz.Resource_RegisteredResourceValueFqn{
RegisteredResourceValueFqn: netRegResValFQN,
},
EphemeralId: "test-reg-res-id-4",
},
entitlements: subjectmappingbuiltin.AttributeValueFQNsToActions{
// Wrong action
levelHighestFQN: []*policy.Action{actionCreate},
},
expectError: false,
expectPass: false,
},
{
name: "nonexistent registered resource value",
resource: &authz.Resource{
Resource: &authz.Resource_RegisteredResourceValueFqn{
RegisteredResourceValueFqn: nonExistentRegResValueFQN,
},
EphemeralId: "test-reg-res-id-5",
},
entitlements: subjectmappingbuiltin.AttributeValueFQNsToActions{},
expectError: true,
expectPass: false,
},
{
name: "invalid nil resource",
resource: nil,
entitlements: subjectmappingbuiltin.AttributeValueFQNsToActions{},
expectError: true,
},
{
name: "case insensitive registered resource value FQN",
resource: &authz.Resource{
Resource: &authz.Resource_RegisteredResourceValueFqn{
RegisteredResourceValueFqn: strings.ToUpper(netRegResValFQN), // Test case insensitivity
},
EphemeralId: "test-reg-res-id-6",
},
entitlements: subjectmappingbuiltin.AttributeValueFQNsToActions{
levelHighestFQN: []*policy.Action{actionRead},
},
expectError: false,
expectPass: true,
},
}

for _, tc := range tests {
Expand All @@ -796,6 +935,8 @@ func (s *EvaluateTestSuite) TestGetResourceDecision() {
} else {
s.Require().NoError(err)
s.NotNil(decision)
s.Equal(tc.expectPass, decision.Passed, "Decision pass status didn't match")
s.Equal(tc.resource.GetEphemeralId(), decision.ResourceID, "Resource ID didn't match")
}
})
}
Expand Down
8 changes: 0 additions & 8 deletions service/internal/access/v2/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,6 @@ func getResourceDecisionableAttributes(
}

for _, aav := range regResValue.GetActionAttributeValues() {
// TODO: DSPX-1295 - revisit this logic bc it is causing failures for attributes with missing actions
// slog.Info("processing action attribute value", slog.Any("aav", aav))
// aavAction := aav.GetAction()
// if aavAction.GetName() != action.GetName() {
// logger.DebugContext(ctx, "skipping action not matching Decision Request action", slog.String("action", aavAction.GetName()))
// continue
// }

attrValueFQNs = append(attrValueFQNs, aav.GetAttributeValue().GetFqn())
}

Expand Down
28 changes: 18 additions & 10 deletions service/internal/access/v2/pdp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ var (
testPlatformOnPremFQN = createAttrValueFQN(testSecondaryNamespace, "platform", "onprem")
testPlatformHybridFQN = createAttrValueFQN(testSecondaryNamespace, "platform", "hybrid")

// Registered resource value FQNs (TODO: DSPX-1295 - remove)
// Registered resource value FQNs (TODO: remove)
testNetworkPrivateFQN = createRegisteredResourceValueFQN("network", "private")
testNetworkPublicFQN = createRegisteredResourceValueFQN("network", "public")
// testNetworkConfidentialFQN = createRegisteredResourceValueFQN("network", "confidential")
Expand All @@ -97,7 +97,6 @@ var (
// registered resource value FQNs using identifier package
var (
// Classification values
// testClassTopSecretRegResFQN = createRegisteredResourceValueFQN("classification", "topsecret")
testClassSecretRegResFQN = createRegisteredResourceValueFQN("classification", "secret")
testClassConfidentialRegResFQN = createRegisteredResourceValueFQN("classification", "confidential")
// testClassPublicRegResFQN = createRegisteredResourceValueFQN("classification", "public")
Expand All @@ -124,7 +123,7 @@ var (
)

// Registered resource value FQNs using identifier package
// TODO: DSPX-1295 - remove these and use the other ones above
// TODO: remove these and use the other ones above
var (
regResValNoActionAttrValFQN string
regResValSingleActionAttrValFQN string
Expand Down Expand Up @@ -175,12 +174,12 @@ type PDPTestSuite struct {
// Test registered resources
classificationRegRes *policy.RegisteredResource
deptRegRes *policy.RegisteredResource
networkRegRes *policy.RegisteredResource // TODO: DSPX-1295 - remove this and use the others that match test attributes
networkRegRes *policy.RegisteredResource // TODO: remove this and use the others that match test attributes
countryRegRes *policy.RegisteredResource
projectRegRes *policy.RegisteredResource
platformRegRes *policy.RegisteredResource

// Test registered resources (TODO: DSPX-1295 - remove these and use the ones above)
// Test registered resources (TODO: remove these and use the ones above)
regRes *policy.RegisteredResource
regResValNoActionAttrVal *policy.RegisteredResourceValue
regResValSingleActionAttrVal *policy.RegisteredResourceValue
Expand Down Expand Up @@ -698,7 +697,7 @@ func (s *PDPTestSuite) SetupTest() {
},
}

// Initialize test registered resources (TODO: DSPX-1295: replace with above real use cases)
// Initialize test registered resources (TODO: replace with above real use cases)
regResValNoActionAttrVal := &policy.RegisteredResourceValue{
Value: "no-action-attr-val",
ActionAttributeValues: []*policy.RegisteredResourceValue_ActionAttributeValue{},
Expand Down Expand Up @@ -2259,6 +2258,18 @@ func (s *PDPTestSuite) Test_GetDecisionRegisteredResource_MultipleResources() {
})
}

func (s *PDPTestSuite) Test_GetDecisionRegisteredResource_PartialActionEntitlement() {
s.T().Skip("TODO")
}

func (s *PDPTestSuite) Test_GetDecisionRegisteredResource_CombinedAttributeRules_SingleResource() {
s.T().Skip("TODO")
}

func (s *PDPTestSuite) Test_GetDecisionRegisteredResource_AcrossNamespaces() {
s.T().Skip("TODO")
}

// TestGetEntitlements tests the functionality of retrieving entitlements for entities
func (s *PDPTestSuite) Test_GetEntitlements() {
f := s.fixtures
Expand Down Expand Up @@ -2875,10 +2886,7 @@ func createResourcePerFqn(attributeValueFQNs ...string) []*authz.Resource {
for i, fqn := range attributeValueFQNs {
// Use the FQN itself as the resource ID instead of a generic "ephemeral-id-X"
resourceID := fqn

// TODO: DSPX-1295 - identifier lib does not do case-insensitive parsing, so we need to ensure FQNs are lowercased
// should maybe be fixed in the identifier library?
if _, err := identifier.Parse[*identifier.FullyQualifiedRegisteredResourceValue](strings.ToLower(fqn)); err == nil {
if _, err := identifier.Parse[*identifier.FullyQualifiedRegisteredResourceValue](fqn); err == nil {
// FQN is a registered resource value
resources[i] = createRegisteredResource(resourceID, fqn)
} else {
Expand Down
2 changes: 0 additions & 2 deletions service/internal/access/v2/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ func validateGetDecision(entityRepresentation *entityresolutionV2.EntityRepresen
// - registeredResourceValueFQN: must be a valid registered resource value FQN
// - action: must not be nil
// - resources: must not be nil and must contain at least one resource
//
// TODO: DSPX-1295 - add unit tests to detect regressions
func validateGetDecisionRegisteredResource(registeredResourceValueFQN string, action *policy.Action, resources []*authzV2.Resource) error {
if _, err := identifier.Parse[*identifier.FullyQualifiedRegisteredResourceValue](registeredResourceValueFQN); err != nil {
return err
Expand Down
Loading
Loading