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
14 changes: 7 additions & 7 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ plugins {
id("com.google.protobuf") version "0.9.5"
id("com.palantir.git-version") version "4.2.0"
id("org.jreleaser") version "1.21.0"
id("com.gradleup.shadow") version "9.2.2"
id("com.gradleup.shadow") version "9.3.0"
}

val gitVersion: groovy.lang.Closure<String> by extra
Expand Down Expand Up @@ -44,7 +44,7 @@ java {

protobuf {
protoc {
artifact = "com.google.protobuf:protoc:4.33.1"
artifact = "com.google.protobuf:protoc:4.33.2"
}

plugins {
Expand All @@ -63,14 +63,14 @@ protobuf {
}

dependencies {
implementation("com.google.protobuf:protobuf-java:4.33.1")
implementation("com.google.protobuf:protobuf-java-util:4.33.1")
implementation("com.google.protobuf:protobuf-java:4.33.2")
implementation("com.google.protobuf:protobuf-java-util:4.33.2")
implementation("io.grpc:grpc-protobuf:1.77.0")
implementation("io.grpc:grpc-stub:1.77.0")
implementation("io.grpc:grpc-netty-shaded:1.77.0")
implementation("io.netty:netty-tcnative-boringssl-static:2.0.74.Final")
implementation("org.testcontainers:testcontainers:2.0.2")
implementation("build.buf:protovalidate:1.0.1")
implementation("build.buf:protovalidate:1.1.0")
implementation("commons-io:commons-io:2.21.0")
implementation("com.google.code.gson:gson:2.13.2")
implementation("io.github.resilience4j:resilience4j-circuitbreaker:2.3.0")
Expand All @@ -79,8 +79,8 @@ dependencies {
testImplementation("org.testcontainers:junit-jupiter:1.21.3")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.14.1")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
testImplementation("ch.qos.logback:logback-core:1.5.21")
testImplementation("ch.qos.logback:logback-classic:1.5.21")
testImplementation("ch.qos.logback:logback-core:1.5.22")
testImplementation("ch.qos.logback:logback-classic:1.5.22")
testImplementation("com.fasterxml.jackson.core:jackson-core:2.20.1")
testImplementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.20.1")
}
Expand Down
283 changes: 283 additions & 0 deletions src/main/proto/authzen/authorization/v1/evaluation.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
// Copyright 2021-2025 Zenauth Ltd.
// SPDX-License-Identifier: Apache-2.0

syntax = "proto3";

package authzen.authorization.v1;

import "buf/validate/validate.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/struct.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

option csharp_namespace = "Cerbos.AuthZen.Api.V1.Authorization";
option go_package = "github.com/cerbos/cerbos/api/genpb/authzen/authorization/v1;authorizationv1";
option java_package = "dev.cerbos.authzen.api.v1.authorization";

// Subject represents the principal requesting access
message Subject {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "Subject requesting access"}
};

string type = 1 [
(buf.validate.field).string = {min_len: 1},
(buf.validate.field).required = true,
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Type of the subject."
example: "\"user\""
}
];

string id = 2 [
(buf.validate.field).string = {min_len: 1},
(buf.validate.field).required = true,
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Unique identifier for the subject."
example: "\"alice@acmecorp.com\""
}
];

map<string, google.protobuf.Value> properties = 3 [
(buf.validate.field).map.keys = {
string: {min_len: 1}
},
(buf.validate.field).map.values.required = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Key-value pairs of contextual data about this subject that should be used during policy evaluation."
example: "{\"department\": \"engineering\"}"
}
];
}

// Resource represents the target of the access request
message Resource {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "Resource being accessed"}
};

string type = 1 [
(buf.validate.field).string = {min_len: 1},
(buf.validate.field).required = true,
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Type of the resource."
example: "\"account\""
}
];

string id = 2 [
(buf.validate.field).string = {min_len: 1},
(buf.validate.field).required = true,
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Unique identifier for the resource."
example: "\"123\""
}
];

map<string, google.protobuf.Value> properties = 3 [
(buf.validate.field).map.keys = {
string: {min_len: 1}
},
(buf.validate.field).map.values.required = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Key-value pairs of contextual data about this resource that should be used during policy evaluation."
example: "{\"owner\": \"bugs_bunny\"}"
}
];
}

// Action represents the operation being performed
message Action {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "Action being performed"}
};

string name = 1 [
(buf.validate.field).string = {min_len: 1},
(buf.validate.field).required = true,
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Name of the action being performed."
example: "\"can_read\""
}
];

map<string, google.protobuf.Value> properties = 2 [
(buf.validate.field).map.keys = {
string: {min_len: 1}
},
(buf.validate.field).map.values.required = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Key-value pairs of contextual data about this action that should be used during policy evaluation."
example: "{\"method\": \"GET\"}"
}
];
}

// AuthZEN evaluation request message
message AccessEvaluationRequest {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "AuthZEN access evaluation request"}
};

Subject subject = 1 [
(buf.validate.field).required = true,
(google.api.field_behavior) = REQUIRED
];

Resource resource = 2 [
(buf.validate.field).required = true,
(google.api.field_behavior) = REQUIRED
];

Action action = 3 [
(buf.validate.field).required = true,
(google.api.field_behavior) = REQUIRED
];

map<string, google.protobuf.Value> context = 4 [
(buf.validate.field).map.keys = {
string: {min_len: 1}
},
(buf.validate.field).map.values.required = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Key-value pairs of environmental/contextual data that should be used during policy evaluation."
example: "{\"time\": \"2023-01-01T00:00:00Z\"}"
}
];
}

// AuthZEN evaluation response message
message AccessEvaluationResponse {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "AuthZEN access evaluation response"}
};

optional bool decision = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Whether to allow or deny the operation."
example: "true"
}];

map<string, google.protobuf.Value> context = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Additional context about evaluation"
example: "{\"time\": \"2023-01-01T00:00:00Z\"}"
}];
}

// AuthZEN evaluations request message
message AccessEvaluationBatchRequest {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "AuthZEN access evaluations request"}
};

Subject subject = 1;
Resource resource = 2;
Action action = 3;

map<string, google.protobuf.Value> context = 4 [
(buf.validate.field).map.keys = {
string: {min_len: 1}
},
(buf.validate.field).map.values.required = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Key-value pairs of environmental/contextual data that should be used during policy evaluation."
example: "{\"time\": \"2023-01-01T00:00:00Z\"}"
}
];

message Evaluation {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "An evaluation"}
};

Subject subject = 1;
Resource resource = 2;
Action action = 3;

map<string, google.protobuf.Value> context = 4 [
(buf.validate.field).map.keys = {
string: {min_len: 1}
},
(buf.validate.field).map.values.required = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Key-value pairs of environmental/contextual data that should be used during policy evaluation."
example: "{\"time\": \"2023-01-01T00:00:00Z\"}"
}
];
}

repeated Evaluation evaluations = 5 [(buf.validate.field).repeated.min_items = 1];

AccessEvaluationsOptions options = 6;

option (buf.validate.message).cel = {
id: "actions"
message: "either the default action must be set or all evaluations must have an action"
expression: "has(this.action) || this.evaluations.all(x, has(x.action))"
};

option (buf.validate.message).cel = {
id: "subjects"
message: "either the default subject must be set or all evaluations must have a subject"
expression: "has(this.subject) || this.evaluations.all(x, has(x.subject))"
};
option (buf.validate.message).cel = {
id: "resources"
message: "either the default resource must be set or all evaluations must have a resource"
expression: "has(this.resource) || this.evaluations.all(x, has(x.resource))"
};
option (buf.validate.message).cel = {
id: "contexts"
message: "either the default context must be set or all evaluations must have a context"
expression: "has(this.context) || this.evaluations.all(x, has(x.context))"
};
}

// AuthZEN evaluations response message
message AccessEvaluationBatchResponse {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "AuthZEN access evaluations response"}
};
repeated AccessEvaluationResponse evaluations = 1;
}

message MetadataRequest {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "AuthZEN Policy Decision Point Metadata request"}
};
}

message MetadataResponse {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "AuthZEN Policy Decision Point Metadata"}
};
string policy_decision_point = 1 [json_name = "policy_decision_point"];
string access_evaluation_endpoint = 2 [json_name = "access_evaluation_endpoint"];
string access_evaluations_endpoint = 3 [json_name = "access_evaluations_endpoint"];
}

// AccessEvaluationsOptions captures optional execution controls for batch requests.
message AccessEvaluationsOptions {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {description: "Optional execution controls for AuthZEN batch requests"}
};
// Controls how the PDP should execute the evaluations array.
string evaluations_semantic = 1 [
(buf.validate.field).string = {
in: [
"",
"execute_all",
"deny_on_first_deny",
"permit_on_first_permit"
]
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Evaluation semantic to apply. Defaults to \"execute_all\" when unset."
example: "\"deny_on_first_deny\""
}
];
}
65 changes: 65 additions & 0 deletions src/main/proto/authzen/authorization/v1/svc.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2021-2025 Zenauth Ltd.
// SPDX-License-Identifier: Apache-2.0

syntax = "proto3";

package authzen.authorization.v1;

import "authzen/authorization/v1/evaluation.proto";
import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

option csharp_namespace = "Cerbos.AuthZen.Api.V1.Authorization";
option go_package = "github.com/cerbos/cerbos/api/genpb/authzen/authorization/v1;authorizationv1";
option java_package = "dev.cerbos.authzen.api.v1.authorization";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "AuthZEN Authorization API"
version: "v1"
description: "OpenID AuthZEN Authorization API for access evaluations"
contact: {
name: "Cerbos"
url: "https://cerbos.dev"
}
}
schemes: HTTPS
consumes: "application/json"
produces: "application/json"
};

// AuthZEN Authorization Service
service AuthorizationService {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_tag) = {description: "AuthZEN Authorization Service for access evaluations"};

// Metadata returns the Policy Decision Point metadata
rpc Metadata(MetadataRequest) returns (MetadataResponse) {
option (google.api.http) = {get: "/.well-known/authzen-configuration"};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Get Policy Decision Point metadata"
description: "Returns the AuthZEN Policy Decision Point metadata including endpoint URLs"
};
}

// Evaluate performs an access evaluation
rpc AccessEvaluation(AccessEvaluationRequest) returns (AccessEvaluationResponse) {
option (google.api.http) = {
post: "/access/v1/evaluation"
body: "*"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Evaluate access request"
description: "Evaluate whether a subject can perform an action on a resource according to AuthZEN specification"
};
}
// Evaluate performs an access evaluation
rpc AccessEvaluationBatch(AccessEvaluationBatchRequest) returns (AccessEvaluationBatchResponse) {
option (google.api.http) = {
post: "/access/v1/evaluations"
body: "*"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Batch evaluate access request"
description: "Batch evaluate whether a subject can perform an action on a resource according to AuthZEN specification"
};
}
}
Loading
Loading