Skip to content
Open
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
54 changes: 39 additions & 15 deletions otdf-python-proto/proto-files/authorization/v2/authorization.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ enum Decision {
DECISION_UNSPECIFIED = 0;
DECISION_DENY = 1;
DECISION_PERMIT = 2;
// DECISION_OBLIGATED = 3;
}

// The EntityIdentifier specifies the actor in an entitlement or decision request - the PE, NPE, or PE+NPE being authorized.
Expand Down Expand Up @@ -41,6 +40,13 @@ message EntityIdentifier {
message: "token must be provided"
expression: "has(this.jwt) && this.jwt.size() > 0"
}];

// derive the entity from the request's authorization access token JWT, rather than passing in the body
google.protobuf.BoolValue with_request_token = 4 [(buf.validate.field).cel = {
id: "with_request_token_must_be_true"
message: "with_request_token must be true when set"
expression: "this == true"
}];
}
}

Expand Down Expand Up @@ -84,19 +90,32 @@ message ResourceDecision {
string ephemeral_resource_id = 1;
// decision result
Decision decision = 2;
// obligations (fully qualified values) the PEP is required to fulfill on the given resource
// i.e. https://<namespace>/obl/<definition name>/value/<value>
repeated string required_obligations = 3;
}

// Can the identified entity/entities access?
// 1. one entity reference (actor)
// 2. one action
// 3. one resource
//
// If entitled, checks obligation policy: fulfillable obligations must satisfy all triggered.
message GetDecisionRequest {
// an entity must be identified for authorization decisioning
EntityIdentifier entity_identifier = 1 [(buf.validate.field).required = true];
// name on action is required
policy.Action action = 2 [(buf.validate.field).required = true];
Resource resource = 3 [(buf.validate.field).required = true];

// obligations (fully qualified values) the requester is capable of fulfilling
// i.e. https://<namespace>/obl/<definition name>/value/<value>
repeated string fulfillable_obligation_fqns = 4 [(buf.validate.field).cel = {
id: "obligation_value_fqns_valid"
message: "if provided, fulfillable_obligation_fqns must be between 1 and 50 in count with all valid FQNs"
expression: "this.size() == 0 || (this.size() <= 50 && this.all(item, item.isUri()))"
}];

option (buf.validate.message).cel = {
id: "get_decision_request.action_name_required"
message: "action.name must be provided"
Expand All @@ -106,26 +125,33 @@ message GetDecisionRequest {
message GetDecisionResponse {
// decision on the resource
ResourceDecision decision = 1;
// optional list of obligations represented in URI format
// repeated string obligations = 2;
}

// Can the identified entity/entities access?
// 1. one entity reference (actor)
// 2. one action
// 3. multiple resources
//
// If entitled, checks obligation policy: fulfillable obligations must satisfy all triggered.
//
// Note: this is a more performant bulk request for multiple resource decisions, up to 1000 per request
message GetDecisionMultiResourceRequest {
// an entity must be identified for authorization decisioning
EntityIdentifier entity_identifier = 1 [(buf.validate.field).required = true];
// name on action is required
policy.Action action = 2 [(buf.validate.field).required = true];
repeated Resource resources = 3 [
(buf.validate.field).repeated = {
min_items: 1
max_items: 1000
}
];
repeated Resource resources = 3 [(buf.validate.field).repeated = {
min_items: 1
max_items: 1000
}];

// obligations (fully qualified values) the requester is capable of fulfilling
// i.e. https://<namespace>/obl/<definition name>/value/<value>
repeated string fulfillable_obligation_fqns = 4 [(buf.validate.field).cel = {
id: "obligation_value_fqns_valid"
message: "if provided, fulfillable_obligation_fqns must be between 1 and 50 in count with all valid FQNs"
expression: "this.size() == 0 || (this.size() <= 50 && this.all(item, item.isUri()))"
}];

option (buf.validate.message).cel = {
id: "get_decision_multi_request.action_name_required"
Expand All @@ -145,12 +171,10 @@ message GetDecisionMultiResourceResponse {
// This is a more performant bulk request for complex decisioning (i.e. multiple entity chains or actions on
// multiple resources)
message GetDecisionBulkRequest {
repeated GetDecisionMultiResourceRequest decision_requests = 1 [
(buf.validate.field).repeated = {
min_items: 1
max_items: 200
}
];
repeated GetDecisionMultiResourceRequest decision_requests = 1 [(buf.validate.field).repeated = {
min_items: 1
max_items: 200
}];
}
message GetDecisionBulkResponse {
repeated GetDecisionMultiResourceResponse decision_responses = 1;
Expand Down
24 changes: 24 additions & 0 deletions otdf-python-proto/proto-files/common/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,30 @@ syntax = "proto3";
package common;

import "google/protobuf/timestamp.proto";
import "buf/validate/validate.proto";

message IdNameIdentifier {
option (buf.validate.message).oneof = { fields: ["id", "name"], required: true };
string id = 1 [(buf.validate.field).string.uuid = true];
string name = 2 [
(buf.validate.field).string.min_len = 1,
(buf.validate.field).string.max_len = 253,
(buf.validate.field).cel = {
id: "name_format"
message: "Name must be an alphanumeric string, allowing hyphens and underscores but not as the first or last character. The stored name will be normalized to lower case."
expression: "this.matches('^[a-zA-Z0-9](?:[a-zA-Z0-9_-]*[a-zA-Z0-9])?$')"
}
];
}

message IdFqnIdentifier {
option (buf.validate.message).oneof = { fields: ["id", "fqn"], required: true };
string id = 1 [(buf.validate.field).string.uuid = true];
string fqn = 2 [(buf.validate.field).string = {
min_len: 1
uri: true
}];
}

// Struct to uniquely identify a resource with optional additional metadata
message Metadata {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,20 @@ import "buf/validate/validate.proto";
import "entity/entity.proto";
import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
import "authorization/v2/authorization.proto";

// Entity Entitlements that do not require subject mappings (experimental)
message DirectEntitlement {
string attribute_value_fqn = 1;
repeated string actions = 2;
}

message EntityRepresentation {
// ephemeral entity id from the request
string original_id = 1;
repeated google.protobuf.Struct additional_props = 2;
// direct entitlements applied to Entity (experimental)
repeated DirectEntitlement direct_entitlements = 3;
}

// Resolve a set of entities to their representations.
Expand All @@ -34,6 +43,8 @@ message EntityNotFoundError {
// Create an entity chain for each token (JWT) in the request.
message CreateEntityChainsFromTokensRequest {
repeated entity.Token tokens = 1;
// resources to consider for direct entitlements (experimental)
repeated authorization.v2.Resource resources = 2;
}

message CreateEntityChainsFromTokensResponse {
Expand Down
Loading
Loading