Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions .github/workflows/_test-kms-live.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
name: Key vendor backend live test

# The one job behind the opt-in live workflows of the key vendor backends
# that have no emulator: integration-gcp-kms.yml (Google Cloud KMS) and
# integration-azure-key-vault.yml (Azure Key Vault). Each caller keeps its
# triggers, its opt-in and fork-PR condition on the calling job, and the
# names of its repository variables and secrets. This file holds what was
# the same in both: the secret pre-flight, the toolchain, and the
# `mise run test:live:<crate>` step.
#
# A caller gives:
#
# * `crate`: the crate. The test task is `test:live:<crate>`.
# * `name`: the name of the test step.
# * `live-key-variable`: the repository variable that turns the caller on,
# for the pre-flight message.
# * `required-secrets`: one line for each secret the test needs:
# `<secret of this workflow> <repository secret>`. The pre-flight fails
# the job when one of them is empty: a credentialed job that skips for
# want of a secret reads exactly like one that passes.
# * `live-env`: `NAME=value` lines (repository variables, not secrets)
# that the test reads.
# * the secrets, by the names below. `credentials-json` goes to a file
# only this user can read, outside the checkout, and its path goes in
# the variable `credentials-file-env` names. The `azure-*` secrets reach
# only the test step's environment.

on:
workflow_call:
inputs:
crate:
type: string
required: true
name:
type: string
required: true
live-key-variable:
type: string
required: true
required-secrets:
type: string
required: true
live-env:
type: string
required: true
credentials-file-env:
type: string
default: ''
secrets:
credentials-json:
required: false
azure-tenant-id:
required: false
azure-client-id:
required: false
azure-client-secret:
required: false

permissions:
contents: read

defaults:
run:
shell: bash

jobs:
live:
runs-on: blacksmith-16vcpu-ubuntu-2204
timeout-minutes: 30
env:
MISE_ENV: test
steps:
# Fast pre-flight: fail in seconds if a secret was rotated or cleared,
# before the toolchain install and the compile.
- name: Require the secrets
env:
LIVE_KEY_VARIABLE: ${{ inputs.live-key-variable }}
REQUIRED_SECRETS: ${{ inputs.required-secrets }}
credentials_json: ${{ secrets.credentials-json }}
azure_tenant_id: ${{ secrets.azure-tenant-id }}
azure_client_id: ${{ secrets.azure-client-id }}
azure_client_secret: ${{ secrets.azure-client-secret }}
run: |
missing=0
while read -r input secret; do
[ -n "$input" ] || continue
name="${input//-/_}"
if [ -z "${!name}" ]; then
echo "::error::$LIVE_KEY_VARIABLE is set but the secret $secret is empty"
missing=1
fi
done <<< "$REQUIRED_SECRETS"
exit "$missing"

- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
with:
version: 2026.4.0
install: true
working_directory: .
cache: true
# Must name runs-on's image; see scripts/__tests__/workflow-mise-cache-image.test.mjs
cache_key_prefix: mise-v1-ubuntu-2204

- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2

# Repository variables, not secrets. Each line must be NAME=value.
- name: Set the live key variables
env:
LIVE_ENV: ${{ inputs.live-env }}
run: |
while IFS= read -r line; do
[ -n "$line" ] || continue
if ! [[ "$line" =~ ^[A-Z][A-Z0-9_]*= ]]; then
echo "::error::live-env line is not NAME=value"
exit 1
fi
echo "$line" >> "$GITHUB_ENV"
done <<< "$LIVE_ENV"

- name: Write the credentials file
if: inputs.credentials-file-env != ''
env:
CREDENTIALS_JSON: ${{ secrets.credentials-json }}
CREDENTIALS_FILE_ENV: ${{ inputs.credentials-file-env }}
CRATE: ${{ inputs.crate }}
run: |
umask 077
printf '%s' "$CREDENTIALS_JSON" > "$RUNNER_TEMP/$CRATE-live.json"
echo "$CREDENTIALS_FILE_ENV=$RUNNER_TEMP/$CRATE-live.json" >> "$GITHUB_ENV"

- name: ${{ inputs.name }}
env:
AZURE_TENANT_ID: ${{ secrets.azure-tenant-id }}
AZURE_CLIENT_ID: ${{ secrets.azure-client-id }}
AZURE_CLIENT_SECRET: ${{ secrets.azure-client-secret }}
# The input is a constant in a caller in this repository. It is
# written into the command, not passed through the environment, so
# scripts/__tests__/crates-ci.test.mjs can see which task runs.
run: mise run test:live:${{ inputs.crate }}

- name: Remove the credentials file
if: always() && inputs.credentials-file-env != ''
env:
CRATE: ${{ inputs.crate }}
run: rm -f "$RUNNER_TEMP/$CRATE-live.json"
76 changes: 76 additions & 0 deletions .github/workflows/integration-gcp-kms.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Integration — stack-kms-gcp (Google Cloud KMS)

# stack-kms-gcp against real Google Cloud KMS (tests/live.rs). Google
# publishes no Cloud KMS emulator, so unlike the LocalStack and Vault jobs in
# tests-crates.yml this needs a real crypto key and real credentials. Every
# other stack-kms-gcp test runs in tests-crates.yml, against fixtures and an
# in-process emulator.
#
# OPT-IN. The job runs only when the repository variable
# STACK_KMS_GCP_LIVE_KEY is set, so the workflow is inert until someone sets
# up the Google Cloud side. To turn it on:
#
# 1. Create a symmetric ENCRYPT_DECRYPT crypto key for this test only.
# 2. Create a service account with roles/cloudkms.cryptoKeyEncrypterDecrypter
# on that key and nothing else, and make a JSON key for it.
# 3. Set the repository variable STACK_KMS_GCP_LIVE_KEY to the crypto key
# name (projects/<p>/locations/<l>/keyRings/<r>/cryptoKeys/<k>), and the
# repository secret STACK_KMS_GCP_SERVICE_ACCOUNT_KEY to the JSON key.
#
# Once the variable is set, a missing or empty secret FAILS the job (the
# pre-flight in _test-kms-live.yml): a credentialed job that skips for want
# of a secret reads exactly like one that passes.
#
# The job itself is _test-kms-live.yml, shared with
# integration-azure-key-vault.yml. This file keeps the triggers, the opt-in,
# the fork-PR condition and the names of the variable and the secret.
#
# Fork PRs have no secrets, so the job skips them; every other event runs.
# Enforced by scripts/__tests__/workflow-dispatch-job-conditions.test.mjs.

on:
push:
branches: [main]
paths:
- packages/stack-kms-gcp/**
- packages/stack-kms-vendor/**
- packages/stack-kms/**
- Cargo.lock
- .github/workflows/integration-gcp-kms.yml
- .github/workflows/_test-kms-live.yml
pull_request:
# Repeated verbatim: GitHub Actions does not support YAML anchors/aliases.
paths:
- packages/stack-kms-gcp/**
- packages/stack-kms-vendor/**
- packages/stack-kms/**
- Cargo.lock
- .github/workflows/integration-gcp-kms.yml
- .github/workflows/_test-kms-live.yml
workflow_dispatch: {}

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
live:
name: stack-kms-gcp against Cloud KMS
if: >-
vars.STACK_KMS_GCP_LIVE_KEY != ''
&& (github.event_name != 'pull_request'
|| github.event.pull_request.head.repo.full_name == github.repository)
uses: ./.github/workflows/_test-kms-live.yml
with:
crate: stack-kms-gcp
name: stack-kms-gcp against Cloud KMS
live-key-variable: STACK_KMS_GCP_LIVE_KEY
required-secrets: credentials-json STACK_KMS_GCP_SERVICE_ACCOUNT_KEY
live-env: STACK_KMS_GCP_LIVE_KEY=${{ vars.STACK_KMS_GCP_LIVE_KEY }}
# The test reads the service account key file this names.
credentials-file-env: GOOGLE_APPLICATION_CREDENTIALS
secrets:
credentials-json: ${{ secrets.STACK_KMS_GCP_SERVICE_ACCOUNT_KEY }}
6 changes: 4 additions & 2 deletions .github/workflows/tests-crates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ on:
- packages/stack-kms-vendor/**
- packages/stack-kms-aws/**
- packages/stack-kms-vault/**
- packages/stack-kms-gcp/**
- packages/stack-encrypt/**
- conformance/stack-encrypt/**
- packages/stack-encrypt-derive/**
Expand Down Expand Up @@ -50,6 +51,7 @@ on:
- packages/stack-kms-vendor/**
- packages/stack-kms-aws/**
- packages/stack-kms-vault/**
- packages/stack-kms-gcp/**
- packages/stack-encrypt/**
- conformance/stack-encrypt/**
- packages/stack-encrypt-derive/**
Expand Down Expand Up @@ -157,15 +159,15 @@ jobs:
# with no `version`, or a crate that uses API its dependency's packaged
# source does not have yet. stack-profile and stack-auth are in the list
# because stack-kms and stack-encrypt depend on them: without them, cargo
# resolves the published versions, which lag the tree. stack-kms-vendor, stack-kms-aws and stack-kms-vault
# resolves the published versions, which lag the tree. stack-kms-vendor, stack-kms-aws, stack-kms-vault and stack-kms-gcp
# are publishable but staged in release-plz.toml (their
# first version is published by hand); packaging them here keeps them
# publishable meanwhile. No token.
# `--allow-dirty` tolerates files earlier steps leave in the tree. Once a
# version is on crates.io, cargo warns rather than fails on a dry run of
# it.
- name: Verify the stack-* crates package cleanly for crates.io
run: cargo publish --locked --dry-run --allow-dirty -p stack-profile -p stack-auth -p stack-kms -p stack-encrypt-derive -p stack-encrypt -p stack-kms-vendor -p stack-kms-aws -p stack-kms-vault
run: cargo publish --locked --dry-run --allow-dirty -p stack-profile -p stack-auth -p stack-kms -p stack-encrypt-derive -p stack-encrypt -p stack-kms-vendor -p stack-kms-aws -p stack-kms-vault -p stack-kms-gcp

# stack-kms-aws against a real AWS KMS API: LocalStack, as a service
# (ADR-0014). The `rust` job runs the same test binary, where it skips
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/udeps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ on:
- packages/stack-kms-vendor/**
- packages/stack-kms-aws/**
- packages/stack-kms-vault/**
- packages/stack-kms-gcp/**
- packages/stack-encrypt/**
- packages/stack-encrypt-derive/**
- packages/stack-guest-abi/**
Expand All @@ -39,6 +40,7 @@ on:
- packages/stack-kms-vendor/**
- packages/stack-kms-aws/**
- packages/stack-kms-vault/**
- packages/stack-kms-gcp/**
- packages/stack-encrypt/**
- packages/stack-encrypt-derive/**
- packages/stack-guest-abi/**
Expand Down
Loading
Loading