diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index eb2a25b380..e420f686d4 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -29,6 +29,8 @@ jobs: checks: write contents: read pull-requests: read + needs: + - example-vault strategy: matrix: directory: @@ -102,6 +104,8 @@ jobs: integration: permissions: contents: read + needs: + - go name: integration tests runs-on: ubuntu-22.04 env: @@ -176,9 +180,89 @@ jobs: - name: validate custom entity rego policy run: test/rego/custom-entity.bats + example-vault: + permissions: + contents: read + runs-on: ubuntu-22.04 + env: + TLS_ENABLED: "true" + VAULT_ADDR: "https://127.0.0.1:8200" + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + go-version-file: "service/go.mod" + check-latest: false + cache-dependency-path: | + service/go.sum + examples/go.sum + protocol/go/go.sum + sdk/go.sum + - run: go mod download + - run: go mod verify + - name: Install mkcert + run: | + sudo apt-get install -y libnss3-tools + curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/amd64" + chmod +x mkcert-v*-linux-amd64 + sudo cp mkcert-v*-linux-amd64 /usr/local/bin/mkcert + - run: | + .github/scripts/init-temp-keys.sh + mkcert -install + mkcert -cert-file ./keys/platform.crt -key-file ./keys/platform-key.pem localhost + cp opentdf-dev.yaml opentdf.yaml + yq eval '.server.tls.enabled = true' -i opentdf.yaml + yq eval '.trace = {"enabled":true}' -i opentdf.yaml + - name: Install vault + # See https://developer.hashicorp.com/vault/install#linux + run: | + wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(grep -oP '(?<=UBUNTU_CODENAME=).*' /etc/os-release || lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list + sudo apt update && sudo apt install vault + - uses: JarvusInnovations/background-action@2428e7b970a846423095c79d43f759abf979a635 # v1.0.7 + name: start vault in background + with: + run: > + vault server -dev -dev-root-token-id root + -dev-tls -dev-tls-cert-dir="keys" + wait-on: | + tcp:localhost:8200 + log-output-if: true + wait-for: 90s + - run: | + echo "VAULT_CACERT=$(pwd)/keys/vault-ca.pem" >> "$GITHUB_ENV" + - name: Added Trusted Certs + run: | + sudo chmod -R 777 ./keys + sudo apt-get install -y ca-certificates + sudo cp "${VAULT_CACERT}" /usr/local/share/ca-certificates || echo unable to find "${VAULT_CACERT}" + sudo cp ./keys/localhost.crt /usr/local/share/ca-certificates || echo unable to find ./keys/localhost.crt + sudo update-ca-certificates + - run: docker compose up -d --wait --wait-timeout 240 || (docker compose logs && exit 1) + - run: go run ./service provision keycloak + - run: go run ./service provision fixtures + - uses: JarvusInnovations/background-action@2428e7b970a846423095c79d43f759abf979a635 # v1.0.7 + name: start server in background + with: + run: | + . ./examples/ckms/setup-vault-env.sh + go run ./examples/ckms + wait-on: | + tcp:localhost:8080 + log-output-if: true + wait-for: 90s + - name: Setup Bats and bats libs + uses: bats-core/bats-action@42fcc8700f773c075a16a90eb11674c0318ad507 # 3.0.1 + - run: ./examples/ckms/trust-sample.bats + benchmark: permissions: contents: read + pull-requests: write + needs: + - go name: benchmark tests outputs: markdown: ${{ steps.save-benchmark.outputs.BENCHMARK_MARKDOWN }} @@ -373,6 +457,8 @@ jobs: image: permissions: contents: read + needs: + - go name: image build runs-on: ubuntu-22.04 steps: @@ -390,10 +476,12 @@ jobs: platform-xtest: permissions: + checks: write contents: read packages: read pull-requests: write - checks: write + needs: + - go uses: opentdf/tests/.github/workflows/xtest.yml@main with: focus-sdk: go @@ -462,6 +550,8 @@ jobs: otdfctl-test: permissions: contents: read + needs: + - go name: otdfctl e2e tests runs-on: ubuntu-latest steps: @@ -482,6 +572,8 @@ jobs: buflint: permissions: contents: read + needs: + - go name: Protocol Buffer Lint and Gencode Up-to-date check runs-on: ubuntu-22.04 steps: diff --git a/examples/ckms/.gitignore b/examples/ckms/.gitignore new file mode 100644 index 0000000000..9e47e2b469 --- /dev/null +++ b/examples/ckms/.gitignore @@ -0,0 +1,11 @@ +# ignores for CKMS Sample Code + +# Generated keydata +*.crt +*.key +*.pem + +# Logfiles +vault-startup.log + + diff --git a/examples/ckms/README.md b/examples/ckms/README.md new file mode 100644 index 0000000000..f958a8ef1d --- /dev/null +++ b/examples/ckms/README.md @@ -0,0 +1,88 @@ +# Sample Key Management System Integration with OpenBao + +This folder includes an example Cryptographic Key Management System (CKMS) extension for OpenTDF. +It uses Vault or OpenBao to store KAS asymmetric key data, +provided via a `trust.KeyService` plugin. + +## Starting Vault + +Start up vault, configured to run in dev mode with local storage. + +```sh +LOCAL_HOSTNAME=$(hostname) +vault server -dev -dev-root-token-id root -dev-tls -dev-tls-cert-dir=./ +``` + +Install the generated CA certificate into the system keychain. + +```sh +sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" ./vault-ca.pem +``` + +Copy the configuration details somewhere. +Copy and paste the environment variable configuration into a new shell. + +```sh +export VAULT_ADDR="https://127.0.0.1:8200" +export VAULT_CACERT="$(pwd)/vault-ca.pem" +``` + +Validate vault is running, and log in + +```sh +vault status +echo root | vault login - +``` + +Let's create some roles, policies, and tokens that apply them: + +```sh +vault secrets enable -path=secret kv-v2 + +vault policy write kas-admin ./vault/policy-admin.hcl +vault policy write kas-service ./vault/policy-service.hcl +vault policy write kas-viewer ./vault/policy-viewer.hcl + +vault token create -policy="kas-admin" -policy="kas-viewer" +# Use this token to create and delete KAS keys +# export KAS_ADMIN_TOKEN= +echo ${KAS_ADMIN_TOKEN} | vault login - +vault kv put secret/kas_keypair/r1 private="$(<../../kas-private.pem | base64)" public="$(<../../kas-cert.pem)" algorithm="rsa:2048"" +``` + +```sh +echo root | vault login - + +# Create a role to from within KAS +vault auth enable approle +vault write auth/approle/role/kas policies="kas-service,kas-viewer" +vault read auth/approle/role/kas/role-id +vault write -f auth/approle/role/kas/secret-id +## Use the role_id and secret_id from the above outputs to create a token with this: +# export KAS_APPROLE_ROLEID= +# export KAS_APPROLE_SECRETID= +vault write auth/approle/login role_id=${KAS_APPROLE_ROLEID} secret_id=${KAS_APPROLE_SECRETID} +``` + +Set KAS_SERVICE_TOKEN to the token returned from the above command. + +```sh +echo ${KAS_SERVICE_TOKEN} | vault login - +vault kv list -mount=secret kas_keypair +``` + + +### Start platform services with sample CKMS plugin + +Run the example + +```sh +go run examples/ckms +``` + +#### +#### Add key based configuration using a new KAS key in the CKMS + + +### Encrypt something + diff --git a/examples/ckms/cfg-vault.yaml b/examples/ckms/cfg-vault.yaml new file mode 100644 index 0000000000..ba2bddbb32 --- /dev/null +++ b/examples/ckms/cfg-vault.yaml @@ -0,0 +1,117 @@ +logger: + level: debug + type: text + output: stdout +# DB and Server configurations are defaulted for local development +# db: +# host: localhost +# port: 5432 +# user: postgres +# password: changeme +services: + entityresolution: + log_level: info + url: http://localhost:8888/auth + clientid: "tdf-entity-resolution" + clientsecret: "secret" + realm: "opentdf" + legacykeycloak: true + inferid: + from: + email: true + username: true + # policy is enabled by default in mode 'all' + # policy: + # enabled: true + # list_request_limit_default: 1000 + # list_request_limit_max: 2500 +server: + tls: + enabled: false + cert: ./keys/platform.crt + key: ./keys/platform-key.pem + auth: + enabled: true + enforceDPoP: false + public_client_id: "opentdf-public" + audience: "http://localhost:8080" + issuer: http://localhost:8888/auth/realms/opentdf + policy: + ## Dot notation is used to access nested claims (i.e. realm_access.roles) + # Claim that represents the user (i.e. email) + username_claim: # preferred_username + # That claim to access groups (i.e. realm_access.roles) + groups_claim: # realm_access.roles + ## Extends the builtin policy + extension: | + g, opentdf-admin, role:admin + g, opentdf-standard, role:standard + ## Custom policy that overrides builtin policy (see examples https://github.com/casbin/casbin/tree/master/examples) + csv: #| + # p, role:admin, *, *, allow + ## Custom model (see https://casbin.org/docs/syntax-for-models/) + model: #| + # [request_definition] + # r = sub, res, act, obj + # + # [policy_definition] + # p = sub, res, act, obj, eft + # + # [role_definition] + # g = _, _ + # + # [policy_effect] + # e = some(where (p.eft == allow)) && !some(where (p.eft == deny)) + # + # [matchers] + # m = g(r.sub, p.sub) && globOrRegexMatch(r.res, p.res) && globOrRegexMatch(r.act, p.act) && globOrRegexMatch(r.obj, p.obj) + trace: + enabled: false + provider: + name: file # file | otlp + file: + path: "./traces/traces.log" + prettyPrint: true # Optional, default is compact JSON + maxSize: 50 # Optional, default 20MB + maxBackups: 5 # Optional, default 10 + maxAge: 14 # Optional, default 30 days + compress: true # Optional, default false + # otlp: + # protocol: grpc # Optional, defaults to grpc + # endpoint: "localhost:4317" + # insecure: true # Set to false if Jaeger requires TLS + # headers: {} # Add if authentication is needed + # HTTP + # protocol: "http/protobuf" + # endpoint: "http://localhost:4318" # Default OTLP HTTP port + # insecure: true # If collector is just HTTP, not HTTPS + # headers: {} # Add if authentication is needed + cors: + # "*" to allow any origin or a specific domain like "https://yourdomain.com" + allowedorigins: + - "*" + # List of methods. Examples: "GET,POST,PUT" + allowedmethods: + - GET + - POST + - PATCH + - PUT + - DELETE + - OPTIONS + # List of headers that are allowed in a request + allowedheaders: + - ACCEPT + - Authorization + - Content-Type + - X-CSRF-Token + - X-Request-ID + # List of response headers that browsers are allowed to access + exposedheaders: + - Link + # Sets whether credentials are included in the CORS request + allowcredentials: true + # Sets the maximum age (in seconds) of a specific CORS preflight request + maxage: 3600 + grpc: + reflectionEnabled: true # Default is false + port: 8080 diff --git a/examples/ckms/docker-compose.yaml b/examples/ckms/docker-compose.yaml new file mode 100644 index 0000000000..116604ab9c --- /dev/null +++ b/examples/ckms/docker-compose.yaml @@ -0,0 +1,18 @@ +version: "3.9" +services: + ckms: + image: hashicorp/vault:latest + cap_add: + - IPC_LOCK + command: vault server -config vault/config/local.json + environment: + VAULT_ADDR: 'https://127.0.0.1:8200' + VAULT_LOCAL_CONFIG: '{"listener":[{"tcp":{"address": "0.0.0.0:8200","tls_disable":"1"}}],"ui":true,"storage":[{"file":{"path":"/vault/data"}}]}' + healthcheck: + retries: 5 + ports: + - 8200:8200 + restart: always + volumes: + - ./vault/config:/vault/config + - ./vault/data:/vault/data diff --git a/examples/ckms/import-keys-from.sh b/examples/ckms/import-keys-from.sh new file mode 100755 index 0000000000..42a726c5a6 --- /dev/null +++ b/examples/ckms/import-keys-from.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# Imports existing keys from opentdf.yaml into Vault. +# +# Usage: +# ./import_keys_from.sh opentdf.yaml +# +# Required environment variables: +# KAS_ADMIN_TOKEN: A token capable of updating kas_keypair in Vault. +# + +# Determine the directory containing this script +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +PROJECT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd) + +# Set environment variables +export VAULT_ADDR="${VAULT_ADDR:-https://127.0.0.1:8200}" +export VAULT_CACERT="${VAULT_CACERT:-${SCRIPT_DIR}/vault-ca.pem}" + +# Check if KAS_ADMIN_TOKEN is set +if [ -z "$KAS_ADMIN_TOKEN" ]; then + echo "KAS_ADMIN_TOKEN is not set. Please set it before running this script." >&2 + exit 1 +fi + +# Log in with the admin token +if ! echo "$KAS_ADMIN_TOKEN" | vault login -; then + echo "Failed to log in with admin token. Exiting." >&2 + exit 1 +fi + +# Make sure the first parameter is provided and is a valid yaml file +if [ -z "$1" ]; then + echo "Usage: $0 " >&2 + exit 1 +fi +if [ ! -f "$1" ]; then + echo "File not found: $1" >&2 + exit 1 +fi +if ! yq eval -o=json "$1" >/dev/null 2>&1; then + echo "Invalid YAML file: $1" >&2 + exit 1 +fi + +# Iterate through keys in opentdf-dev.yaml and store them in Vault +if ! yq eval -o=json ".server.cryptoProvider.standard.keys" <"$1"; then + echo "Failed to retrieve keys from $1. Exiting." >&2 + exit 1 +fi +OPENTDF_KAS_KEYS_JSON=$(yq eval -o=json ".server.cryptoProvider.standard.keys" <"$1") +if [ -z "$OPENTDF_KAS_KEYS_JSON" ]; then + echo "No keys found in $1. Exiting." >&2 + exit 1 +fi + +# Store keys in Vault from opentdf.yaml +echo "$OPENTDF_KAS_KEYS_JSON" | jq -r 'keys[]' | while read -r KEY; do + PRIVATE_KEY_PATH=${PROJECT_DIR}/$(echo "$OPENTDF_KAS_KEYS_JSON" | jq -r ".[${KEY}].private") + PUBLIC_KEY_PATH=${PROJECT_DIR}/$(echo "$OPENTDF_KAS_KEYS_JSON" | jq -r ".[${KEY}].cert") + KEY_ALGORITHM=$(echo "$OPENTDF_KAS_KEYS_JSON" | jq -r ".[${KEY}].alg") + KEY_ID=$(echo "$OPENTDF_KAS_KEYS_JSON" | jq -r ".[${KEY}].kid") + + if ! vault kv put "secret/kas_keypair/${KEY_ID}" \ + private="$(<"$PRIVATE_KEY_PATH")" \ + public="$(<"$PUBLIC_KEY_PATH")" \ + algorithm="$KEY_ALGORITHM"; then + echo "Failed to store key '${KEY}' in Vault." >&2 + else + echo "Successfully stored key '${KEY_ID}' in Vault." + fi +done diff --git a/examples/ckms/main.go b/examples/ckms/main.go new file mode 100644 index 0000000000..1e4b08e478 --- /dev/null +++ b/examples/ckms/main.go @@ -0,0 +1,96 @@ +package main + +import ( + "context" + "errors" + "fmt" + "log" + "os" + + vault "github.com/hashicorp/vault/api" + auth "github.com/hashicorp/vault/api/auth/approle" + "github.com/opentdf/platform/examples/ckms/vaultkms" + "github.com/opentdf/platform/service/pkg/server" + "github.com/opentdf/platform/service/trust" +) + +func start() error { + configFile := "./cfg-vault.yaml" + configKey := "opentdf" + + config := vault.DefaultConfig() + vaultClient, err := vault.NewClient(config) + if err != nil { + return fmt.Errorf("unable to initialize Vault client: %w", err) + } + + kmf := trust.NamedKeyManagerCtxFactory{ + Name: "vault", + Factory: func(ctx context.Context, _ *trust.KeyManagerFactoryOptions) (trust.KeyManager, error) { + kms, err := newVaultTrustService(ctx, vaultClient) + if err != nil { + return nil, err + } + return kms, nil + }, + } + + customStartOptions := []server.StartOptions{ + server.WithWaitForShutdownSignal(), + server.WithConfigFile(configFile), + server.WithConfigKey(configKey), + server.WithTrustKeyManagerCtxFactories(kmf), + } + + // Start the platform server with the custom options + if err := server.Start(customStartOptions...); err != nil { + log.Fatalf("Failed to start the server: %v", err) + } + return nil +} + +func newVaultTrustService(ctx context.Context, vaultClient *vault.Client) (*vaultkms.VaultKeyService, error) { + roleID := os.Getenv("KAS_APPROLE_ROLEID") + if roleID == "" { + return nil, errors.New("no role ID was provided in KAS_APPROLE_ROLEID env var") + } + + // FIXME: The Secret ID is a value that needs to be protected, so do this!! + // // The Secret ID is a value that needs to be protected, so instead of the + // // app having knowledge of the secret ID directly, we have a trusted orchestrator (https://learn.hashicorp.com/tutorials/vault/secure-introduction?in=vault/app-integration#trusted-orchestrator) + // // give the app access to a short-lived response-wrapping token (https://developer.hashicorp.com/vault/docs/concepts/response-wrapping). + // // Read more at: https://learn.hashicorp.com/tutorials/vault/approle-best-practices?in=vault/auth-methods#secretid-delivery-best-practices + // secretID := &auth.SecretID{FromFile: "path/to/wrapping-token"} + + secretID := &auth.SecretID{FromString: os.Getenv("KAS_APPROLE_SECRETID")} + if secretID.FromString == "" { + return nil, errors.New("no role secret ID was provided in KAS_APPROLE_SECRETID env var") + } + + appRoleAuth, err := auth.NewAppRoleAuth( + roleID, + secretID, + ) + if err != nil { + return nil, fmt.Errorf("unable to initialize AppRole auth method: %w", err) + } + + authInfo, err := vaultClient.Auth().Login(ctx, appRoleAuth) + if err != nil { + return nil, fmt.Errorf("unable to login to AppRole auth method: %w", err) + } + if authInfo == nil { + return nil, errors.New("no auth info was returned after login") + } + + kms := vaultkms.NewVaultKeyService(vaultClient) + return kms, nil +} + +func main() { + log.Println("Starting CKMS...") + if err := start(); err != nil { + log.Fatalf("Error starting CKMS: %v", err) + } + log.Println("CKMS started successfully.") +} diff --git a/examples/ckms/new-keys.sh b/examples/ckms/new-keys.sh new file mode 100755 index 0000000000..6daaa50f80 --- /dev/null +++ b/examples/ckms/new-keys.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# Creates and uploads new EC and RSA keys to Vault. +# +# Usage: +# . ./setup_vault_env.sh +# ./new_keys.sh + +# Determine the directory containing this script +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +PROJECT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd) + +# Check if Vault is already running +if ! pgrep -f "vault server"; then + echo "Vault is not running. Please start it first" >&2 + exit 1 +fi + +export VAULT_ADDR="${VAULT_ADDR:-https://127.0.0.1:8200}" +export VAULT_CACERT="${VAULT_CACERT:-${SCRIPT_DIR}/vault-ca.pem}" + +if [ -z "$KAS_ADMIN_TOKEN" ]; then + echo "KAS_ADMIN_TOKEN is not set. Creating a new admin role" >&2 + + echo root | vault login - + if ! echo root | vault login -; then + echo "Failed to log in to Vault. Exiting." >&2 + exit 1 + fi + + ADMIN_TOKEN=$(vault token create -policy="kas-admin" -policy="kas-viewer" -format=json | jq -r '.auth.client_token') + if [ -z "$ADMIN_TOKEN" ]; then + echo "Failed to create admin token. Exiting." >&2 + exit 1 + fi + + export KAS_ADMIN_TOKEN="$ADMIN_TOKEN" +fi + +# Log in with the admin token +if ! echo "$KAS_ADMIN_TOKEN" | vault login -; then + echo "Failed to log in with admin token. Exiting." >&2 + exit 1 +fi + +mkdir -p "${PROJECT_DIR}/keys" + +tstamp=$(date +%Y%m%d-%H%M%S) +opt_output="${PROJECT_DIR}/keys/${tstamp}" +mkdir -p "$opt_output" +if [ -z "$opt_output" ]; then + echo "Failed to create output directory. Exiting." >&2 + exit 1 +fi + +openssl req -x509 -nodes -newkey RSA:2048 -subj "/CN=kas" -keyout "$opt_output/rsa-private.pem" -out "$opt_output/rsa.crt" -days 365 +if ! vault kv put "secret/kas_keypair/r${tstamp}" \ + private="$(<"$opt_output/rsa-private.pem")" \ + public="$(<"$opt_output/rsa.crt")" \ + algorithm="rsa:2048"; then + echo "Failed to store key r${tstamp} in Vault. Exiting." >&2 + exit 1 +fi + +openssl ecparam -name prime256v1 >ecparams.tmp +openssl req -x509 -nodes -newkey ec:ecparams.tmp -subj "/CN=kas" -keyout "$opt_output/ec-private.pem" -out "$opt_output/ec.crt" -days 365 +if ! vault kv put "secret/kas_keypair/e${tstamp}" \ + private="$(<"$opt_output/ec-private.pem")" \ + public="$(<"$opt_output/ec.crt")" \ + algorithm="ec:secp256r1"; then + echo "Failed to store key e${tstamp} in Vault. Exiting." >&2 + exit 1 +fi diff --git a/examples/ckms/setup-vault-env.sh b/examples/ckms/setup-vault-env.sh new file mode 100644 index 0000000000..aa248f2fde --- /dev/null +++ b/examples/ckms/setup-vault-env.sh @@ -0,0 +1,150 @@ +#!/bin/bash +# Sets up the Vault environment for KAS with CKMS example. +# +# Usage: +# . ./setup_vault_env.sh +# go run ./ +# Outputs: +# KAS_ADMIN_TOKEN: A token capable of updating kas_keypair in Vault. +# KAS_APPROLE_ROLEID: The role ID for the AppRole. +# KAS_APPROLE_SECRETID: The secret ID for the AppRole. +# +# This script sets up a local Vault server in development mode, configures it for KAS, +# and retrieves the AppRole credentials needed for KAS to authenticate with Vault. +# It also checks if Vault is already running and if the required port is available. +# Requires: jq, yq, and Vault CLI to be installed and available in PATH. + +# Determine the directory containing this script +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + +# Check if Vault is already running +if pgrep -f "vault server"; then + echo "Vault is already running." >&2 +else + # Check if port 8200 is in use + if lsof -i :8200; then + echo "Port 8200 is already in use. Exiting." >&2 + return 1 + fi + + # Start Vault in dev mode + vault server -dev -dev-root-token-id root -dev-tls -dev-tls-cert-dir="${SCRIPT_DIR}/" &>>vault_startup.log & + VAULT_PID=$! + + echo "Vault started with PID $VAULT_PID. Waiting for it to be ready..." >&2 + echo "To install cert on macOS, run: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ./vault-ca.pem" >&2 + + # Clean up Vault process on exit + trap 'echo "Trapped signal: EXIT at $(date)"; kill $VAULT_PID' EXIT +fi + +# Set environment variables +export VAULT_ADDR="https://127.0.0.1:8200" +export VAULT_CACERT="${SCRIPT_DIR}/vault-ca.pem" + +# Wait for Vault to start, checking every 2 seconds for up to 30 seconds +for i in {1..15}; do + if vault status -format=json; then + echo "Vault is running." >&2 + break + fi + if [ "$i" -eq 15 ]; then + echo "Vault did not start / respond with positive within 30 seconds. Exiting." >&2 + kill "$VAULT_PID" + return 1 + fi + sleep 2 +done + +setup_vault_adminrole() { + # Log in to Vault + echo root | vault login - + if ! echo root | vault login -; then + echo "Failed to log in to Vault. Exiting." >&2 + return 1 + fi + + # Check if the path is already in use before enabling KV secrets engine + if vault secrets list -format=json | jq -e 'has("secret/")' >/dev/null; then + echo "KV secrets engine is already enabled at the path 'secret/'. Skipping." >&2 + else + # Enable KV secrets engine + if ! vault secrets enable -path=secret kv-v2; then + echo "Failed to enable KV secrets engine. Exiting." >&2 + return 1 + fi + fi + + # Write policies + if ! vault policy write kas-admin "${SCRIPT_DIR}/vaultkms/policy-admin.hcl"; then + echo "Failed to write kas-admin policy. Exiting." >&2 + return 1 + fi + + if ! vault policy write kas-service "${SCRIPT_DIR}/vaultkms/policy-service.hcl"; then + echo "Failed to write kas-service policy. Exiting." >&2 + return 1 + fi + + if ! vault policy write kas-viewer "${SCRIPT_DIR}/vaultkms/policy-viewer.hcl"; then + echo "Failed to write kas-viewer policy. Exiting." >&2 + return 1 + fi + + # Create an admin token + ADMIN_TOKEN=$(vault token create -policy="kas-admin" -policy="kas-viewer" -format=json | jq -r '.auth.client_token') + if [ -z "$ADMIN_TOKEN" ]; then + echo "Failed to create admin token. Exiting." >&2 + return 1 + fi + + # Export the admin token + export KAS_ADMIN_TOKEN="$ADMIN_TOKEN" + echo "Admin token created; exported as KAS_ADMIN_TOKEN" >&2 +} + +setup_vault_approle() { + # Log in to Vault + echo root | vault login -format=json - + if ! echo root | vault login -format=json -; then + echo "Failed to log in to Vault. Exiting." >&2 + return 1 + fi + + # Enable approle authentication + if ! vault auth enable approle; then + echo "Failed to enable approle authentication. Assuming it is already present and continuing." >&2 + fi + + # Create a role for KAS + if ! vault write auth/approle/role/kas policies="kas-service,kas-viewer" \ + secret_id_ttl=10h \ + token_ttl=10h \ + token_max_ttl=20h \ + secret_id_num_uses=100; then + echo "Failed to create role for KAS. Exiting." >&2 + return 1 + fi + + # Retrieve role_id and secret_id + ROLE_ID=$(vault read -format=json auth/approle/role/kas/role-id | tee /dev/stderr | jq -r '.data.role_id') + if ! ROLE_ID=$(vault read -format=json auth/approle/role/kas/role-id | jq -r '.data.role_id'); then + echo "Failed to retrieve role_id. Exiting." >&2 + return 1 + fi + + SECRET_ID=$(vault write -f -format=json auth/approle/role/kas/secret-id | tee /dev/stderr | jq -r '.data.secret_id') + if ! SECRET_ID=$(vault write -f -format=json auth/approle/role/kas/secret-id | jq -r '.data.secret_id'); then + echo "Failed to retrieve secret_id. Exiting." >&2 + return 1 + fi + + # Export the retrieved values + export KAS_APPROLE_ROLEID="$ROLE_ID" + export KAS_APPROLE_SECRETID="$SECRET_ID" +} + +setup_vault_adminrole +setup_vault_approle +export KAS_APPROLE_ROLEID="$ROLE_ID" +export KAS_APPROLE_SECRETID="$SECRET_ID" diff --git a/examples/ckms/trust-sample.bats b/examples/ckms/trust-sample.bats new file mode 100755 index 0000000000..1d295346c7 --- /dev/null +++ b/examples/ckms/trust-sample.bats @@ -0,0 +1,24 @@ +#!/usr/bin/env bats + +# Tests for validating that we are using a vault backend + +@test "vault: service is available" { + run vault status + echo "${output}" + [ $status = 0 ] +} + +@test "vault: we can log in as an approle" { + . ./setup-vault-env.sh + echo "$KAS_ADMIN_TOKEN" | vault login - + run vault kv list -mount=secret kas_keypair + echo "${output}" + [ $status = 0 ] +} + +@test "vault: we can add new keys (rotate)" { + . ./setup-vault-env.sh + run ./new-keys.sh + echo "${output}" + [ $status = 0 ] +} diff --git a/examples/ckms/vaultkms/policy-admin.hcl b/examples/ckms/vaultkms/policy-admin.hcl new file mode 100644 index 0000000000..8e4b6f0413 --- /dev/null +++ b/examples/ckms/vaultkms/policy-admin.hcl @@ -0,0 +1,14 @@ +# policy-admin.hcl + +# kv v2 has paths of the form /[path]/{data,metadata,[other action]/[name] + +path "secret/data/kas_keypair/*" { + # We don't want to enable `patch`, + # since kas does explicit rotation + # and never reuses key identifiers. + capabilities = ["create", "update", "delete", "list", "read"] +} + +path "secret/metadata/kas_keypair/*" { + capabilities = ["list"] +} diff --git a/examples/ckms/vaultkms/policy-service.hcl b/examples/ckms/vaultkms/policy-service.hcl new file mode 100644 index 0000000000..11754e10f5 --- /dev/null +++ b/examples/ckms/vaultkms/policy-service.hcl @@ -0,0 +1,13 @@ +# policy-service.hcl + +path "secret/data/kas_keypair/*" { + capabilities = ["list", "read"] +} + +path "secret/metadata/kas_keypair/*" { + capabilities = ["list"] +} + +path "secret/data/kas_keypair/+/private" { + capabilities = ["read"] +} diff --git a/examples/ckms/vaultkms/policy-viewer.hcl b/examples/ckms/vaultkms/policy-viewer.hcl new file mode 100644 index 0000000000..de2a964840 --- /dev/null +++ b/examples/ckms/vaultkms/policy-viewer.hcl @@ -0,0 +1,9 @@ +# policy-viewer.hcl + +path "secret/data/kas_keypair/*/public" { + capabilities = ["read"] +} + +path "secret/metadata/kas_keypair" { + capabilities = ["list"] +} diff --git a/examples/ckms/vaultkms/vault_service.go b/examples/ckms/vaultkms/vault_service.go new file mode 100644 index 0000000000..039c011599 --- /dev/null +++ b/examples/ckms/vaultkms/vault_service.go @@ -0,0 +1,344 @@ +package vaultkms + +import ( + "context" + "crypto/elliptic" + "crypto/hmac" + "crypto/sha256" + "errors" + "fmt" + "log/slog" + + vault "github.com/hashicorp/vault/api" + "github.com/opentdf/platform/lib/ocrypto" + "github.com/opentdf/platform/protocol/go/policy" + "github.com/opentdf/platform/service/trust" +) + +type VaultItem struct { + kid trust.KeyIdentifier + alg ocrypto.KeyType + public ocrypto.PublicKeyEncryptor + private ocrypto.PrivateKeyDecryptor + nano *ocrypto.ECDecryptor +} + +func (v *VaultItem) ID() trust.KeyIdentifier { + return v.kid +} + +func (v *VaultItem) Algorithm() ocrypto.KeyType { + return v.alg +} + +func (v *VaultItem) ProviderConfig() *policy.KeyProviderConfig { + return &policy.KeyProviderConfig{ + Manager: "vault", + } +} + +func (v *VaultItem) IsLegacy() bool { + return false +} + +func (v *VaultItem) ExportPrivateKey(_ context.Context) (*trust.PrivateKey, error) { + return nil, errors.New("private key export not supported") +} + +func (v *VaultItem) ExportPublicKey(_ context.Context, format trust.KeyType) (string, error) { + if format != trust.KeyTypePKCS8 { + return "", fmt.Errorf("unsupported key format: %v", format) + } + return v.public.PublicKeyInPemFormat() +} + +func (v *VaultItem) ExportCertificate(_ context.Context) (string, error) { + return "", errors.New("certificate export not supported") +} + +func (v VaultItem) System() string { + return "examples.opentdf.io/vault" +} + +type VaultKeyService struct { + client *vault.Client + items map[trust.KeyIdentifier]*VaultItem +} + +func NewVaultKeyService(client *vault.Client) *VaultKeyService { + return &VaultKeyService{ + client: client, + items: make(map[trust.KeyIdentifier]*VaultItem), + } +} + +func (v VaultKeyService) Name() string { + return "examples.opentdf.io/vault" +} + +func (v *VaultKeyService) LoadKeys(ctx context.Context) error { + secretsPath := "secret/metadata/kas_keypair" + lra, err := v.client.Logical().ListWithContext(ctx, secretsPath) + if err != nil { + return fmt.Errorf("unable to list secrets at %s: %w", secretsPath, err) + } + + var keys []interface{} + if lra == nil || lra.Data == nil || lra.Data["keys"] == nil { + return fmt.Errorf("no keys found at %s", secretsPath) + } + + keys, ok := lra.Data["keys"].([]interface{}) + if !ok { + return fmt.Errorf("unable to assert type of keys to []interface{} for path %s", secretsPath) + } + + for _, key := range keys { + if k, err := v.loadKey(ctx, key); err != nil { + slog.ErrorContext(ctx, "failed to load key", + slog.Any("key", key), + slog.Any("err", err)) + } else { + slog.DebugContext(ctx, "loaded key", slog.Any("key", key)) + v.items[k.ID()] = k + } + } + + if len(v.items) == 0 { + return errors.New("no valid keys were found") + } + return nil +} + +func nanoSalt() []byte { + digest := sha256.New() + digest.Write([]byte("L1L")) + salt := digest.Sum(nil) + return salt +} + +func (v *VaultKeyService) FindKeyByAlgorithm(ctx context.Context, algorithm ocrypto.KeyType, _ bool) (trust.KeyDetails, error) { + // Legacy keys are not supported + if err := v.LoadKeys(ctx); err != nil { + return nil, fmt.Errorf("failed to refresh keys: %w", err) + } + for _, item := range v.items { + if item.Algorithm() == algorithm { + return item, nil + } + } + return nil, errors.New("no key found for algorithm: " + string(algorithm)) +} + +func (v *VaultKeyService) FindKeyByID(ctx context.Context, id trust.KeyIdentifier) (trust.KeyDetails, error) { + if err := v.LoadKeys(ctx); err != nil { + return nil, fmt.Errorf("failed to refresh keys: %w", err) + } + item, exists := v.items[id] + if !exists { + return nil, fmt.Errorf("no key found for ID: %s", id) + } + return item, nil +} + +func (v *VaultKeyService) ListKeys(ctx context.Context) ([]trust.KeyDetails, error) { + if err := v.LoadKeys(ctx); err != nil { + return nil, fmt.Errorf("failed to refresh keys: %w", err) + } + keys := make([]trust.KeyDetails, 0, len(v.items)) + for _, item := range v.items { + keys = append(keys, item) + } + return keys, nil +} + +type InProcessWrappedKey struct { + rawKey []byte + cipher ocrypto.AesGcm +} + +func NewInProcessAESKey(key []byte) (*InProcessWrappedKey, error) { + if len(key) == 0 { + return nil, errors.New("key cannot be empty") + } + + cipher, err := ocrypto.NewAESGcm(key) + if err != nil { + return nil, fmt.Errorf("failed to create AES-GCM cipher: %w", err) + } + + return &InProcessWrappedKey{ + rawKey: key, + cipher: cipher, + }, nil +} + +func (k *InProcessWrappedKey) VerifyBinding(_ context.Context, policy, binding []byte) error { + actualHMAC, err := k.generateHMACDigest(policy) + if err != nil { + return fmt.Errorf("unable to generate policy hmac: %w", err) + } + + if !hmac.Equal(actualHMAC, binding) { + return errors.New("policy hmac mismatch") + } + + return nil +} + +func (k *InProcessWrappedKey) Export(encapsulator ocrypto.Encapsulator) ([]byte, error) { + return encapsulator.Encrypt(k.rawKey) +} + +func (k *InProcessWrappedKey) DecryptAESGCM(iv []byte, body []byte, tagSize int) ([]byte, error) { + decryptedData, err := k.cipher.DecryptWithIVAndTagSize(iv, body, tagSize) + if err != nil { + return nil, err + } + + return decryptedData, nil +} + +func (v *VaultKeyService) Decrypt(ctx context.Context, keyDetails trust.KeyDetails, ciphertext []byte, ephemeralPublicKey []byte) (ocrypto.ProtectedKey, error) { + if err := v.refreshKeys(ctx); err != nil { + return nil, fmt.Errorf("failed to refresh keys: %w", err) + } + item, exists := v.items[keyDetails.ID()] + if !exists { + return nil, fmt.Errorf("key not found: %s", keyDetails.ID()) + } + + decryptedData, err := item.private.DecryptWithEphemeralKey(ciphertext, ephemeralPublicKey) + if err != nil { + return nil, fmt.Errorf("decryption failed: %w", err) + } + + return NewInProcessAESKey(decryptedData) +} + +func (v *VaultKeyService) DeriveKey(ctx context.Context, keyDetails trust.KeyDetails, ephemeralPublicKeyBytes []byte, curve elliptic.Curve) (ocrypto.ProtectedKey, error) { + if err := v.refreshKeys(ctx); err != nil { + return nil, fmt.Errorf("failed to refresh keys: %w", err) + } + vi := v.items[keyDetails.ID()] + if vi == nil { + return nil, fmt.Errorf("key not found: %s", keyDetails.ID()) + } + if vi.nano == nil { + return nil, fmt.Errorf("key %s is not a nano key", keyDetails.ID()) + } + key, err := vi.nano.DeriveNanoTDFSymmetricKey(curve, ephemeralPublicKeyBytes) + if err != nil { + return nil, fmt.Errorf("failed to derive key: %w", err) + } + return NewInProcessAESKey(key) +} + +type OCEncapsulator struct { + ocrypto.PublicKeyEncryptor +} + +func (e *OCEncapsulator) Encapsulate(dek ocrypto.ProtectedKey) ([]byte, error) { + // Delegate to the ProtectedKey to avoid exposing raw key material + return dek.Export(e) +} + +func (e *OCEncapsulator) PublicKeyAsPEM() (string, error) { + return e.PublicKeyInPemFormat() +} + +func (v *VaultKeyService) GenerateECSessionKey(_ context.Context, ephemeralPublicKey string) (ocrypto.Encapsulator, error) { + pke, err := ocrypto.FromPublicPEMWithSalt(ephemeralPublicKey, nanoSalt(), nil) + if err != nil { + return nil, fmt.Errorf("failed to create public key encryptor: %w", err) + } + return &OCEncapsulator{PublicKeyEncryptor: pke}, nil +} + +func (v *VaultKeyService) Close() { + // Implement any cleanup logic if necessary +} + +func (k *InProcessWrappedKey) generateHMACDigest(msg []byte) ([]byte, error) { + mac := hmac.New(sha256.New, k.rawKey) + _, err := mac.Write(msg) + if err != nil { + return nil, fmt.Errorf("failed to write to HMAC: %w", err) + } + return mac.Sum(nil), nil +} + +func (v *VaultKeyService) loadKey(ctx context.Context, key interface{}) (*VaultItem, error) { + var kid trust.KeyIdentifier + if keyStr, ok := key.(string); ok { + kid = trust.KeyIdentifier(keyStr) + } else { + return nil, fmt.Errorf("key is not a string: %T", key) + } + + secretPath := fmt.Sprintf("kas_keypair/%s", kid) + secret, err := v.client.KVv2("secret").Get(ctx, secretPath) + if err != nil { + return nil, fmt.Errorf("unable to read secret in kv store secret with path [%s]: %w", secretPath, err) + } + + var privateKeyPEM string + if pem, ok := secret.Data["private"].(string); ok { + privateKeyPEM = pem + } else { + return nil, fmt.Errorf("unable to assert type of private key to string for key %s", kid) + } + + privateKey, err := ocrypto.FromPrivatePEM(privateKeyPEM) + if err != nil { + return nil, fmt.Errorf("failed to create private key from PEM: %w", err) + } + var nanoKey *ocrypto.ECDecryptor + if _, ok := privateKey.(*ocrypto.ECDecryptor); ok { + salt := nanoSalt() + nk, err := ocrypto.FromPrivatePEMWithSalt(privateKeyPEM, salt, nil) + if err != nil { + return nil, fmt.Errorf("failed to create EC decryptor from PEM: %w", err) + } + if ec2, ecOK := nk.(ocrypto.ECDecryptor); ecOK { + nanoKey = &ec2 + } else { + return nil, fmt.Errorf("failed to assert type of EC decryptor for key %s", kid) + } + } + + var publicKey ocrypto.PublicKeyEncryptor + if publicKeyPEM, ok := secret.Data["public"].(string); ok { + publicKey, err = ocrypto.FromPublicPEM(publicKeyPEM) + if err != nil { + return nil, fmt.Errorf("failed to create public key from PEM: %w", err) + } + } else { + publicKey = privateKey.PublicKey() + } + + algorithm, ok := secret.Data["algorithm"].(string) + if !ok { + return nil, fmt.Errorf("unable to assert type of algorithm to string for key %s", kid) + } + + alg := ocrypto.KeyType(algorithm) + if !alg.IsEC() && !alg.IsRSA() { + return nil, fmt.Errorf("unsupported key algorithm: %s", algorithm) + } + + return &VaultItem{ + kid: kid, + alg: alg, + public: publicKey, + private: privateKey, + nano: nanoKey, + }, nil +} + +func (v *VaultKeyService) refreshKeys(ctx context.Context) error { + if len(v.items) > 0 { + return nil + } + return v.LoadKeys(ctx) +} diff --git a/examples/cmd/decrypt.go b/examples/cmd/decrypt.go index 8105e8c84a..1cc7a51822 100644 --- a/examples/cmd/decrypt.go +++ b/examples/cmd/decrypt.go @@ -87,7 +87,7 @@ func decrypt(cmd *cobra.Command, args []string) error { if !isNano { opts := []sdk.TDFReaderOption{} if alg != "" { - kt, err := keyTypeForKeyType(alg) + kt, err := parseKeyType(alg) if err != nil { return err } diff --git a/examples/cmd/encrypt.go b/examples/cmd/encrypt.go index ada8585f79..7250d03e28 100644 --- a/examples/cmd/encrypt.go +++ b/examples/cmd/encrypt.go @@ -106,11 +106,11 @@ func encrypt(cmd *cobra.Command, args []string) error { })) } if alg != "" { - kt, err := keyTypeForKeyType(alg) + kt, err := parseKeyType(alg) if err != nil { return err } - opts = append(opts, sdk.WithWrappingKeyAlg(kt)) + opts = append(opts, sdk.WithWrappingKeyAlg(kt)) //nolint:staticcheck // SA1019: This is test code for backward compatibility } tdf, err := client.CreateTDF(out, in, opts...) if err != nil { @@ -176,16 +176,12 @@ func encrypt(cmd *cobra.Command, args []string) error { return nil } -func keyTypeForKeyType(alg string) (ocrypto.KeyType, error) { - switch alg { - case string(ocrypto.RSA2048Key): - return ocrypto.RSA2048Key, nil - case string(ocrypto.EC256Key): - return ocrypto.EC256Key, nil - default: - // do not submit add ocrypto.UnknownKey - return ocrypto.RSA2048Key, fmt.Errorf("unsupported key type [%s]", alg) +func parseKeyType(alg string) (ocrypto.KeyType, error) { + kt := ocrypto.KeyType(alg) + if kt.IsEC() || kt.IsRSA() { + return kt, nil } + return ocrypto.RSA2048Key, fmt.Errorf("unsupported key type [%s]", alg) } func cat(_ *cobra.Command, nTdfFile string) error { diff --git a/examples/go.mod b/examples/go.mod index 7db23aeec9..7c9c83b35b 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -5,9 +5,12 @@ go 1.24.0 toolchain go1.24.6 require ( + github.com/hashicorp/vault/api v1.16.0 + github.com/hashicorp/vault/api/auth/approle v0.9.0 github.com/opentdf/platform/lib/ocrypto v0.7.0 github.com/opentdf/platform/protocol/go v0.13.0 github.com/opentdf/platform/sdk v0.7.0 + github.com/opentdf/platform/service v0.5.3 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 google.golang.org/grpc v1.73.0 @@ -16,37 +19,132 @@ require ( require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1 // indirect + cel.dev/expr v0.23.1 // indirect connectrpc.com/connect v1.18.1 // indirect + connectrpc.com/grpchealth v1.3.0 // indirect + connectrpc.com/grpcreflect v1.2.0 // indirect + connectrpc.com/validate v0.2.0 // indirect github.com/Masterminds/semver/v3 v3.3.1 // indirect + github.com/Masterminds/squirrel v1.5.4 // indirect + github.com/Nerzal/gocloak/v13 v13.9.0 // indirect + github.com/agnivade/levenshtein v1.2.1 // indirect + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bmatcuk/doublestar v1.3.4 // indirect + github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect + github.com/bufbuild/protovalidate-go v0.9.3 // indirect + github.com/casbin/casbin/v2 v2.101.0 // indirect + github.com/casbin/govaluate v1.2.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.2 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect + github.com/creasty/defaults v1.8.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/go-chi/cors v1.2.1 // indirect + github.com/go-ini/ini v1.67.0 // indirect + github.com/go-jose/go-jose/v4 v4.0.5 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.22.0 // indirect + github.com/go-resty/resty/v2 v2.16.5 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/gobwas/glob v0.2.3 // indirect github.com/goccy/go-json v0.10.5 // indirect + github.com/golang-jwt/jwt/v5 v5.2.2 // indirect + github.com/google/cel-go v0.25.0 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/mux v1.8.1 // indirect github.com/gowebpki/jcs v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect + github.com/hashicorp/go-rootcerts v1.0.2 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect + github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect + github.com/hashicorp/go-sockaddr v1.0.2 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/kr/text v0.2.0 // indirect + github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/pgx/v5 v5.7.5 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect + github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/lestrrat-go/blackmagic v1.0.4 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.6 // indirect github.com/lestrrat-go/iter v1.0.2 // indirect github.com/lestrrat-go/jwx/v2 v2.1.6 // indirect github.com/lestrrat-go/option v1.0.1 // indirect + github.com/mfridman/interpolate v0.0.2 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/open-policy-agent/opa v1.4.2 // indirect + github.com/opentdf/platform/lib/flattening v0.1.3 // indirect + github.com/opentdf/platform/lib/identifier v0.0.2 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/pressly/goose/v3 v3.19.1 // indirect + github.com/prometheus/client_golang v1.21.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.62.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect + github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/segmentio/asm v1.2.0 // indirect + github.com/segmentio/ksuid v1.0.4 // indirect + github.com/sethvargo/go-retry v0.2.4 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/cast v1.7.1 // indirect github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/viper v1.20.1 // indirect + github.com/stoewer/go-strcase v1.3.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/tchap/go-patricia/v2 v2.3.2 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect + github.com/yashtewari/glob-intersection v0.2.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/sdk v1.36.0 // indirect + go.opentelemetry.io/otel/trace v1.36.0 // indirect + go.opentelemetry.io/proto/otlp v1.6.0 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.39.0 // indirect + golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect golang.org/x/net v0.41.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/sync v0.15.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/text v0.26.0 // indirect + golang.org/x/time v0.11.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/examples/go.sum b/examples/go.sum index 3b4cd41af2..ab563fb931 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -1,19 +1,67 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1 h1:uwSqFkn8DDTzNlaV9TxgSXY5OCaNdb4rH+Axd2FujkE= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250603165357-b52ab10f4468.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= +cel.dev/expr v0.23.1 h1:K4KOtPCJQjVggkARsjG9RWXP6O4R73aHeJMa/dmCQQg= +cel.dev/expr v0.23.1/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw= connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= +connectrpc.com/grpchealth v1.3.0 h1:FA3OIwAvuMokQIXQrY5LbIy8IenftksTP/lG4PbYN+E= +connectrpc.com/grpchealth v1.3.0/go.mod h1:3vpqmX25/ir0gVgW6RdnCPPZRcR6HvqtXX5RNPmDXHM= +connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= +connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +connectrpc.com/validate v0.2.0 h1:izFAPJwZzfseE93aq0ZqnMBsuNRXKZe6aDWZ3vo8dhY= +connectrpc.com/validate v0.2.0/go.mod h1:3v6kC0nIp6DtXwDMdq/BXrVPPm+w3nWlHW8T193FErE= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/ClickHouse/ch-go v0.58.2 h1:jSm2szHbT9MCAB1rJ3WuCJqmGLi5UTjlNu+f530UTS0= +github.com/ClickHouse/ch-go v0.58.2/go.mod h1:Ap/0bEmiLa14gYjCiRkYGbXvbe8vwdrfTYWhsuQ99aw= +github.com/ClickHouse/clickhouse-go/v2 v2.17.1 h1:ZCmAYWpu75IyEi7+Yrs/uaAjiCGY5wfW5kXo64exkX4= +github.com/ClickHouse/clickhouse-go/v2 v2.17.1/go.mod h1:rkGTvFDTLqLIm0ma+13xmcCfr/08Gvs7KmFt1tgiWHQ= github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= +github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzSVZhw= github.com/Nerzal/gocloak/v13 v13.9.0/go.mod h1:YYuDcXZ7K2zKECyVP7pPqjKxx2AzYSpKDj8d6GuyM10= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= +github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 h1:goHVqTbFX3AIo0tzGr14pgfAW2ZfPChKO21Z9MGf/gk= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= +github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= +github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= +github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bufbuild/protovalidate-go v0.9.3 h1:XvdtwQuppS3wjzGfpOirsqwN5ExH2+PiIuA/XZd3MTM= +github.com/bufbuild/protovalidate-go v0.9.3/go.mod h1:2lUDP6fNd3wxznRNH3Nj64VB07+PySeslamkerwP6tE= +github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA= +github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q= +github.com/casbin/casbin/v2 v2.101.0 h1:y8qZRXcgv5omd3k/7kpaP03Hov82sXzCC5FAfm17lkw= +github.com/casbin/casbin/v2 v2.101.0/go.mod h1:LO7YPez4dX3LgoTCqSQAleQDo0S0BeZBDxYnPUl95Ng= +github.com/casbin/govaluate v1.2.0 h1:wXCXFmqyY+1RwiKfYo3jMKyrtZmOL3kHwaqDyCPOYak= +github.com/casbin/govaluate v1.2.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= +github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= @@ -26,58 +74,181 @@ github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GK github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creasty/defaults v1.8.0 h1:z27FJxCAa0JKt3utc0sCImAEb+spPucmKoOdLHvHYKk= +github.com/creasty/defaults v1.8.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= +github.com/dgraph-io/badger/v4 v4.7.0 h1:Q+J8HApYAY7UMpL8d9owqiB+odzEc0zn/aqOD9jhc6Y= +github.com/dgraph-io/badger/v4 v4.7.0/go.mod h1:He7TzG3YBy3j4f5baj5B7Zl2XyfNe5bl4Udl0aPemVA= +github.com/dgraph-io/ristretto/v2 v2.2.0 h1:bkY3XzJcXoMuELV8F+vS8kzNgicwQFAaGINAEJdWGOM= +github.com/dgraph-io/ristretto/v2 v2.2.0/go.mod h1:RZrm63UmcBAaYWC1DotLYBmTvgkrs0+XhBd7Npn7/zI= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= +github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/elastic/go-sysinfo v1.11.2 h1:mcm4OSYVMyws6+n2HIVMGkln5HOpo5Ie1ZmbbNn0jg4= +github.com/elastic/go-sysinfo v1.11.2/go.mod h1:GKqR8bbMK/1ITnez9NIsIfXQr25aLhRJa7AfT8HpBFQ= +github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0= +github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss= +github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= +github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= +github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= +github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= +github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= +github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw= +github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06FI= +github.com/go-faster/errors v0.6.1/go.mod h1:5MGV2/2T9yvlrbhe9pD9LO5Z/2zCSq2T8j+Jpi2LAyY= +github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= +github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= +github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= +github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= +github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/cel-go v0.25.0 h1:jsFw9Fhn+3y2kBbltZR4VEz5xKkcIFRPDnuEzAGv5GY= +github.com/google/cel-go v0.25.0/go.mod h1:hjEb6r5SuOSlhCHmFoLzu8HGCERvIsDAbxDAyNU/MmI= +github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q= +github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gowebpki/jcs v1.0.1 h1:Qjzg8EOkrOTuWP7DqQ1FbYtcpEbeTzUoTN9bptp8FOU= github.com/gowebpki/jcs v1.0.1/go.mod h1:CID1cNZ+sHp1CCpAR8mPf6QRtagFBgPJE0FCUQ6+BrI= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= +github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/vault/api v1.16.0 h1:nbEYGJiAPGzT9U4oWgaaB0g+Rj8E59QuHKyA5LhwQN4= +github.com/hashicorp/vault/api v1.16.0/go.mod h1:KhuUhzOD8lDSk29AtzNjgAu2kxRA9jL9NAbkFlqvkBA= +github.com/hashicorp/vault/api/auth/approle v0.9.0 h1:FdpspwGVWnGiWmAxd5L1Yd+T+fX2kYnyAIvI5oGdvNs= +github.com/hashicorp/vault/api/auth/approle v0.9.0/go.mod h1:fvtJhBs3AYMs2fXk4U5+u+7unhUGuboiKzFpLPpIazw= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa h1:s+4MhCQ6YrzisK6hFJUX53drDT4UsSW3DEhKn0ifuHw= +github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs= +github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= +github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= +github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA= github.com/lestrrat-go/blackmagic v1.0.4/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= @@ -90,10 +261,31 @@ github.com/lestrrat-go/jwx/v2 v2.1.6 h1:hxM1gfDILk/l5ylers6BX/Eq1m/pnxe9NBwW6lVf github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU= github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475 h1:6PfEMwfInASh9hkN83aR0j4W/eKaAZt/AURtXAXlas0= +github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475/go.mod h1:20nXSmcf0nAscrzqsXeC2/tA3KkV2eCiJqYuyAgl+ss= github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc= github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/marcboeker/go-duckdb v1.5.6 h1:5+hLUXRuKlqARcnW4jSsyhCwBRlu4FGjM0UTf2Yq5fw= +github.com/marcboeker/go-duckdb v1.5.6/go.mod h1:wm91jO2GNKa6iO9NTcjXIRsW+/ykPoJbQcHSXhdAl28= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= +github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= +github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= +github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= @@ -110,56 +302,125 @@ github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/open-policy-agent/opa v1.4.2 h1:ag4upP7zMsa4WE2p1pwAFeG4Pn3mNwfAx9DLhhJfbjU= +github.com/open-policy-agent/opa v1.4.2/go.mod h1:DNzZPKqKh4U0n0ANxcCVlw8lCSv2c+h5G/3QvSYdWZ8= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= +github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= github.com/opentdf/platform/lib/fixtures v0.3.0 h1:pgEm9ynMDIFH7Wd/lre2tfvtura8LfaV3iA1w1m7D3Q= github.com/opentdf/platform/lib/fixtures v0.3.0/go.mod h1:K/r0REv5MYClnkuiCxCOT1LTXbuIDP0kqixlGmPQzXc= +github.com/opentdf/platform/lib/flattening v0.1.3 h1:IuOm/wJVXNrzOV676Ticgr0wyBkL+lVjsoSfh+WSkNo= +github.com/opentdf/platform/lib/flattening v0.1.3/go.mod h1:Gs/T+6FGZKk9OAdz2Jf1R8CTGeNRYrq1lZGDeYT3hrY= +github.com/opentdf/platform/lib/identifier v0.0.2 h1:h3zR+IZ/4/X5UOYUp/aTA0OcX1QqsmgSiqjaM0uttFE= +github.com/opentdf/platform/lib/identifier v0.0.2/go.mod h1:/tHnLlSVOq3qmbIYSvKrtuZchQfagenv4wG5twl4oRs= github.com/opentdf/platform/lib/ocrypto v0.7.0 h1:uBZJXisuXU3V8681aP8FVMJkyWBrwWOqrsYFzb3yZfY= github.com/opentdf/platform/lib/ocrypto v0.7.0/go.mod h1:sYhoBL1bQYgQVSSNpxU13RsrE5JAk8BABT1hfr9L3j8= github.com/opentdf/platform/protocol/go v0.13.0 h1:vrOOHyhYDPzJgNenz/1g0M5nWtkOYKkPggMNHKzeMcs= github.com/opentdf/platform/protocol/go v0.13.0/go.mod h1:GRycoDGDxaz91sOvGZFWVEKJLluZFg2wM3NJmhucDHo= github.com/opentdf/platform/sdk v0.7.0 h1:8hczDycXGY1ucdIXSrP17oW/Eyu3vsb4LEX4hc7tvVY= github.com/opentdf/platform/sdk v0.7.0/go.mod h1:CTJR1NXeYe896M1/VN0h+1Ff54SdBtxv4z18BGTi8yk= +github.com/opentdf/platform/service v0.5.3 h1:llYXBtpFd/ao6LXXa6+l4aYnnCETYXHGDp5TlWQ5XWI= +github.com/opentdf/platform/service v0.5.3/go.mod h1:3pS9lDm9w3d7JP3WwUF4ZFR2nnOpxBBo4npLHWCsYt8= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= +github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= +github.com/paulmach/orb v0.10.0 h1:guVYVqzxHE/CQ1KpfGO077TR0ATHSNjp4s6XGLn3W9s= +github.com/paulmach/orb v0.10.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/pressly/goose/v3 v3.19.1 h1:ESO4QAltQChAY4zcenS8O1HKnyW9I0rKMxLwV7hpwGk= +github.com/pressly/goose/v3 v3.19.1/go.mod h1:6OPM/AnUu6338xBlaX7R3veZ6F5iCobaGEEkoN7BTFc= +github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk= +github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= +github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= +github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= +github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc= github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= +github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= +github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tchap/go-patricia/v2 v2.3.2 h1:xTHFutuitO2zqKAQ5rCROYgUb7Or/+IC3fts9/Yc7nM= +github.com/tchap/go-patricia/v2 v2.3.2/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= github.com/testcontainers/testcontainers-go v0.37.0 h1:L2Qc0vkTw2EHWQ08djon0D2uw7Z/PtHS/QzZZ5Ra/hg= github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM= github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= +github.com/tursodatabase/libsql-client-go v0.0.0-20231216154754-8383a53d618f h1:teZ0Pj1Wp3Wk0JObKBiKZqgxhYwLeJhVAyj6DRgmQtY= +github.com/tursodatabase/libsql-client-go v0.0.0-20231216154754-8383a53d618f/go.mod h1:UMde0InJz9I0Le/1YIR4xsB0E2vb01MrDY6k/eNdfkg= +github.com/vertica/vertica-sql-go v1.3.3 h1:fL+FKEAEy5ONmsvya2WH5T8bhkvY27y/Ik3ReR2T+Qw= +github.com/vertica/vertica-sql-go v1.3.3/go.mod h1:jnn2GFuv+O2Jcjktb7zyc4Utlbu9YVqpHH/lx63+1M4= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -167,6 +428,12 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yashtewari/glob-intersection v0.2.0 h1:8iuHdN88yYuCzCdjt0gDe+6bAhUwBeEWqThExu54RFg= +github.com/yashtewari/glob-intersection v0.2.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok= +github.com/ydb-platform/ydb-go-genproto v0.0.0-20240126124512-dbb0e1720dbf h1:ckwNHVo4bv2tqNkgx3W3HANh3ta1j6TR5qw08J1A7Tw= +github.com/ydb-platform/ydb-go-genproto v0.0.0-20240126124512-dbb0e1720dbf/go.mod h1:Er+FePu1dNUieD+XTMDduGpQuCPssK5Q4BjF+IIXJ3I= +github.com/ydb-platform/ydb-go-sdk/v3 v3.55.1 h1:Ebo6J5AMXgJ3A438ECYotA0aK7ETqjQx9WoZvVxzKBE= +github.com/ydb-platform/ydb-go-sdk/v3 v3.55.1/go.mod h1:udNPW8eupyH/EZocecFmaSNJacKKYjzQa7cVgX5U2nc= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= @@ -175,24 +442,56 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6h go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgTNQVet8iTDW7oIk03tXHq+wkwIDnE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= +go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= @@ -204,6 +503,36 @@ google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= +howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= +lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= +lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q= +modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= +modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0= +modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI= +modernc.org/libc v1.32.0 h1:yXatHTrACp3WaKNRCoZwUK7qj5V8ep1XyY0ka4oYcNc= +modernc.org/libc v1.32.0/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= +modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ= +modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/lib/ocrypto/asym_decryption.go b/lib/ocrypto/asym_decryption.go index 426f859723..f6e75b98c3 100644 --- a/lib/ocrypto/asym_decryption.go +++ b/lib/ocrypto/asym_decryption.go @@ -26,6 +26,12 @@ type AsymDecryption struct { type PrivateKeyDecryptor interface { // Decrypt decrypts ciphertext with private key. Decrypt(data []byte) ([]byte, error) + + // DecryptWithEphemeralKey decrypts ciphertext with private key and ephemeral key, if needed. + DecryptWithEphemeralKey(data, ephemeral []byte) ([]byte, error) + + // Gets the public key + PublicKey() PublicKeyEncryptor } // FromPrivatePEM creates and returns a new AsymDecryption. @@ -93,6 +99,14 @@ func NewAsymDecryption(privateKeyInPem string) (AsymDecryption, error) { } } +func (asymDecryption AsymDecryption) PublicKey() PublicKeyEncryptor { + publicKey, ok := asymDecryption.PrivateKey.Public().(*rsa.PublicKey) + if !ok { + return nil + } + return AsymEncryption{publicKey} +} + // Decrypt decrypts ciphertext with private key. func (asymDecryption AsymDecryption) Decrypt(data []byte) ([]byte, error) { if asymDecryption.PrivateKey == nil { @@ -109,6 +123,10 @@ func (asymDecryption AsymDecryption) Decrypt(data []byte) ([]byte, error) { return bytes, nil } +func (asymDecryption AsymDecryption) DecryptWithEphemeralKey(data, _ []byte) ([]byte, error) { + return asymDecryption.Decrypt(data) +} + type ECDecryptor struct { sk *ecdh.PrivateKey salt []byte @@ -128,6 +146,18 @@ func NewSaltedECDecryptor(sk *ecdh.PrivateKey, salt, info []byte) (ECDecryptor, return ECDecryptor{sk, salt, info}, nil } +func (e ECDecryptor) PublicKey() PublicKeyEncryptor { + publicKey, ok := e.sk.Public().(*ecdh.PublicKey) + if !ok { + return nil + } + ecEncryptor, err := NewECIES(publicKey, e.salt, e.info) + if err != nil { + return nil + } + return ecEncryptor +} + func (e ECDecryptor) Decrypt(_ []byte) ([]byte, error) { // TK How to get the ephmeral key into here? return nil, errors.New("ecdh standard decrypt unimplemented") @@ -196,6 +226,29 @@ func (e ECDecryptor) DecryptWithEphemeralKey(data, ephemeral []byte) ([]byte, er return plaintext, nil } +func (e ECDecryptor) DeriveNanoTDFSymmetricKey(curve elliptic.Curve, clientEphemeralKey []byte) ([]byte, error) { + ephemeralECDSAPublicKey, err := UncompressECPubKey(curve, clientEphemeralKey) + if err != nil { + return nil, err + } + + ephemeralECDHPublicKey, err := ephemeralECDSAPublicKey.ECDH() + if err != nil { + return nil, fmt.Errorf("ecdh failure: %w", err) + } + sharedSecret, err := e.sk.ECDH(ephemeralECDHPublicKey) + if err != nil { + return nil, fmt.Errorf("there was a problem deriving a shared ECDH key: %w", err) + } + + key, err := CalculateHKDF(e.salt, sharedSecret) + if err != nil { + return nil, fmt.Errorf("DeriveNanoTDFSymmetricKey error during CalculateHKDF: %w", err) + } + + return key, nil +} + func convCurve(c ecdh.Curve) elliptic.Curve { switch c { case ecdh.P256(): diff --git a/lib/ocrypto/asym_encryption.go b/lib/ocrypto/asym_encryption.go index b0136ddb45..ff65160337 100644 --- a/lib/ocrypto/asym_encryption.go +++ b/lib/ocrypto/asym_encryption.go @@ -82,9 +82,9 @@ func FromPublicPEMWithSalt(publicKeyInPem string, salt, info []byte) (PublicKeyE if err != nil { return nil, err } - return newECIES(e, salt, info) + return NewECIES(e, salt, info) case *ecdh.PublicKey: - return newECIES(pub, salt, info) + return NewECIES(pub, salt, info) default: break } @@ -92,7 +92,7 @@ func FromPublicPEMWithSalt(publicKeyInPem string, salt, info []byte) (PublicKeyE return nil, errors.New("unsupported type of public key") } -func newECIES(pub *ecdh.PublicKey, salt, info []byte) (ECEncryptor, error) { +func NewECIES(pub *ecdh.PublicKey, salt, info []byte) (ECEncryptor, error) { ek, err := pub.Curve().GenerateKey(rand.Reader) return ECEncryptor{pub, ek, salt, info}, err } diff --git a/lib/ocrypto/ec_key_pair.go b/lib/ocrypto/ec_key_pair.go index 040b367f34..0f061c7d9a 100644 --- a/lib/ocrypto/ec_key_pair.go +++ b/lib/ocrypto/ec_key_pair.go @@ -73,6 +73,10 @@ type ECKeyPair struct { PrivateKey *ecdsa.PrivateKey } +func (kt KeyType) IsEC() bool { + return IsECKeyType(kt) +} + func IsECKeyType(kt KeyType) bool { switch kt { //nolint:exhaustive // only handle ec types case EC256Key, EC384Key, EC521Key: @@ -82,6 +86,10 @@ func IsECKeyType(kt KeyType) bool { } } +func (kt KeyType) IsRSA() bool { + return IsRSAKeyType(kt) +} + func IsRSAKeyType(kt KeyType) bool { switch kt { //nolint:exhaustive // only handle rsa types case RSA2048Key, RSA4096Key: diff --git a/service/internal/security/in_process_provider.go b/service/internal/security/in_process_provider.go index 520c5085de..8b343c0e99 100644 --- a/service/internal/security/in_process_provider.go +++ b/service/internal/security/in_process_provider.go @@ -97,8 +97,10 @@ func (k *KeyDetailsAdapter) ExportCertificate(_ context.Context) (string, error) } func (k *KeyDetailsAdapter) ProviderConfig() *policy.KeyProviderConfig { - // Provider config is not supported for this adapter. - return nil + return &policy.KeyProviderConfig{ + Manager: inProcessSystemName, + Name: "static", + } } // NewSecurityProviderAdapter creates a new adapter that implements SecurityProvider using a CryptoProvider diff --git a/service/kas/access/publicKey_test.go b/service/kas/access/publicKey_test.go index 53e9686240..b51a610312 100644 --- a/service/kas/access/publicKey_test.go +++ b/service/kas/access/publicKey_test.go @@ -182,7 +182,9 @@ func TestPublicKeyWithSecurityProvider(t *testing.T) { // Create Provider with the mock security provider delegator := trust.NewDelegatingKeyService(mockProvider, logger.CreateTestLogger(), nil) - delegator.RegisterKeyManager(mockProvider.Name(), func(_ *trust.KeyManagerFactoryOptions) (trust.KeyManager, error) { return mockProvider, nil }) + delegator.RegisterKeyManagerCtx(mockProvider.Name(), func(_ context.Context, _ *trust.KeyManagerFactoryOptions) (trust.KeyManager, error) { + return mockProvider, nil + }) kas := Provider{ KeyDelegator: delegator, KASConfig: KASConfig{ @@ -351,7 +353,7 @@ func TestStandardCertificateHandlerEmpty(t *testing.T) { inProcess := security.NewSecurityProviderAdapter(c, nil, nil) delegator := trust.NewDelegatingKeyService(inProcess, logger.CreateTestLogger(), nil) - delegator.RegisterKeyManager(inProcess.Name(), func(_ *trust.KeyManagerFactoryOptions) (trust.KeyManager, error) { + delegator.RegisterKeyManagerCtx(inProcess.Name(), func(_ context.Context, _ *trust.KeyManagerFactoryOptions) (trust.KeyManager, error) { return inProcess, nil }) diff --git a/service/kas/kas.go b/service/kas/kas.go index 95ffdc3876..0b0fd81fba 100644 --- a/service/kas/kas.go +++ b/service/kas/kas.go @@ -61,7 +61,7 @@ func NewRegistration() *serviceregistry.Service[kasconnect.AccessServiceHandler] } } - var kmgrNames []string + var kmgrs []string if kasCfg.Preview.KeyManagement { srp.Logger.Info("preview feature: key management is enabled") @@ -75,23 +75,26 @@ func NewRegistration() *serviceregistry.Service[kasconnect.AccessServiceHandler] // Configure new delegation service p.KeyDelegator = trust.NewDelegatingKeyService(NewPlatformKeyIndexer(srp.SDK, kasURL.String(), srp.Logger), srp.Logger, cacheClient) - for _, manager := range srp.KeyManagerFactories { - p.KeyDelegator.RegisterKeyManager(manager.Name, manager.Factory) - kmgrNames = append(kmgrNames, manager.Name) + if len(srp.KeyManagerFactories) > 0 { + srp.Logger.Error("kas service ignores legacy KeyManagerFactories; using KeyManagerCtxFactories instead") + } + for _, manager := range srp.KeyManagerCtxFactories { + p.KeyDelegator.RegisterKeyManagerCtx(manager.Name, manager.Factory) + kmgrs = append(kmgrs, manager.Name) } // Register Basic Key Manager - p.KeyDelegator.RegisterKeyManager(security.BasicManagerName, func(opts *trust.KeyManagerFactoryOptions) (trust.KeyManager, error) { + p.KeyDelegator.RegisterKeyManagerCtx(security.BasicManagerName, func(_ context.Context, opts *trust.KeyManagerFactoryOptions) (trust.KeyManager, error) { bm, err := security.NewBasicManager(opts.Logger, opts.Cache, kasCfg.RootKey) if err != nil { return nil, err } return bm, nil }) - kmgrNames = append(kmgrNames, security.BasicManagerName) + kmgrs = append(kmgrs, security.BasicManagerName) // Explicitly set the default manager for session key generation. // This should be configurable, e.g., defaulting to BasicManager or an HSM if available. - p.KeyDelegator.SetDefaultMode(security.BasicManagerName) // Example: default to BasicManager + p.KeyDelegator.SetDefaultMode(security.BasicManagerName, "") // Example: default to BasicManager } else { // Set up both the legacy CryptoProvider and the new SecurityProvider kasCfg.UpgradeMapToKeyring(srp.OTDF.CryptoProvider) @@ -100,14 +103,14 @@ func NewRegistration() *serviceregistry.Service[kasconnect.AccessServiceHandler] inProcessService := initSecurityProviderAdapter(p.CryptoProvider, kasCfg, srp.Logger) p.KeyDelegator = trust.NewDelegatingKeyService(inProcessService, srp.Logger, nil) - p.KeyDelegator.RegisterKeyManager(inProcessService.Name(), func(*trust.KeyManagerFactoryOptions) (trust.KeyManager, error) { + p.KeyDelegator.RegisterKeyManagerCtx(inProcessService.Name(), func(_ context.Context, _ *trust.KeyManagerFactoryOptions) (trust.KeyManager, error) { return inProcessService, nil }) // Set default for non-key-management mode - p.KeyDelegator.SetDefaultMode(inProcessService.Name()) - kmgrNames = append(kmgrNames, inProcessService.Name()) + p.KeyDelegator.SetDefaultMode(inProcessService.Name(), "") + kmgrs = append(kmgrs, inProcessService.Name()) } - srp.Logger.Info("kas registered trust.KeyManagers", slog.Any("key_managers", kmgrNames)) + srp.Logger.Info("kas registered trust.KeyManagers", slog.Any("key_managers", kmgrs)) p.SDK = srp.SDK p.Logger = srp.Logger diff --git a/service/policy/db/actions.sql.go b/service/policy/db/actions.sql.go index 38dc9171d1..22ab6b526e 100644 --- a/service/policy/db/actions.sql.go +++ b/service/policy/db/actions.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: actions.sql package db diff --git a/service/policy/db/attribute_fqn.sql.go b/service/policy/db/attribute_fqn.sql.go index e66c59a770..ad4ed6b043 100644 --- a/service/policy/db/attribute_fqn.sql.go +++ b/service/policy/db/attribute_fqn.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: attribute_fqn.sql package db diff --git a/service/policy/db/attribute_values.sql.go b/service/policy/db/attribute_values.sql.go index c5d886baa8..ab8e010d74 100644 --- a/service/policy/db/attribute_values.sql.go +++ b/service/policy/db/attribute_values.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: attribute_values.sql package db diff --git a/service/policy/db/attributes.sql.go b/service/policy/db/attributes.sql.go index 0898808948..c3b7094e04 100644 --- a/service/policy/db/attributes.sql.go +++ b/service/policy/db/attributes.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: attributes.sql package db diff --git a/service/policy/db/copyfrom.go b/service/policy/db/copyfrom.go index 999216a76b..2f450ac823 100644 --- a/service/policy/db/copyfrom.go +++ b/service/policy/db/copyfrom.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: copyfrom.go package db diff --git a/service/policy/db/db.go b/service/policy/db/db.go index d3d2e33af1..95f1a604c9 100644 --- a/service/policy/db/db.go +++ b/service/policy/db/db.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 package db diff --git a/service/policy/db/key_access_server_registry.go b/service/policy/db/key_access_server_registry.go index a7c94c22bd..1f35df3b27 100644 --- a/service/policy/db/key_access_server_registry.go +++ b/service/policy/db/key_access_server_registry.go @@ -480,6 +480,7 @@ func (c PolicyDBClient) GetKey(ctx context.Context, identifier any) (*policy.Kas if key.ProviderConfigID.Valid { providerConfig = &policy.KeyProviderConfig{} providerConfig.Id = UUIDToString(key.ProviderConfigID) + providerConfig.Manager = key.PcManager.String providerConfig.Name = key.ProviderName.String providerConfig.ConfigJson = key.PcConfig providerConfig.Metadata = &common.Metadata{} diff --git a/service/policy/db/key_access_server_registry.sql.go b/service/policy/db/key_access_server_registry.sql.go index acca6e60be..a721107292 100644 --- a/service/policy/db/key_access_server_registry.sql.go +++ b/service/policy/db/key_access_server_registry.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: key_access_server_registry.sql package db @@ -179,6 +179,7 @@ SELECT 'updated_at', kask.updated_at ) ) AS metadata, + pc.manager AS pc_manager, pc.provider_name, pc.config AS pc_config, JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', pc.metadata -> 'labels', 'created_at', pc.created_at, 'updated_at', pc.updated_at)) AS pc_metadata, @@ -215,6 +216,7 @@ type getKeyRow struct { KeyAccessServerID string `json:"key_access_server_id"` KasUri string `json:"kas_uri"` Metadata []byte `json:"metadata"` + PcManager pgtype.Text `json:"pc_manager"` ProviderName pgtype.Text `json:"provider_name"` PcConfig []byte `json:"pc_config"` PcMetadata []byte `json:"pc_metadata"` @@ -241,6 +243,7 @@ type getKeyRow struct { // 'updated_at', kask.updated_at // ) // ) AS metadata, +// pc.manager AS pc_manager, // pc.provider_name, // pc.config AS pc_config, // JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', pc.metadata -> 'labels', 'created_at', pc.created_at, 'updated_at', pc.updated_at)) AS pc_metadata, @@ -276,6 +279,7 @@ func (q *Queries) getKey(ctx context.Context, arg getKeyParams) (getKeyRow, erro &i.KeyAccessServerID, &i.KasUri, &i.Metadata, + &i.PcManager, &i.ProviderName, &i.PcConfig, &i.PcMetadata, diff --git a/service/policy/db/key_management.sql.go b/service/policy/db/key_management.sql.go index 2e7ed0de4b..6e265e292f 100644 --- a/service/policy/db/key_management.sql.go +++ b/service/policy/db/key_management.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: key_management.sql package db diff --git a/service/policy/db/models.go b/service/policy/db/models.go index 9d9f20e4c8..e0409af9e3 100644 --- a/service/policy/db/models.go +++ b/service/policy/db/models.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 package db diff --git a/service/policy/db/namespaces.sql.go b/service/policy/db/namespaces.sql.go index b70527c1e0..09ae878aa0 100644 --- a/service/policy/db/namespaces.sql.go +++ b/service/policy/db/namespaces.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: namespaces.sql package db diff --git a/service/policy/db/obligations.sql.go b/service/policy/db/obligations.sql.go index 6d5b4deffb..3d7fbecfc7 100644 --- a/service/policy/db/obligations.sql.go +++ b/service/policy/db/obligations.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: obligations.sql package db diff --git a/service/policy/db/queries/key_access_server_registry.sql b/service/policy/db/queries/key_access_server_registry.sql index 50892767f3..78b9e47b9f 100644 --- a/service/policy/db/queries/key_access_server_registry.sql +++ b/service/policy/db/queries/key_access_server_registry.sql @@ -188,6 +188,7 @@ SELECT 'updated_at', kask.updated_at ) ) AS metadata, + pc.manager AS pc_manager, pc.provider_name, pc.config AS pc_config, JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', pc.metadata -> 'labels', 'created_at', pc.created_at, 'updated_at', pc.updated_at)) AS pc_metadata, diff --git a/service/policy/db/registered_resources.sql.go b/service/policy/db/registered_resources.sql.go index cc6ede2b31..1aeba4aa96 100644 --- a/service/policy/db/registered_resources.sql.go +++ b/service/policy/db/registered_resources.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: registered_resources.sql package db diff --git a/service/policy/db/resource_mapping.sql.go b/service/policy/db/resource_mapping.sql.go index 151b55083d..be46e31ab5 100644 --- a/service/policy/db/resource_mapping.sql.go +++ b/service/policy/db/resource_mapping.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: resource_mapping.sql package db diff --git a/service/policy/db/subject_mappings.sql.go b/service/policy/db/subject_mappings.sql.go index 6915454a30..18a1a66e57 100644 --- a/service/policy/db/subject_mappings.sql.go +++ b/service/policy/db/subject_mappings.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.29.0 +// sqlc v1.30.0 // source: subject_mappings.sql package db diff --git a/service/policy/keymanagement/key_management.go b/service/policy/keymanagement/key_management.go index 7a9ca5ff2c..440da3b885 100644 --- a/service/policy/keymanagement/key_management.go +++ b/service/policy/keymanagement/key_management.go @@ -69,8 +69,11 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer // Register key managers in well-known configuration ksvc.keyManagerFactories = make([]registeredManagers, 0, len(srp.KeyManagerFactories)) + if len(srp.KeyManagerFactories) > 0 { + srp.Logger.Error("keymanagement: ignoring legacy KeyManagerFactories; using KeyManagerCtxFactories instead") + } managersMap := make(map[string]any) - for i, factory := range srp.KeyManagerFactories { + for i, factory := range srp.KeyManagerCtxFactories { rm := registeredManagers{ Name: factory.Name, Description: "Key manager: " + factory.Name, diff --git a/service/trust/delegating_key_service.go b/service/trust/delegating_key_service.go index 781c2d3ca9..0c43332e97 100644 --- a/service/trust/delegating_key_service.go +++ b/service/trust/delegating_key_service.go @@ -11,6 +11,7 @@ import ( "sync" "github.com/opentdf/platform/lib/ocrypto" + "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/cache" ) @@ -18,6 +19,21 @@ import ( type KeyManagerFactoryOptions struct { Logger *logger.Logger Cache *cache.Cache + Config *policy.KeyProviderConfig +} + +type keyManagerDesignation struct { + Manager, Name string +} + +func (kmd keyManagerDesignation) String() string { + return fmt.Sprintf("%s#%s", kmd.Manager, kmd.Name) +} + +type loadedManager struct { + keyManagerDesignation + *policy.KeyProviderConfig + KeyManager } // KeyManagerFactory defines the signature for functions that can create KeyManager instances. @@ -32,13 +48,13 @@ type DelegatingKeyService struct { // Lookup key manager by mode for a given key identifier index KeyIndex - // Lazily create key managers based on their mode + // Lazily create key managers based on their manager managerFactories map[string]KeyManagerFactoryCtx // Cache of key managers to avoid creating them multiple times - managers map[string]KeyManager + managers map[keyManagerDesignation]loadedManager - defaultMode string + defaultMode keyManagerDesignation defaultKeyManager KeyManager @@ -54,30 +70,22 @@ func NewDelegatingKeyService(index KeyIndex, l *logger.Logger, c *cache.Cache) * return &DelegatingKeyService{ index: index, managerFactories: make(map[string]KeyManagerFactoryCtx), - managers: make(map[string]KeyManager), + managers: make(map[keyManagerDesignation]loadedManager), l: l, c: c, } } -func (d *DelegatingKeyService) RegisterKeyManager(name string, factory KeyManagerFactory) { - d.mutex.Lock() - defer d.mutex.Unlock() - d.managerFactories[name] = func(_ context.Context, opts *KeyManagerFactoryOptions) (KeyManager, error) { - return factory(opts) - } -} - func (d *DelegatingKeyService) RegisterKeyManagerCtx(name string, factory KeyManagerFactoryCtx) { d.mutex.Lock() defer d.mutex.Unlock() d.managerFactories[name] = factory } -func (d *DelegatingKeyService) SetDefaultMode(name string) { +func (d *DelegatingKeyService) SetDefaultMode(manager, name string) { d.mutex.Lock() defer d.mutex.Unlock() - d.defaultMode = name + d.defaultMode = keyManagerDesignation{Manager: manager, Name: name} } // Implementing KeyIndex methods @@ -108,7 +116,8 @@ func (d *DelegatingKeyService) Decrypt(ctx context.Context, keyID KeyIdentifier, return nil, fmt.Errorf("unable to find key by ID '%s' within index %s: %w", keyID, d.index, err) } - manager, err := d.getKeyManager(ctx, keyDetails.System()) + pcfg := keyDetails.ProviderConfig() + manager, err := d.getKeyManager(ctx, pcfg) if err != nil { return nil, fmt.Errorf("unable to get key manager for system '%s': %w", keyDetails.System(), err) } @@ -122,7 +131,7 @@ func (d *DelegatingKeyService) DeriveKey(ctx context.Context, keyID KeyIdentifie return nil, fmt.Errorf("unable to find key by ID '%s' in index %s: %w", keyID, d.index, err) } - manager, err := d.getKeyManager(ctx, keyDetails.System()) + manager, err := d.getKeyManager(ctx, keyDetails.ProviderConfig()) if err != nil { return nil, fmt.Errorf("unable to get key manager for system '%s': %w", keyDetails.System(), err) } @@ -161,7 +170,7 @@ func (d *DelegatingKeyService) _defKM(ctx context.Context) (KeyManager, error) { defaultModeName := d.defaultMode d.mutex.Unlock() // Unlock before calling getKeyManager to avoid re-entrant lock on the same goroutine. - if defaultModeName == "" { + if defaultModeName.Manager == "" { return nil, errors.New("no default key manager mode configured") } @@ -169,7 +178,11 @@ func (d *DelegatingKeyService) _defKM(ctx context.Context) (KeyManager, error) { // This call to getKeyManager will handle its own locking and, // due to the check `if name == currentDefaultMode` in getKeyManager, // will error out if `defaultModeName` itself is not found, preventing recursion. - manager, err := d.getKeyManager(ctx, defaultModeName) + cfg := policy.KeyProviderConfig{ + Manager: defaultModeName.Manager, + Name: defaultModeName.Name, + } + manager, err := d.getKeyManager(ctx, &cfg) if err != nil { return nil, fmt.Errorf("failed to get default key manager for mode '%s': %w", defaultModeName, err) } @@ -187,36 +200,44 @@ func (d *DelegatingKeyService) _defKM(ctx context.Context) (KeyManager, error) { return managerToReturn, nil } -func (d *DelegatingKeyService) getKeyManager(ctx context.Context, name string) (KeyManager, error) { +func (d *DelegatingKeyService) getKeyManager(ctx context.Context, cfg *policy.KeyProviderConfig) (KeyManager, error) { d.mutex.Lock() // Check For Manager First - if manager, exists := d.managers[name]; exists { + designation := keyManagerDesignation{ + Manager: cfg.GetManager(), + Name: cfg.GetName(), + } + if manager, exists := d.managers[designation]; exists { d.mutex.Unlock() - return manager, nil + return manager.KeyManager, nil } // Check Factory - factory, factoryExists := d.managerFactories[name] + factory, factoryExists := d.managerFactories[designation.Manager] // Read defaultMode under lock for comparison. currentDefaultMode := d.defaultMode - allNames := slices.Collect(maps.Keys(d.managerFactories)) + allManagers := slices.Collect(maps.Keys(d.managerFactories)) d.mutex.Unlock() if factoryExists { - options := &KeyManagerFactoryOptions{Logger: d.l.With("key-manager", name), Cache: d.c} + options := &KeyManagerFactoryOptions{ + Logger: d.l.With("key-manager", designation.String()), + Cache: d.c, + Config: cfg, + } managerFromFactory, err := factory(ctx, options) if err != nil { - return nil, fmt.Errorf("factory for key manager '%s' failed: %w", name, err) + return nil, fmt.Errorf("factory for key manager '%s' failed: %w", designation, err) } // If err is nil (checked above) but managerFromFactory is still nil, // the factory implementation is problematic. if managerFromFactory == nil { - return nil, fmt.Errorf("factory for key manager '%s' returned nil manager without an error", name) + return nil, fmt.Errorf("factory for key manager '%s' returned nil manager without an error", designation) } d.mutex.Lock() - d.managers[name] = managerFromFactory // Cache the newly created manager + d.managers[designation] = loadedManager{designation, cfg, managerFromFactory} d.mutex.Unlock() return managerFromFactory, nil } @@ -224,9 +245,9 @@ func (d *DelegatingKeyService) getKeyManager(ctx context.Context, name string) ( // If 'name' was the defaultMode, _defKM will error if its factory is also missing. // If 'name' was not the defaultMode, we fall back to the default manager. d.l.Debug("key manager factory not found for name, attempting to use/load default", - slog.Any("key_managers", allNames), - slog.String("requested_name", name), - slog.String("configured_default_mode", currentDefaultMode), + slog.Any("key_managers", allManagers), + slog.Any("requested_name", designation), + slog.Any("configured_default_mode", currentDefaultMode), ) return d._defKM(ctx) // _defKM handles erroring if the default manager itself cannot be loaded. } diff --git a/service/trust/delegating_key_service_test.go b/service/trust/delegating_key_service_test.go index 1828c95fb7..7e6c8b1d71 100644 --- a/service/trust/delegating_key_service_test.go +++ b/service/trust/delegating_key_service_test.go @@ -259,6 +259,7 @@ func (suite *DelegatingKeyServiceTestSuite) TestListKeysWith_Legacy() { func (suite *DelegatingKeyServiceTestSuite) TestDecrypt() { mockKeyDetails := &MockKeyDetails{} + mockKeyDetails.On("ProviderConfig").Return(&policy.KeyProviderConfig{Manager: "mockManager", Name: "mock-01"}) mockKeyDetails.On("System").Return("mockManager") suite.mockIndex.On("FindKeyByID", mock.Anything, KeyIdentifier("key1")).Return(mockKeyDetails, nil) @@ -266,7 +267,7 @@ func (suite *DelegatingKeyServiceTestSuite) TestDecrypt() { mockProtectedKey.On("DecryptAESGCM", mock.Anything, mock.Anything, mock.Anything).Return([]byte("decrypted"), nil) suite.mockManagerA.On("Decrypt", mock.Anything, mockKeyDetails, []byte("ciphertext"), []byte("ephemeralKey")).Return(mockProtectedKey, nil) - suite.service.RegisterKeyManager("mockManager", func(_ *KeyManagerFactoryOptions) (KeyManager, error) { + suite.service.RegisterKeyManagerCtx("mockManager", func(_ context.Context, _ *KeyManagerFactoryOptions) (KeyManager, error) { return suite.mockManagerA, nil }) @@ -277,6 +278,7 @@ func (suite *DelegatingKeyServiceTestSuite) TestDecrypt() { func (suite *DelegatingKeyServiceTestSuite) TestDeriveKey() { mockKeyDetails := &MockKeyDetails{} + mockKeyDetails.On("ProviderConfig").Return(&policy.KeyProviderConfig{Manager: "mockManager", Name: "mock-01"}) mockKeyDetails.On("System").Return("mockManager") suite.mockIndex.On("FindKeyByID", mock.Anything, KeyIdentifier("key1")).Return(mockKeyDetails, nil) @@ -284,7 +286,7 @@ func (suite *DelegatingKeyServiceTestSuite) TestDeriveKey() { mockProtectedKey.On("Export", mock.Anything).Return([]byte("exported"), nil) suite.mockManagerA.On("DeriveKey", mock.Anything, mockKeyDetails, []byte("ephemeralKey"), elliptic.P256()).Return(mockProtectedKey, nil) - suite.service.RegisterKeyManager("mockManager", func(_ *KeyManagerFactoryOptions) (KeyManager, error) { + suite.service.RegisterKeyManagerCtx("mockManager", func(_ context.Context, _ *KeyManagerFactoryOptions) (KeyManager, error) { return suite.mockManagerA, nil }) @@ -294,10 +296,10 @@ func (suite *DelegatingKeyServiceTestSuite) TestDeriveKey() { } func (suite *DelegatingKeyServiceTestSuite) TestGenerateECSessionKey() { - suite.service.RegisterKeyManager("default", func(_ *KeyManagerFactoryOptions) (KeyManager, error) { + suite.service.RegisterKeyManagerCtx("default", func(_ context.Context, _ *KeyManagerFactoryOptions) (KeyManager, error) { return suite.mockManagerA, nil }) - suite.service.defaultMode = "default" + suite.service.defaultMode = keyManagerDesignation{Manager: "default"} suite.mockManagerA.On("GenerateECSessionKey", mock.Anything, "ephemeralPublicKey").Return(&MockEncapsulator{}, nil) encapsulator, err := suite.service.GenerateECSessionKey(context.Background(), "ephemeralPublicKey") diff --git a/test/start-up-with-containers/action.yaml b/test/start-up-with-containers/action.yaml index 231407ddf8..0d9b6d3b3b 100644 --- a/test/start-up-with-containers/action.yaml +++ b/test/start-up-with-containers/action.yaml @@ -25,7 +25,7 @@ runs: using: 'composite' steps: - name: Check out platform - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: repository: opentdf/platform # use a distinct path to avoid conflicts @@ -39,7 +39,7 @@ runs: curl https://raw.githubusercontent.com/opentdf/platform/refs/tags/keycloak-image-fix/docker-compose.yaml > otdf-test-platform/docker-compose.yaml - name: Set up go (platform's go version) id: setup-go - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: 'otdf-test-platform/service/go.mod' check-latest: false diff --git a/vault-ca.pem b/vault-ca.pem new file mode 100644 index 0000000000..4074819192 --- /dev/null +++ b/vault-ca.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBtDCCAVqgAwIBAgIUaP3288YUdnIW/5aMcbow0fcvJHMwCgYIKoZIzj0EAwIw +FzEVMBMGA1UEAxMMVmF1bHQgRGV2IENBMB4XDTI1MDUwODE0MzYyN1oXDTM1MDUw +NjE0MzcyN1owFzEVMBMGA1UEAxMMVmF1bHQgRGV2IENBMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAExnKRWQHxl6741BD8F0lA1jGXgmqCX9Om4SUBcUSKhKO7pxuE +CgptnS+LYgkAp500AmkbMddWoi9XBZCrn4EnhqOBgzCBgDAOBgNVHQ8BAf8EBAMC +AgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFM1b9POq8kRUfQZZ1C2f4jvckDkFMB8GA1UdIwQYMBaAFM1b +9POq8kRUfQZZ1C2f4jvckDkFMAoGCCqGSM49BAMCA0gAMEUCIFl/QeiTzoGnTZcQ +nF+l/2m3nIFhNJXAID7Dd7OKZY/wAiEA2sXWuqIDVq4zqTBnRVAdBwCVlTVeVsCa +3vlO+o0VJkI= +-----END CERTIFICATE----- diff --git a/vault-cert.pem b/vault-cert.pem new file mode 100644 index 0000000000..96d3aa103c --- /dev/null +++ b/vault-cert.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICAjCCAaigAwIBAgIUbSm9ceZzDph7wQMs5hJD+LWniqEwCgYIKoZIzj0EAwIw +FzEVMBMGA1UEAxMMVmF1bHQgRGV2IENBMB4XDTI1MDUwODE0MzYyN1oXDTI2MDUw +ODE0MzcyN1owGjEYMBYGA1UEAxMPZG1paGFsY2lrLmxvY2FsMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAEsIn6CA1oD+kCEO/i6xPdc2xpQew1tN/zz6d30R4XVAxW +Q6vqipEL+xT+YZSIXz7ak0bVxs0xKbXebYZ6Ic5WTqOBzjCByzAOBgNVHQ8BAf8E +BAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBSX +ofXoUwsRGhyOanjVq6UtNcjwWTAfBgNVHSMEGDAWgBTNW/TzqvJEVH0GWdQtn+I7 +3JA5BTBaBgNVHREEUzBRgglsb2NhbGhvc3SCCmxvY2FsaG9zdDSCCmxvY2FsaG9z +dDaCFWxvY2FsaG9zdC5sb2NhbGRvbWFpboIPZG1paGFsY2lrLmxvY2FshwR/AAAB +MAoGCCqGSM49BAMCA0gAMEUCIH3BFlZWLs8LOxlB421WyVmoy8STisEbwFduqxvP +yqVpAiEA8F2nXDDRSb3ic/ubtgdyBrGaeJzwP/kBH86YhHgWG7g= +-----END CERTIFICATE----- diff --git a/vault-key.pem b/vault-key.pem new file mode 100644 index 0000000000..9fc0c020c5 --- /dev/null +++ b/vault-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEICeT5+ay6H4mVk/Ba2gUV0Yuz5fVlcnTbje8EBPr505VoAoGCCqGSM49 +AwEHoUQDQgAEsIn6CA1oD+kCEO/i6xPdc2xpQew1tN/zz6d30R4XVAxWQ6vqipEL ++xT+YZSIXz7ak0bVxs0xKbXebYZ6Ic5WTg== +-----END EC PRIVATE KEY-----