Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: proto changes for attribute-based access control #98

Merged
merged 20 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
aa7d2ff
feat: update definitions to support ABAC Conditions (#90)
jpadilla Sep 14, 2023
2b2e5ac
feat(abac): update Write API to include a condition per tuple (#95)
miparnisari Sep 15, 2023
8bd5c66
fix: fix json interface for Write API (#96)
jpadilla Sep 20, 2023
c3a581f
fix: use snake case (#99)
jpadilla Sep 26, 2023
dba5895
Re-order tuple-related fields (#97)
jpadilla Sep 29, 2023
8def830
fix: set condition name to be `condition_name` in json
rhamzeh Oct 3, 2023
e4bc967
fix: reduce stutter in `RelationshipCondition` (#103)
jpadilla Oct 13, 2023
6484aa0
chore: run workflow against base branch instead of always main (#105)
rhamzeh Oct 13, 2023
0fc8019
fix!: mark required fields as required (#104)
rhamzeh Oct 13, 2023
7c84e50
feat: increase contextual tuple limit to 20 (#92)
rhamzeh Aug 28, 2023
105d9e7
fix: add missing newline in Read API (#93)
miparnisari Aug 29, 2023
7278f42
chore(deps): bump golang.org/x/net from 0.12.0 to 0.17.0 in /proto (#…
dependabot[bot] Oct 12, 2023
9e3d648
rebuild
jpadilla Oct 13, 2023
fb9e0a8
Merge branch 'main' into feat/abac
jpadilla Oct 13, 2023
c85ea63
Merge branch 'main' into feat/abac
rhamzeh Nov 9, 2023
7161d70
refactor(write): normalize `deletes` field to TupleKeyWithoutConditio…
jon-whit Nov 22, 2023
7f9be45
refactor: modify WriteRequestWrites body (#117)
jon-whit Nov 22, 2023
abc04f2
docs: update docs for abac (#118)
miparnisari Nov 30, 2023
4281354
Merge branch 'main' into feat/abac
jon-whit Dec 1, 2023
79c1ad3
fix: mark more fields as required - add ComputedUserset (#109)
rhamzeh Dec 1, 2023
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
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/docs/openapiv2/apidocs.swagger.json linguist-generated=true
*.pb.go linguist-generated=true
*.pb.*.go linguist-generated=true
go.sum linguist-generated=true
buf.lock linguist-generated=true
3 changes: 2 additions & 1 deletion .github/workflows/review.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ on:
pull_request:
branches:
- main
- feat/abac

permissions:
contents: read
Expand All @@ -21,7 +22,7 @@ jobs:
- uses: bufbuild/buf-breaking-action@a074e988ee34efcd4927079e79c611f428354c01 # v1.1.3
with:
# The 'main' branch of the GitHub repository that defines the module.
against: "https://github.com/${GITHUB_REPOSITORY}.git#branch=main"
against: "https://github.com/${GITHUB_REPOSITORY}.git#branch=${GITHUB_BASE_REF}"
- run: buf format -d --exit-code

diff-openapi:
Expand Down
403 changes: 356 additions & 47 deletions docs/openapiv2/apidocs.swagger.json

Large diffs are not rendered by default.

64 changes: 61 additions & 3 deletions openfga/v1/authzmodel.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@ message AuthorizationModel {

repeated TypeDefinition type_definitions = 3 [
json_name = "type_definitions",
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "[{\"type\": \"user\"}, {\"type\":\"document\",\"relations\":{\"reader\":{\"union\":{\"child\":[{\"this\":{}},{\"computedUserset\":{\"object\":\"\",\"relation\":\"writer\"}}]}},\"writer\":{\"this\":{}}},\"metadata\":{\"relations\":{\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\"}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\"}]}}}}]"}
];

map<string, Condition> conditions = 4 [
json_name = "conditions",
(validate.rules).map.max_pairs = 25,
(validate.rules).map.keys.string = {pattern: "^[^:#@\\s]{1,50}$"}
];
}

message TypeDefinition {
Expand Down Expand Up @@ -81,12 +88,15 @@ message RelationReference {

Wildcard wildcard = 3;
}

// The name of a condition that is enforced over the allowed relation.
string condition = 4;
}

message Wildcard {}

message Usersets {
repeated Userset child = 1;
repeated Userset child = 1 [(google.api.field_behavior) = REQUIRED];
}

message Difference {
Expand Down Expand Up @@ -123,6 +133,54 @@ message ObjectRelation {

message TupleToUserset {
// The target object/relation
ObjectRelation tupleset = 1;
ObjectRelation computed_userset = 2;
ObjectRelation tupleset = 1 [(google.api.field_behavior) = REQUIRED];
ObjectRelation computed_userset = 2 [(google.api.field_behavior) = REQUIRED];
}

message Condition {
// A unique name for the condition
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(validate.rules).string = {pattern: "^[^:#@\\s]{1,50}$"}
];

// A Google CEL expression, expressed as a string.
string expression = 2 [
(google.api.field_behavior) = REQUIRED,
(validate.rules).string = {max_bytes: 512}
];

// A map of parameter names to the parameter's defined type reference.
map<string, ConditionParamTypeRef> parameters = 3 [
(validate.rules).map.max_pairs = 25,
(validate.rules).map.keys.string = {pattern: "^[^:#@\\s]{1,50}$"}
];
}

message ConditionParamTypeRef {
enum TypeName {
TYPE_NAME_UNSPECIFIED = 0;
TYPE_NAME_ANY = 1;
TYPE_NAME_BOOL = 2;
TYPE_NAME_STRING = 3;
TYPE_NAME_INT = 4;
TYPE_NAME_UINT = 5;
TYPE_NAME_DOUBLE = 6;
TYPE_NAME_DURATION = 7;
TYPE_NAME_TIMESTAMP = 8;
TYPE_NAME_MAP = 9;
TYPE_NAME_LIST = 10;
TYPE_NAME_IPADDRESS = 11;
}

TypeName type_name = 1 [
json_name = "type_name",
(google.api.field_behavior) = REQUIRED,
(validate.rules).enum.defined_only = true
];

repeated ConditionParamTypeRef generic_types = 2 [
json_name = "generic_types",
(validate.rules).repeated.max_items = 5
];
}
140 changes: 99 additions & 41 deletions openfga/v1/openfga.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package openfga.v1;

import "google/api/field_behavior.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
Expand All @@ -25,8 +26,47 @@
];
}

message TupleKey {
string object = 1 [
message RelationshipCondition {
// A reference (by name) of the relationship condition defined in the authorization model.
string name = 1 [
(validate.rules).string = {pattern: "^[^\\s]{2,256}$"},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
max_length: 256,
example: "\"condition1\""
}
];

// Additional context/data to persist along with the condition.
// The keys must match the parameters defined by the condition, and the value types must
// match the parameter type definitions.
google.protobuf.Struct context = 2 [(google.api.field_behavior) = REQUIRED];
}

message TupleKeyWithoutCondition {
string user = 1 [
(google.api.field_behavior) = REQUIRED,
(validate.rules).string = {max_bytes: 512},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
max_length: 512,
example: "\"user:anne\""
}
];

string relation = 2 [
(google.api.field_behavior) = REQUIRED,
(validate.rules).string = {
pattern: "^[^:#@\\s]{1,50}$",
ignore_empty: true
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
max_length: 50,
example: "\"reader\""
}
];

string object = 3 [
(google.api.field_behavior) = REQUIRED,
(validate.rules).string = {
pattern: "^[^\\s]{2,256}$",
ignore_empty: true
Expand All @@ -36,7 +76,20 @@
example: "\"document:2021-budget\""
}
];
}

message TupleKey {
string user = 1 [

Check failure on line 82 in openfga/v1/openfga.proto

View workflow job for this annotation

GitHub Actions / build

Field "1" with name "user" on message "TupleKey" changed option "json_name" from "object" to "user".

Check failure on line 82 in openfga/v1/openfga.proto

View workflow job for this annotation

GitHub Actions / build

Field "1" on message "TupleKey" changed name from "object" to "user".
(google.api.field_behavior) = REQUIRED,
(validate.rules).string = {max_bytes: 512},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
max_length: 512,
example: "\"user:anne\""
}
];

string relation = 2 [
(google.api.field_behavior) = REQUIRED,
(validate.rules).string = {
pattern: "^[^:#@\\s]{1,50}$",
ignore_empty: true
Expand All @@ -46,18 +99,25 @@
example: "\"reader\""
}
];
string user = 3 [
(validate.rules).string = {max_bytes: 512},

string object = 3 [

Check failure on line 103 in openfga/v1/openfga.proto

View workflow job for this annotation

GitHub Actions / build

Field "3" with name "object" on message "TupleKey" changed option "json_name" from "user" to "object".

Check failure on line 103 in openfga/v1/openfga.proto

View workflow job for this annotation

GitHub Actions / build

Field "3" on message "TupleKey" changed name from "user" to "object".
(google.api.field_behavior) = REQUIRED,
(validate.rules).string = {
pattern: "^[^\\s]{2,256}$",
ignore_empty: true
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
max_length: 512,
example: "\"user:anne\""
max_length: 256,
example: "\"document:2021-budget\""
}
];

RelationshipCondition condition = 4;
}

message Tuple {
TupleKey key = 1;
google.protobuf.Timestamp timestamp = 2;
TupleKey key = 1 [(google.api.field_behavior) = REQUIRED];
google.protobuf.Timestamp timestamp = 2 [(google.api.field_behavior) = REQUIRED];
}

message TupleKeys {
Expand Down Expand Up @@ -96,29 +156,29 @@
}

message Nodes {
repeated Node nodes = 1;
repeated Node nodes = 1 [(google.api.field_behavior) = REQUIRED];
}

message Users {
repeated string users = 1;
repeated string users = 1 [(google.api.field_behavior) = REQUIRED];
}

message Computed {
string userset = 1;
string userset = 1 [(google.api.field_behavior) = REQUIRED];
}

message TupleToUserset {
string tupleset = 1;
repeated Computed computed = 2;
string tupleset = 1 [(google.api.field_behavior) = REQUIRED];
repeated Computed computed = 2 [(google.api.field_behavior) = REQUIRED];
}

message Difference {
Node base = 1;
Node subtract = 2;
Node base = 1 [(google.api.field_behavior) = REQUIRED];
Node subtract = 2 [(google.api.field_behavior) = REQUIRED];
}

message Node {
string name = 1;
string name = 1 [(google.api.field_behavior) = REQUIRED];
oneof value {
Leaf leaf = 2;
Difference difference = 5;
Expand All @@ -130,39 +190,37 @@
Node root = 1;
}

message Assertion {
TupleKey tuple_key = 1 [
(validate.rules).message.required = true,
json_name = "tuple_key",
(google.api.field_behavior) = REQUIRED
];

bool expectation = 2 [
json_name = "expectation",
(google.api.field_behavior) = REQUIRED
];
}

message Assertions {
repeated Assertion assertions = 1;
}

// buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX
enum TupleOperation {
TUPLE_OPERATION_WRITE = 0;
TUPLE_OPERATION_DELETE = 1;
}

message TupleChange {
TupleKey tuple_key = 1 [json_name = "tuple_key"];
TupleOperation operation = 2 [(validate.rules).enum.defined_only = true];
google.protobuf.Timestamp timestamp = 3;
TupleKey tuple_key = 1 [
json_name = "tuple_key",
(google.api.field_behavior) = REQUIRED
];
TupleOperation operation = 2 [
(validate.rules).enum.defined_only = true,
(google.api.field_behavior) = REQUIRED
];
google.protobuf.Timestamp timestamp = 3 [(google.api.field_behavior) = REQUIRED];
}

message Store {
string id = 1;
string name = 2;
google.protobuf.Timestamp created_at = 3 [json_name = "created_at"];
google.protobuf.Timestamp updated_at = 4 [json_name = "updated_at"];
google.protobuf.Timestamp deleted_at = 5 [json_name = "deleted_at"];
string id = 1 [(google.api.field_behavior) = REQUIRED];
string name = 2 [(google.api.field_behavior) = REQUIRED];
google.protobuf.Timestamp created_at = 3 [
json_name = "created_at",
(google.api.field_behavior) = REQUIRED
];
google.protobuf.Timestamp updated_at = 4 [
json_name = "updated_at",
(google.api.field_behavior) = REQUIRED
];
google.protobuf.Timestamp deleted_at = 5 [
json_name = "deleted_at",
(google.api.field_behavior) = REQUIRED
];
}
Loading
Loading