diff --git a/cre/capabilities/networking/confidentialhttp/v1alpha/client.proto b/cre/capabilities/networking/confidentialhttp/v1alpha/client.proto index 9feec6f0..ec01a216 100644 --- a/cre/capabilities/networking/confidentialhttp/v1alpha/client.proto +++ b/cre/capabilities/networking/confidentialhttp/v1alpha/client.proto @@ -60,6 +60,151 @@ message HTTPResponse { message ConfidentialHTTPRequest { repeated SecretIdentifier vault_don_secrets = 1; HTTPRequest request = 2; + // auth, when set, instructs the enclave to sign the outbound request using + // the specified method. Every secret_name referenced inside AuthConfig must + // also appear in vault_don_secrets (enforced by the capability validator). + // When auth is nil, the request is sent with only the headers/body the + // caller provided — preserving the legacy "{{.SECRET_NAME}}" header-template + // behavior. + optional AuthConfig auth = 3; +} + +// AuthConfig selects one of the supported request-signing methods. +// Each variant carries the method-specific parameters and references +// the names of the Vault-DON secrets it needs. +message AuthConfig { + oneof method { + ApiKeyAuth api_key = 1; + BasicAuth basic = 2; + BearerAuth bearer = 3; + HmacAuth hmac = 4; + OAuth2Auth oauth2 = 5; + } +} + +// ApiKeyAuth attaches a secret value to a chosen header. +// Renders as: : +// Example (header_name="x-api-key", secret_name="coingecko", value_prefix=""): +// x-api-key: +message ApiKeyAuth { + string header_name = 1; // required, e.g. "x-api-key", "Authorization" + string secret_name = 2; // required; key into ConfidentialHTTPRequest.vault_don_secrets + string value_prefix = 3; // optional, e.g. "ApiKey ", "Token " +} + +// BasicAuth renders: Authorization: Basic base64(username ":" password). +message BasicAuth { + string username_secret_name = 1; // required + string password_secret_name = 2; // required +} + +// BearerAuth attaches a pre-issued long-lived token. +// Default behavior: Authorization: Bearer +// header_name and value_prefix allow rare overrides (e.g. GitHub's +// "Authorization: token "). +message BearerAuth { + string token_secret_name = 1; // required + string header_name = 2; // optional override, default "Authorization" + string value_prefix = 3; // optional override, default "Bearer " +} + +// HmacAuth groups all HMAC-family signing variants. +message HmacAuth { + oneof variant { + HmacSha256 sha256 = 1; + AwsSigV4 aws_sig_v4 = 2; + HmacCustom custom = 3; + } +} + +// HmacSha256 implements a generic canonical-string HMAC-SHA256 signature. +// Canonical string: method "\n" url "\n" sha256(body) "\n" timestamp +// Signature is attached via signature_header, timestamp via timestamp_header. +message HmacSha256 { + string secret_name = 1; // required shared secret + string signature_header = 2; // default "X-Signature" + string timestamp_header = 3; // default "X-Timestamp" + bool include_query = 4; // if true, include the query string in the canonical url + string encoding = 5; // "hex" (default) or "base64" +} + +// AwsSigV4 implements AWS Signature Version 4. +// Uses github.com/aws/aws-sdk-go-v2/aws/signer/v4 under the hood. +message AwsSigV4 { + string access_key_id_secret_name = 1; // required + string secret_access_key_secret_name = 2; // required + string session_token_secret_name = 3; // optional (for STS creds) + string region = 4; // required, e.g. "us-east-1" + string service = 5; // required, e.g. "execute-api", "s3" + // Signed headers (comma-separated lowercase). Optional; defaults to + // "host;x-amz-date" plus "x-amz-security-token" if session_token_secret_name + // is set. + repeated string signed_headers = 6; + // If true, uses X-Amz-Content-Sha256: UNSIGNED-PAYLOAD (useful for large S3 + // uploads). Default false. + bool unsigned_payload = 7; +} + +// HmacCustom lets workflow authors specify the canonical string via a +// Go text/template string. Available template vars: +// {{.method}} {{.url}} {{.path}} {{.query}} {{.body}} {{.body_sha256}} +// {{.timestamp}} {{.nonce}} {{header "X-Foo"}} +message HmacCustom { + string secret_name = 1; // required + string canonical_template = 2; // required + enum Hash { + HASH_SHA256 = 0; + HASH_SHA512 = 1; + } + Hash hash = 3; + string signature_header = 4; // required + string signature_prefix = 5; // e.g. "HMAC-SHA256 " + string timestamp_header = 6; // optional; if set, timestamp header injected + string nonce_header = 7; // optional; if set, random nonce header injected + string encoding = 8; // "hex" (default) or "base64" +} + +// OAuth2Auth groups headless OAuth 2.0 flows. +// Interactive flows (Authorization Code, PKCE, Device Code) are NOT supported — +// they require browser consent that a headless TEE cannot perform. +message OAuth2Auth { + oneof variant { + OAuth2ClientCredentials client_credentials = 1; + OAuth2RefreshToken refresh_token = 2; + } +} + +// OAuth2ClientCredentials: machine-to-machine grant. +// The enclave POSTs to token_url with client_id/client_secret, caches the +// resulting access_token per (workflow_owner, token_url, client_id, scopes), +// and attaches "Authorization: Bearer " to the outbound request. +message OAuth2ClientCredentials { + string token_url = 1; // required, must be https:// + string client_id_secret_name = 2; // required + string client_secret_secret_name = 3; // required + repeated string scopes = 4; // optional + string audience = 5; // optional (Auth0-style) + // "basic_auth" (default) or "request_body" — where to put client creds + // on the token request. + string client_auth_method = 6; + // Extra form params to send with the token request. + map extra_params = 7; +} + +// OAuth2RefreshToken: the workflow stores a long-lived refresh_token in Vault +// (obtained out-of-band during an interactive consent). The enclave exchanges +// it for an access_token on cache miss. +// +// Important: if the IdP rotates refresh tokens on each exchange, the enclave +// cannot persist the new refresh_token back to Vault. Disable refresh-token +// rotation at the IdP, or prefer client_credentials where possible. +message OAuth2RefreshToken { + string token_url = 1; // required, must be https:// + string refresh_token_secret_name = 2; // required + string client_id_secret_name = 3; // optional (some IdPs require) + string client_secret_secret_name = 4; // optional (some IdPs require) + repeated string scopes = 5; // optional + map extra_params = 6; } service Client { diff --git a/cre/go/installer/pkg/embedded_gen.go b/cre/go/installer/pkg/embedded_gen.go index c52246cd..8808421e 100755 --- a/cre/go/installer/pkg/embedded_gen.go +++ b/cre/go/installer/pkg/embedded_gen.go @@ -711,6 +711,151 @@ message HTTPResponse { message ConfidentialHTTPRequest { repeated SecretIdentifier vault_don_secrets = 1; HTTPRequest request = 2; + // auth, when set, instructs the enclave to sign the outbound request using + // the specified method. Every secret_name referenced inside AuthConfig must + // also appear in vault_don_secrets (enforced by the capability validator). + // When auth is nil, the request is sent with only the headers/body the + // caller provided — preserving the legacy "{{.SECRET_NAME}}" header-template + // behavior. + optional AuthConfig auth = 3; +} + +// AuthConfig selects one of the supported request-signing methods. +// Each variant carries the method-specific parameters and references +// the names of the Vault-DON secrets it needs. +message AuthConfig { + oneof method { + ApiKeyAuth api_key = 1; + BasicAuth basic = 2; + BearerAuth bearer = 3; + HmacAuth hmac = 4; + OAuth2Auth oauth2 = 5; + } +} + +// ApiKeyAuth attaches a secret value to a chosen header. +// Renders as: : +// Example (header_name="x-api-key", secret_name="coingecko", value_prefix=""): +// x-api-key: +message ApiKeyAuth { + string header_name = 1; // required, e.g. "x-api-key", "Authorization" + string secret_name = 2; // required; key into ConfidentialHTTPRequest.vault_don_secrets + string value_prefix = 3; // optional, e.g. "ApiKey ", "Token " +} + +// BasicAuth renders: Authorization: Basic base64(username ":" password). +message BasicAuth { + string username_secret_name = 1; // required + string password_secret_name = 2; // required +} + +// BearerAuth attaches a pre-issued long-lived token. +// Default behavior: Authorization: Bearer +// header_name and value_prefix allow rare overrides (e.g. GitHub's +// "Authorization: token "). +message BearerAuth { + string token_secret_name = 1; // required + string header_name = 2; // optional override, default "Authorization" + string value_prefix = 3; // optional override, default "Bearer " +} + +// HmacAuth groups all HMAC-family signing variants. +message HmacAuth { + oneof variant { + HmacSha256 sha256 = 1; + AwsSigV4 aws_sig_v4 = 2; + HmacCustom custom = 3; + } +} + +// HmacSha256 implements a generic canonical-string HMAC-SHA256 signature. +// Canonical string: method "\n" url "\n" sha256(body) "\n" timestamp +// Signature is attached via signature_header, timestamp via timestamp_header. +message HmacSha256 { + string secret_name = 1; // required shared secret + string signature_header = 2; // default "X-Signature" + string timestamp_header = 3; // default "X-Timestamp" + bool include_query = 4; // if true, include the query string in the canonical url + string encoding = 5; // "hex" (default) or "base64" +} + +// AwsSigV4 implements AWS Signature Version 4. +// Uses github.com/aws/aws-sdk-go-v2/aws/signer/v4 under the hood. +message AwsSigV4 { + string access_key_id_secret_name = 1; // required + string secret_access_key_secret_name = 2; // required + string session_token_secret_name = 3; // optional (for STS creds) + string region = 4; // required, e.g. "us-east-1" + string service = 5; // required, e.g. "execute-api", "s3" + // Signed headers (comma-separated lowercase). Optional; defaults to + // "host;x-amz-date" plus "x-amz-security-token" if session_token_secret_name + // is set. + repeated string signed_headers = 6; + // If true, uses X-Amz-Content-Sha256: UNSIGNED-PAYLOAD (useful for large S3 + // uploads). Default false. + bool unsigned_payload = 7; +} + +// HmacCustom lets workflow authors specify the canonical string via a +// Go text/template string. Available template vars: +// {{.method}} {{.url}} {{.path}} {{.query}} {{.body}} {{.body_sha256}} +// {{.timestamp}} {{.nonce}} {{header "X-Foo"}} +message HmacCustom { + string secret_name = 1; // required + string canonical_template = 2; // required + enum Hash { + HASH_SHA256 = 0; + HASH_SHA512 = 1; + } + Hash hash = 3; + string signature_header = 4; // required + string signature_prefix = 5; // e.g. "HMAC-SHA256 " + string timestamp_header = 6; // optional; if set, timestamp header injected + string nonce_header = 7; // optional; if set, random nonce header injected + string encoding = 8; // "hex" (default) or "base64" +} + +// OAuth2Auth groups headless OAuth 2.0 flows. +// Interactive flows (Authorization Code, PKCE, Device Code) are NOT supported — +// they require browser consent that a headless TEE cannot perform. +message OAuth2Auth { + oneof variant { + OAuth2ClientCredentials client_credentials = 1; + OAuth2RefreshToken refresh_token = 2; + } +} + +// OAuth2ClientCredentials: machine-to-machine grant. +// The enclave POSTs to token_url with client_id/client_secret, caches the +// resulting access_token per (workflow_owner, token_url, client_id, scopes), +// and attaches "Authorization: Bearer " to the outbound request. +message OAuth2ClientCredentials { + string token_url = 1; // required, must be https:// + string client_id_secret_name = 2; // required + string client_secret_secret_name = 3; // required + repeated string scopes = 4; // optional + string audience = 5; // optional (Auth0-style) + // "basic_auth" (default) or "request_body" — where to put client creds + // on the token request. + string client_auth_method = 6; + // Extra form params to send with the token request. + map extra_params = 7; +} + +// OAuth2RefreshToken: the workflow stores a long-lived refresh_token in Vault +// (obtained out-of-band during an interactive consent). The enclave exchanges +// it for an access_token on cache miss. +// +// Important: if the IdP rotates refresh tokens on each exchange, the enclave +// cannot persist the new refresh_token back to Vault. Disable refresh-token +// rotation at the IdP, or prefer client_credentials where possible. +message OAuth2RefreshToken { + string token_url = 1; // required, must be https:// + string refresh_token_secret_name = 2; // required + string client_id_secret_name = 3; // optional (some IdPs require) + string client_secret_secret_name = 4; // optional (some IdPs require) + repeated string scopes = 5; // optional + map extra_params = 6; } service Client {