diff --git a/cmd/start.go b/cmd/start.go
index 14e83268db..0ef72242ef 100644
--- a/cmd/start.go
+++ b/cmd/start.go
@@ -142,7 +142,7 @@ func RegisterServices(_ config.Config, otdf *server.OpenTDFServer, dbClient *db.
}
slog.Info("registering attributes server")
- err = attr.NewAttributesServer(dbClient, otdf.GrpcServer, otdf.Mux)
+ err = attr.NewAttributesServer(dbClient, otdf.GrpcServer, otdf.GrpcInProcess.GetGrpcServer(), otdf.Mux)
if err != nil {
return fmt.Errorf("could not register attributes service: %w", err)
}
@@ -166,7 +166,7 @@ func RegisterServices(_ config.Config, otdf *server.OpenTDFServer, dbClient *db.
}
slog.Info("registering authorization server")
- err = authorization.NewAuthorizationServer(otdf.GrpcServer, otdf.Mux)
+ err = authorization.NewAuthorizationServer(otdf.GrpcServer, otdf.GrpcInProcess.Conn(), otdf.Mux)
if err != nil {
return fmt.Errorf("could not register authorization service: %w", err)
}
diff --git a/docs/grpc/index.html b/docs/grpc/index.html
index 051664f713..6840a8b4c5 100644
--- a/docs/grpc/index.html
+++ b/docs/grpc/index.html
@@ -746,7 +746,7 @@
Action
DecisionRequest
- Example Request Get Decisions to answer the question - Do Bob (represented by entity chain ec1)
and Alice (represented by entity chain ec2) have TRANSMIT authorization for
2 resources; resource1 (attr-set-1) defined by attributes foo:bar resource2 (attr-set-2) defined by attribute foo:bar, color:red ?
{
"actions": [
{
"standard": "STANDARD_ACTION_TRANSMIT"
}
],
"entityChains": [
{
"id": "ec1",
"entities": [
{
"emailAddress": "bob@example.org"
}
]
},
{
"id": "ec2",
"entities": [
{
"userName": "alice@example.org"
}
]
}
],
"resourceAttributes": [
{
"attributeValueReferences": [
{
"attributeFqn": "http://www.example.org/attr/foo/value/bar"
}
]
},
{
"attributeValueReferences": [
{
"attributeFqn": "http://www.example.org/attr/foo/value/bar"
},
{
"attributeFqn": "http://www.example.org/attr/color/value/red"
}
]
}
]
}
+ Example Request Get Decisions to answer the question - Do Bob (represented by entity chain ec1)
and Alice (represented by entity chain ec2) have TRANSMIT authorization for
2 resources; resource1 (attr-set-1) defined by attributes foo:bar resource2 (attr-set-2) defined by attribute foo:bar, color:red ?
{
"actions": [
{
"standard": "STANDARD_ACTION_TRANSMIT"
}
],
"entityChains": [
{
"id": "ec1",
"entities": [
{
"emailAddress": "bob@example.org"
}
]
},
{
"id": "ec2",
"entities": [
{
"userName": "alice@example.org"
}
]
}
],
"resourceAttributes": [
{
"attributeFqns": [
"https://www.example.org/attr/foo/value/value1"
]
},
{
"attributeFqns": [
"https://example.net/attr/attr1/value/value1",
"https://example.net/attr/attr1/value/value2"
]
}
]
}
diff --git a/docs/openapi/authorization/authorization.swagger.json b/docs/openapi/authorization/authorization.swagger.json
index 7a8ac21eb2..436fbc05d5 100644
--- a/docs/openapi/authorization/authorization.swagger.json
+++ b/docs/openapi/authorization/authorization.swagger.json
@@ -130,7 +130,7 @@
}
}
},
- "description": "{\n\"actions\": [\n{\n\"standard\": \"STANDARD_ACTION_TRANSMIT\"\n}\n],\n\"entityChains\": [\n{\n\"id\": \"ec1\",\n\"entities\": [\n{\n\"emailAddress\": \"bob@example.org\"\n}\n]\n},\n{\n\"id\": \"ec2\",\n\"entities\": [\n{\n\"userName\": \"alice@example.org\"\n}\n]\n}\n],\n\"resourceAttributes\": [\n{\n\"attributeValueReferences\": [\n{\n\"attributeFqn\": \"http://www.example.org/attr/foo/value/bar\"\n}\n]\n},\n{\n\"attributeValueReferences\": [\n{\n\"attributeFqn\": \"http://www.example.org/attr/foo/value/bar\"\n},\n{\n\"attributeFqn\": \"http://www.example.org/attr/color/value/red\"\n}\n]\n}\n]\n}",
+ "description": "{\n\"actions\": [\n{\n\"standard\": \"STANDARD_ACTION_TRANSMIT\"\n}\n],\n\"entityChains\": [\n{\n\"id\": \"ec1\",\n\"entities\": [\n{\n\"emailAddress\": \"bob@example.org\"\n}\n]\n},\n{\n\"id\": \"ec2\",\n\"entities\": [\n{\n\"userName\": \"alice@example.org\"\n}\n]\n}\n],\n\"resourceAttributes\": [\n{\n\"attributeFqns\": [\n\"https://www.example.org/attr/foo/value/value1\"\n]\n},\n{\n\"attributeFqns\": [\n\"https://example.net/attr/attr1/value/value1\",\n\"https://example.net/attr/attr1/value/value2\"\n]\n}\n]\n}",
"title": "Example Request Get Decisions to answer the question - Do Bob (represented by entity chain ec1)\nand Alice (represented by entity chain ec2) have TRANSMIT authorization for\n2 resources; resource1 (attr-set-1) defined by attributes foo:bar resource2 (attr-set-2) defined by attribute foo:bar, color:red ?"
},
"authorizationDecisionResponse": {
diff --git a/protocol/go/authorization/authorization.pb.go b/protocol/go/authorization/authorization.pb.go
index 3b0c9cd1fc..eb76189c01 100644
--- a/protocol/go/authorization/authorization.pb.go
+++ b/protocol/go/authorization/authorization.pb.go
@@ -485,20 +485,14 @@ func (*Action_Custom) isAction_Value() {}
// ],
// "resourceAttributes": [
// {
-// "attributeValueReferences": [
-// {
-// "attributeFqn": "http://www.example.org/attr/foo/value/bar"
-// }
+// "attributeFqns": [
+// "https://www.example.org/attr/foo/value/value1"
// ]
// },
// {
-// "attributeValueReferences": [
-// {
-// "attributeFqn": "http://www.example.org/attr/foo/value/bar"
-// },
-// {
-// "attributeFqn": "http://www.example.org/attr/color/value/red"
-// }
+// "attributeFqns": [
+// "https://example.net/attr/attr1/value/value1",
+// "https://example.net/attr/attr1/value/value2"
// ]
// }
// ]
diff --git a/sdkjava/src/main/java/io/opentdf/platform/authorization/DecisionRequest.java b/sdkjava/src/main/java/io/opentdf/platform/authorization/DecisionRequest.java
index a441fb9508..64296b8cdd 100644
--- a/sdkjava/src/main/java/io/opentdf/platform/authorization/DecisionRequest.java
+++ b/sdkjava/src/main/java/io/opentdf/platform/authorization/DecisionRequest.java
@@ -37,20 +37,14 @@
*],
*"resourceAttributes": [
*{
- *"attributeValueReferences": [
- *{
- *"attributeFqn": "http://www.example.org/attr/foo/value/bar"
- *}
+ *"attributeFqns": [
+ *"https://www.example.org/attr/foo/value/value1"
*]
*},
*{
- *"attributeValueReferences": [
- *{
- *"attributeFqn": "http://www.example.org/attr/foo/value/bar"
- *},
- *{
- *"attributeFqn": "http://www.example.org/attr/color/value/red"
- *}
+ *"attributeFqns": [
+ *"https://example.net/attr/attr1/value/value1",
+ *"https://example.net/attr/attr1/value/value2"
*]
*}
*]
@@ -435,20 +429,14 @@ protected Builder newBuilderForType(
*],
*"resourceAttributes": [
*{
- *"attributeValueReferences": [
- *{
- *"attributeFqn": "http://www.example.org/attr/foo/value/bar"
- *}
+ *"attributeFqns": [
+ *"https://www.example.org/attr/foo/value/value1"
*]
*},
*{
- *"attributeValueReferences": [
- *{
- *"attributeFqn": "http://www.example.org/attr/foo/value/bar"
- *},
- *{
- *"attributeFqn": "http://www.example.org/attr/color/value/red"
- *}
+ *"attributeFqns": [
+ *"https://example.net/attr/attr1/value/value1",
+ *"https://example.net/attr/attr1/value/value2"
*]
*}
*]
diff --git a/services/authorization/authorization.go b/services/authorization/authorization.go
index 145151fff2..9c544f7e8d 100644
--- a/services/authorization/authorization.go
+++ b/services/authorization/authorization.go
@@ -4,18 +4,24 @@ import (
"context"
"fmt"
"log/slog"
+ "strings"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/opentdf/platform/protocol/go/authorization"
+ attr "github.com/opentdf/platform/protocol/go/policy/attributes"
+ "github.com/opentdf/platform/services"
"google.golang.org/grpc"
)
type AuthorizationService struct {
authorization.UnimplementedAuthorizationServiceServer
+ cc *grpc.ClientConn
}
-func NewAuthorizationServer(g *grpc.Server, s *runtime.ServeMux) error {
- as := &AuthorizationService{}
+func NewAuthorizationServer(g *grpc.Server, cc *grpc.ClientConn, s *runtime.ServeMux) error {
+ as := &AuthorizationService{
+ cc: cc,
+ }
authorization.RegisterAuthorizationServiceServer(g, as)
err := authorization.RegisterAuthorizationServiceHandlerServer(context.Background(), s, as)
if err != nil {
@@ -27,13 +33,25 @@ func NewAuthorizationServer(g *grpc.Server, s *runtime.ServeMux) error {
func (as AuthorizationService) GetDecisions(ctx context.Context, req *authorization.GetDecisionsRequest) (*authorization.GetDecisionsResponse, error) {
slog.Debug("getting decisions")
+ attrClient := attr.NewAttributesServiceClient(as.cc)
+
// Temporary canned echo response with permit decision for all requested decision/entity/ra combos
rsp := &authorization.GetDecisionsResponse{
DecisionResponses: make([]*authorization.DecisionResponse, 0),
}
for _, dr := range req.DecisionRequests {
for _, ra := range dr.ResourceAttributes {
+ slog.Debug("getting resource attributes", slog.String("FQNs", strings.Join(ra.AttributeFqns, ", ")))
+
+ attrs, err := attrClient.GetAttributesByValueFqns(ctx, &attr.GetAttributesByValueFqnsRequest{
+ Fqns: ra.AttributeFqns,
+ })
+ if err != nil {
+ // TODO: should all decisions in a request fail if one FQN lookup fails?
+ return nil, services.HandleError(err, services.ErrGetRetrievalFailed, slog.String("fqns", strings.Join(ra.AttributeFqns, ", ")))
+ }
for _, ec := range dr.EntityChains {
+ fmt.Printf("\nTODO: make access decision here with these fully qualified attributes: %+v\n", attrs)
decision := &authorization.DecisionResponse{
Decision: authorization.DecisionResponse_DECISION_PERMIT,
EntityChainId: ec.Id,
diff --git a/services/authorization/authorization.proto b/services/authorization/authorization.proto
index d4fa2944e2..37bd50dd9a 100644
--- a/services/authorization/authorization.proto
+++ b/services/authorization/authorization.proto
@@ -49,52 +49,44 @@ message Action {
and Alice (represented by entity chain ec2) have TRANSMIT authorization for
2 resources; resource1 (attr-set-1) defined by attributes foo:bar resource2 (attr-set-2) defined by attribute foo:bar, color:red ?
- {
- "actions": [
- {
- "standard": "STANDARD_ACTION_TRANSMIT"
- }
- ],
- "entityChains": [
- {
- "id": "ec1",
- "entities": [
- {
- "emailAddress": "bob@example.org"
- }
- ]
- },
- {
- "id": "ec2",
- "entities": [
- {
- "userName": "alice@example.org"
- }
- ]
- }
- ],
- "resourceAttributes": [
- {
- "attributeValueReferences": [
- {
- "attributeFqn": "http://www.example.org/attr/foo/value/bar"
- }
- ]
- },
- {
- "attributeValueReferences": [
- {
- "attributeFqn": "http://www.example.org/attr/foo/value/bar"
- },
- {
- "attributeFqn": "http://www.example.org/attr/color/value/red"
- }
- ]
- }
- ]
- }
-
-
+ {
+ "actions": [
+ {
+ "standard": "STANDARD_ACTION_TRANSMIT"
+ }
+ ],
+ "entityChains": [
+ {
+ "id": "ec1",
+ "entities": [
+ {
+ "emailAddress": "bob@example.org"
+ }
+ ]
+ },
+ {
+ "id": "ec2",
+ "entities": [
+ {
+ "userName": "alice@example.org"
+ }
+ ]
+ }
+ ],
+ "resourceAttributes": [
+ {
+ "attributeFqns": [
+ "https://www.example.org/attr/foo/value/value1"
+ ]
+ },
+ {
+ "attributeFqns": [
+ "https://example.net/attr/attr1/value/value1",
+ "https://example.net/attr/attr1/value/value2"
+ ]
+ }
+ ]
+}
*/
message DecisionRequest {
diff --git a/services/policy/attributes/attributes.go b/services/policy/attributes/attributes.go
index 65655d9c60..b56ff958d9 100644
--- a/services/policy/attributes/attributes.go
+++ b/services/policy/attributes/attributes.go
@@ -18,11 +18,14 @@ type AttributesService struct {
dbClient *policydb.PolicyDbClient
}
-func NewAttributesServer(dbClient *db.Client, g *grpc.Server, s *runtime.ServeMux) error {
+func NewAttributesServer(dbClient *db.Client, g *grpc.Server, grpcInprocess *grpc.Server, s *runtime.ServeMux) error {
as := &AttributesService{
dbClient: policydb.NewClient(*dbClient),
}
attr.RegisterAttributesServiceServer(g, as)
+ if grpcInprocess != nil {
+ attr.RegisterAttributesServiceServer(grpcInprocess, as)
+ }
err := attr.RegisterAttributesServiceHandlerServer(context.Background(), s, as)
if err != nil {
return fmt.Errorf("failed to register attributes service handler: %w", err)