diff --git a/proto/agynio/api/egress/v1/egress.proto b/proto/agynio/api/egress/v1/egress.proto new file mode 100644 index 0000000..24b34d6 --- /dev/null +++ b/proto/agynio/api/egress/v1/egress.proto @@ -0,0 +1,186 @@ +syntax = "proto3"; + +package agynio.api.egress.v1; + +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/agynio/api/gen/agynio/api/egress/v1;egressv1"; + +// EgressRulesService manages egress rules and agent attachments. +service EgressRulesService { + // --- Egress Rules --- + rpc CreateEgressRule(CreateEgressRuleRequest) returns (CreateEgressRuleResponse); + rpc GetEgressRule(GetEgressRuleRequest) returns (GetEgressRuleResponse); + rpc ListEgressRules(ListEgressRulesRequest) returns (ListEgressRulesResponse); + rpc UpdateEgressRule(UpdateEgressRuleRequest) returns (UpdateEgressRuleResponse); + rpc DeleteEgressRule(DeleteEgressRuleRequest) returns (DeleteEgressRuleResponse); + + // --- Egress Rule Attachments --- + rpc CreateEgressRuleAttachment(CreateEgressRuleAttachmentRequest) returns (CreateEgressRuleAttachmentResponse); + rpc DeleteEgressRuleAttachment(DeleteEgressRuleAttachmentRequest) returns (DeleteEgressRuleAttachmentResponse); + rpc ListEgressRuleAttachments(ListEgressRuleAttachmentsRequest) returns (ListEgressRuleAttachmentsResponse); + + // --- Internal --- + rpc ListEgressRulesByAgent(ListEgressRulesByAgentRequest) returns (ListEgressRulesByAgentResponse); + rpc CountRulesReferencingSecret(CountRulesReferencingSecretRequest) returns (CountRulesReferencingSecretResponse); +} + +// Metadata shared by egress resources. +message EntityMeta { + string id = 1; + google.protobuf.Timestamp created_at = 2; + google.protobuf.Timestamp updated_at = 3; +} + +// Effect to apply to a request matching an egress rule. +enum EgressRuleAction { + EGRESS_RULE_ACTION_UNSPECIFIED = 0; + EGRESS_RULE_ACTION_ALLOW = 1; + EGRESS_RULE_ACTION_DENY = 2; +} + +// Authentication scheme used when emitting an injected header. +enum HeaderAuthScheme { + HEADER_AUTH_SCHEME_UNSPECIFIED = 0; + HEADER_AUTH_SCHEME_BEARER = 1; + HEADER_AUTH_SCHEME_BASIC = 2; +} + +// Request attributes matched by an egress rule. +message EgressRuleMatcher { + // Hostname pattern. Examples: "api.github.com", "*.github.com". + string domain_pattern = 1; + // Destination ports to intercept. Empty means service default ports. + repeated int32 ports = 2; + // HTTP methods the rule applies to. Empty means any method. + repeated string methods = 3; + // Glob over the request path. Empty means any path. + string path_pattern = 4; +} + +// Header credential injected by the egress gateway. +message EgressRuleHeader { + string name = 1; + HeaderAuthScheme scheme = 2; + oneof credential { + string value = 3; + string secret_id = 4; + } +} + +// Behavior to apply to requests matching an egress rule. +message EgressRuleEffect { + optional EgressRuleAction action = 1; + repeated EgressRuleHeader inject = 2; +} + +// Rule mediating outbound HTTP/HTTPS traffic from agent workloads. +message EgressRule { + EntityMeta meta = 1; + string organization_id = 2; + string name = 3; + string description = 4; + EgressRuleMatcher matcher = 5; + EgressRuleEffect effect = 6; +} + +// Attachment binding an egress rule to an agent. +message EgressRuleAttachment { + EntityMeta meta = 1; + string rule_id = 2; + string agent_id = 3; +} + +message CreateEgressRuleRequest { + string organization_id = 1; + string name = 2; + string description = 3; + EgressRuleMatcher matcher = 4; + EgressRuleEffect effect = 5; +} + +message CreateEgressRuleResponse { + EgressRule egress_rule = 1; +} + +message GetEgressRuleRequest { + string id = 1; +} + +message GetEgressRuleResponse { + EgressRule egress_rule = 1; +} + +message ListEgressRulesRequest { + string organization_id = 1; + int32 page_size = 2; + string page_token = 3; +} + +message ListEgressRulesResponse { + repeated EgressRule egress_rules = 1; + string next_page_token = 2; +} + +message UpdateEgressRuleRequest { + string id = 1; + optional string name = 2; + optional string description = 3; + optional EgressRuleMatcher matcher = 4; + optional EgressRuleEffect effect = 5; +} + +message UpdateEgressRuleResponse { + EgressRule egress_rule = 1; +} + +message DeleteEgressRuleRequest { + string id = 1; +} + +message DeleteEgressRuleResponse {} + +message CreateEgressRuleAttachmentRequest { + string rule_id = 1; + string agent_id = 2; +} + +message CreateEgressRuleAttachmentResponse { + EgressRuleAttachment egress_rule_attachment = 1; +} + +message DeleteEgressRuleAttachmentRequest { + string id = 1; +} + +message DeleteEgressRuleAttachmentResponse {} + +message ListEgressRuleAttachmentsRequest { + string organization_id = 1; + optional string rule_id = 2; + optional string agent_id = 3; + int32 page_size = 4; + string page_token = 5; +} + +message ListEgressRuleAttachmentsResponse { + repeated EgressRuleAttachment egress_rule_attachments = 1; + string next_page_token = 2; +} + +message ListEgressRulesByAgentRequest { + string agent_id = 1; +} + +message ListEgressRulesByAgentResponse { + repeated EgressRule egress_rules = 1; +} + +message CountRulesReferencingSecretRequest { + string secret_id = 1; +} + +message CountRulesReferencingSecretResponse { + int32 count = 1; + repeated string egress_rule_ids = 2; +} diff --git a/proto/agynio/api/gateway/v1/egress.proto b/proto/agynio/api/gateway/v1/egress.proto new file mode 100644 index 0000000..41ee293 --- /dev/null +++ b/proto/agynio/api/gateway/v1/egress.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +package agynio.api.gateway.v1; + +import "agynio/api/egress/v1/egress.proto"; + +option go_package = "github.com/agynio/api/gen/agynio/api/gateway/v1;gatewayv1"; + +service EgressRulesGateway { + // --- Egress Rules --- + rpc CreateEgressRule(agynio.api.egress.v1.CreateEgressRuleRequest) returns (agynio.api.egress.v1.CreateEgressRuleResponse); + rpc GetEgressRule(agynio.api.egress.v1.GetEgressRuleRequest) returns (agynio.api.egress.v1.GetEgressRuleResponse); + rpc ListEgressRules(agynio.api.egress.v1.ListEgressRulesRequest) returns (agynio.api.egress.v1.ListEgressRulesResponse); + rpc UpdateEgressRule(agynio.api.egress.v1.UpdateEgressRuleRequest) returns (agynio.api.egress.v1.UpdateEgressRuleResponse); + rpc DeleteEgressRule(agynio.api.egress.v1.DeleteEgressRuleRequest) returns (agynio.api.egress.v1.DeleteEgressRuleResponse); + + // --- Egress Rule Attachments --- + rpc CreateEgressRuleAttachment(agynio.api.egress.v1.CreateEgressRuleAttachmentRequest) returns (agynio.api.egress.v1.CreateEgressRuleAttachmentResponse); + rpc DeleteEgressRuleAttachment(agynio.api.egress.v1.DeleteEgressRuleAttachmentRequest) returns (agynio.api.egress.v1.DeleteEgressRuleAttachmentResponse); + rpc ListEgressRuleAttachments(agynio.api.egress.v1.ListEgressRuleAttachmentsRequest) returns (agynio.api.egress.v1.ListEgressRuleAttachmentsResponse); +} diff --git a/proto/agynio/api/runner/v1/runner.proto b/proto/agynio/api/runner/v1/runner.proto index 993798d..e923689 100644 --- a/proto/agynio/api/runner/v1/runner.proto +++ b/proto/agynio/api/runner/v1/runner.proto @@ -102,6 +102,12 @@ message VolumeMount { bool read_only = 3; } +// InlineFileMount references a file supplied through +// StartWorkloadRequest.inline_files. +message InlineFileMount { + string path = 1; +} + // ContainerSpec describes a single container within a workload. message ContainerSpec { string image = 1; @@ -120,6 +126,9 @@ message ContainerSpec { // Example values: "privileged", "dind". repeated string required_capabilities = 8; + // Inline files mounted read-only into this container. + repeated InlineFileMount inline_file_mounts = 9; + // Backend-specific optional properties. map additional_properties = 100; } @@ -165,6 +174,10 @@ message StartWorkloadRequest { // (e.g., "privileged", "dind"). repeated string capabilities = 9; + // Small files keyed by absolute container path and mounted read-only into + // containers that list the path in inline_file_mounts. + map inline_files = 10; + map additional_properties = 100; } diff --git a/proto/agynio/api/secrets/v1/secrets.proto b/proto/agynio/api/secrets/v1/secrets.proto index 33211ee..e41e1eb 100644 --- a/proto/agynio/api/secrets/v1/secrets.proto +++ b/proto/agynio/api/secrets/v1/secrets.proto @@ -30,6 +30,8 @@ service SecretsService { // --- Resolution --- // Resolve a secret to its actual value by fetching from the external provider. rpc ResolveSecret(ResolveSecretRequest) returns (ResolveSecretResponse); + // Verify that a secret exists without resolving its value. + rpc ResolveSecretExists(ResolveSecretExistsRequest) returns (ResolveSecretExistsResponse); // --- Image Pull Secrets --- rpc CreateImagePullSecret(CreateImagePullSecretRequest) returns (CreateImagePullSecretResponse); @@ -218,6 +220,15 @@ message ResolveSecretResponse { string value = 1; // The resolved secret value from the external provider } +message ResolveSecretExistsRequest { + string id = 1; // UUID of the Secret to check +} + +message ResolveSecretExistsResponse { + bool exists = 1; + string organization_id = 2; +} + // =========================================================================== // Image Pull Secret // ===========================================================================