diff --git a/.bazelrc b/.bazelrc index deff2fa8a..8f70af802 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,9 +1,3 @@ -# Sadly, some Bazel rules we depend on have no support for bzlmod yet -# Here is an (incomplete) list of rules known to not support bzlmod. -# Please extend this list as you find more. -# - rules_nixpkgs: https://github.com/tweag/rules_nixpkgs/issues/181 -common --noenable_bzlmod - # Import bazelrc presets import %workspace%/bazel/bazelrc/bazel7.bazelrc import %workspace%/bazel/bazelrc/convenience.bazelrc diff --git a/.bazelversion b/.bazelversion index a3fcc7121..eab246c06 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -7.1.0 +7.3.2 diff --git a/.github/actions/artifact_delete/delete_artifact.sh b/.github/actions/artifact_delete/delete_artifact.sh index 956927116..942304831 100755 --- a/.github/actions/artifact_delete/delete_artifact.sh +++ b/.github/actions/artifact_delete/delete_artifact.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # get_artifact_id retrieves the artifact id of # an artifact that was generated by a workflow. @@ -9,7 +9,7 @@ function get_artifact_id { -H "X-GitHub-Api-Version: 2022-11-28" \ --paginate \ "/repos/edgelesssys/constellation/actions/runs/$1/artifacts" --jq ".artifacts |= map(select(.name==\"$2\")) | .artifacts[0].id" || exit 1)" - echo "$artifact_id" + echo "$artifact_id" | tr -d "\n" } # delete_artifact_by_id deletes an artifact by its artifact id. @@ -25,14 +25,7 @@ function delete_artifact_by_id { workflow_id="$1" artifact_name="$2" -if [[ -z $workflow_id ]]; then - echo "[X] No workflow id provided." - echo "Usage: delete_artifact.sh " - exit 1 -fi - -if [[ -z $artifact_name ]]; then - echo "[X] No artifact name provided." +if [[ -z $workflow_id ]] || [[ -z $artifact_name ]]; then echo "Usage: delete_artifact.sh " exit 1 fi diff --git a/.github/actions/artifact_download/action.yml b/.github/actions/artifact_download/action.yml index 7bef0caa5..148adc258 100644 --- a/.github/actions/artifact_download/action.yml +++ b/.github/actions/artifact_download/action.yml @@ -28,7 +28,7 @@ runs: run: echo "directory=$(mktemp -d)" >> "$GITHUB_OUTPUT" - name: Download the artifact - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: ${{ inputs.name }} path: ${{ steps.tempdir.outputs.directory }} @@ -37,4 +37,4 @@ runs: shell: bash run: | mkdir -p ${{ inputs.path }} - 7zz x -p'${{ inputs.encryptionSecret }}' -t7z -o"${{ inputs.path }}" ${{ steps.tempdir.outputs.directory }}/archive.7z + 7zz x -p'${{ inputs.encryptionSecret }}' -bso0 -bsp0 -t7z -o"${{ inputs.path }}" ${{ steps.tempdir.outputs.directory }}/archive.7z diff --git a/.github/actions/artifact_upload/action.yml b/.github/actions/artifact_upload/action.yml index ec2d4d85b..50974a9fd 100644 --- a/.github/actions/artifact_upload/action.yml +++ b/.github/actions/artifact_upload/action.yml @@ -36,6 +36,7 @@ runs: - name: Create archive shell: bash run: | + set -euo pipefail shopt -s extglob paths="${{ inputs.path }}" paths=${paths%$'\n'} # Remove trailing newline @@ -47,6 +48,7 @@ runs: something_exists=true fi done + # Create an archive if files exist. # Don't create an archive file if no files are found # and warn. @@ -55,15 +57,19 @@ runs: echo "::warning:: No files/directories found with the provided path(s): ${paths}. No artifact will be uploaded." exit 0 fi + for target in ${paths} do - pushd "$(dirname "${target}")" || exit 1 - 7zz a -p'${{ inputs.encryptionSecret }}' -t7z -ms=on -mhe=on "${{ steps.tempdir.outputs.directory }}/archive.7z" "$(basename "${target}")" - popd || exit 1 + if compgen -G "${target}" > /dev/null + then + pushd "$(dirname "${target}")" + 7zz a -p'${{ inputs.encryptionSecret }}' -bso0 -bsp0 -t7z -ms=on -mhe=on "${{ steps.tempdir.outputs.directory }}/archive.7z" "$(basename "${target}")" + popd + fi done - name: Upload archive as artifact - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: ${{ inputs.name }} path: ${{ steps.tempdir.outputs.directory }}/archive.7z diff --git a/.github/actions/build_cli/action.yml b/.github/actions/build_cli/action.yml index 5102a6e18..87fd1d055 100644 --- a/.github/actions/build_cli/action.yml +++ b/.github/actions/build_cli/action.yml @@ -79,7 +79,7 @@ runs: # once it has the functionality - name: Install Cosign if: inputs.cosignPublicKey != '' && inputs.cosignPrivateKey != '' && inputs.cosignPassword != '' - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 - name: Install Rekor if: inputs.cosignPublicKey != '' && inputs.cosignPrivateKey != '' && inputs.cosignPassword != '' diff --git a/.github/actions/build_micro_service/action.yml b/.github/actions/build_micro_service/action.yml index be1c69254..e7da91e77 100644 --- a/.github/actions/build_micro_service/action.yml +++ b/.github/actions/build_micro_service/action.yml @@ -42,7 +42,7 @@ runs: - name: Docker metadata id: meta - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1 with: images: | ghcr.io/${{ github.repository }}/${{ inputs.name }} @@ -62,7 +62,7 @@ runs: - name: Build and push container image id: build-micro-service - uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 + uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 with: context: . file: ${{ inputs.dockerfile }} diff --git a/.github/actions/cdbg_deploy/action.yml b/.github/actions/cdbg_deploy/action.yml index 7917fcde1..b82a67226 100644 --- a/.github/actions/cdbg_deploy/action.yml +++ b/.github/actions/cdbg_deploy/action.yml @@ -91,6 +91,11 @@ runs: shell: bash run: | echo "::group::cdbg deploy" + on_error() { + echo "::error::cdbg deploy failed" + } + trap on_error ERR + chmod +x $GITHUB_WORKSPACE/build/cdbg cdbg deploy \ --bootstrapper "${{ github.workspace }}/build/bootstrapper" \ diff --git a/.github/actions/constellation_create/action.yml b/.github/actions/constellation_create/action.yml index 9aed0ac58..63cddf9d8 100644 --- a/.github/actions/constellation_create/action.yml +++ b/.github/actions/constellation_create/action.yml @@ -192,6 +192,13 @@ runs: run: | echo "flag=--force" | tee -a $GITHUB_OUTPUT + - name: Set conformance flag + id: set-conformance-flag + if: inputs.test == 'sonobuoy conformance' + shell: bash + run: | + echo "flag=--conformance" | tee -a $GITHUB_OUTPUT + - name: Constellation apply (Terraform) id: constellation-apply-terraform if: inputs.clusterCreation == 'terraform' @@ -204,7 +211,7 @@ runs: if: inputs.clusterCreation != 'terraform' shell: bash run: | - constellation apply --skip-phases=infrastructure --debug ${{ steps.set-force-flag.outputs.flag }} + constellation apply --skip-phases=infrastructure --debug ${{ steps.set-force-flag.outputs.flag }} ${{ steps.set-conformance-flag.outputs.flag }} - name: Get kubeconfig id: get-kubeconfig diff --git a/.github/actions/constellation_iam_create/action.yml b/.github/actions/constellation_iam_create/action.yml index eac3d0d76..a6607d982 100644 --- a/.github/actions/constellation_iam_create/action.yml +++ b/.github/actions/constellation_iam_create/action.yml @@ -27,6 +27,9 @@ inputs: # # Azure specific inputs # + azureSubscriptionID: + description: "Azure subscription ID to deploy Constellation in." + required: true azureRegion: description: "Azure region to deploy Constellation in." required: false @@ -76,13 +79,19 @@ runs: shell: bash if: inputs.cloudProvider == 'azure' run: | + extraFlags="" + + if [[ $(constellation iam create azure --help | grep -c -- --subscriptionID) -ne 0 ]]; then + extraFlags="--subscriptionID=${{ inputs.azureSubscriptionID }}" + fi + constellation iam create azure \ --region="${{ inputs.azureRegion }}" \ --resourceGroup="${{ inputs.namePrefix }}-rg" \ --servicePrincipal="${{ inputs.namePrefix }}-sp" \ --update-config \ --tf-log=DEBUG \ - --yes + --yes ${extraFlags} - name: Constellation iam create gcp shell: bash diff --git a/.github/actions/container_registry_login/action.yml b/.github/actions/container_registry_login/action.yml index ff49a2798..1c0e5d50f 100644 --- a/.github/actions/container_registry_login/action.yml +++ b/.github/actions/container_registry_login/action.yml @@ -17,7 +17,7 @@ runs: steps: - name: Use docker for logging in if: runner.os != 'macOS' - uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: registry: ${{ inputs.registry }} username: ${{ inputs.username }} diff --git a/.github/actions/container_sbom/action.yml b/.github/actions/container_sbom/action.yml index ae1402090..a100f3f6e 100644 --- a/.github/actions/container_sbom/action.yml +++ b/.github/actions/container_sbom/action.yml @@ -19,7 +19,7 @@ runs: steps: - name: Install Cosign if: inputs.cosignPublicKey != '' && inputs.cosignPrivateKey != '' && inputs.cosignPassword != '' - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 - name: Download Syft & Grype uses: ./.github/actions/install_syft_grype diff --git a/.github/actions/download_release_binaries/action.yml b/.github/actions/download_release_binaries/action.yml index 3fa79693b..a336a5e43 100644 --- a/.github/actions/download_release_binaries/action.yml +++ b/.github/actions/download_release_binaries/action.yml @@ -5,51 +5,51 @@ runs: using: "composite" steps: - name: Download CLI binaries darwin-amd64 - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: constellation-darwin-amd64 - name: Download CLI binaries darwin-arm64 - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: constellation-darwin-arm64 - name: Download CLI binaries linux-amd64 - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: constellation-linux-amd64 - name: Download CLI binaries linux-arm64 - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: constellation-linux-arm64 - name: Download CLI binaries windows-amd64 - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: constellation-windows-amd64 - name: Download Terraform module - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: terraform-module - name: Download Terraform provider binary darwin-amd64 - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: terraform-provider-constellation-darwin-amd64 - name: Download Terraform provider binary darwin-arm64 - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: terraform-provider-constellation-darwin-arm64 - name: Download Terraform provider binary linux-amd64 - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: terraform-provider-constellation-linux-amd64 - name: Download Terraform provider binary linux-arm64 - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: terraform-provider-constellation-linux-arm64 diff --git a/.github/actions/e2e_attestationconfigapi/action.yml b/.github/actions/e2e_attestationconfigapi/action.yml index a98b54670..02ec28084 100644 --- a/.github/actions/e2e_attestationconfigapi/action.yml +++ b/.github/actions/e2e_attestationconfigapi/action.yml @@ -2,9 +2,9 @@ name: E2E Attestationconfig API Test description: "Test the attestationconfig CLI is functional." inputs: - csp: - description: "Cloud provider to run tests against" - default: "azure" + attestationVariant: + description: "attestation variant to run tests against" + default: "azure-sev-snp" cosignPrivateKey: description: "Cosign private key" required: true @@ -30,4 +30,4 @@ runs: COSIGN_PRIVATE_KEY: ${{ inputs.cosignPrivateKey }} COSIGN_PASSWORD: ${{ inputs.cosignPassword }} run: | - bazel run //internal/api/attestationconfigapi/cli:cli_e2e_test -- ${{ inputs.csp }} + bazel run //internal/api/attestationconfigapi/cli:cli_e2e_test -- ${{ inputs.attestationVariant }} diff --git a/.github/actions/e2e_benchmark/action.yml b/.github/actions/e2e_benchmark/action.yml index ac223ed77..d55a4c214 100644 --- a/.github/actions/e2e_benchmark/action.yml +++ b/.github/actions/e2e_benchmark/action.yml @@ -5,7 +5,6 @@ inputs: cloudProvider: description: "Which cloud provider to use." required: true - # TODO: Create different report depending on the attestation variant attestationVariant: description: "Which attestation variant to use." required: true @@ -33,7 +32,7 @@ runs: steps: - name: Setup python - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 with: python-version: "3.10" @@ -49,25 +48,25 @@ runs: install kubestr /usr/local/bin - name: Checkout k8s-bench-suite - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 repository: "edgelesssys/k8s-bench-suite" ref: 67c64c854841165b778979375444da1c02e02210 path: k8s-bench-suite - - - name: Run FIO benchmark without caching in Azure - if: inputs.cloudProvider == 'azure' + - name: Run FIO benchmark shell: bash env: KUBECONFIG: ${{ inputs.kubeconfig }} run: | + if [[ "${{ inputs.cloudProvider }}" == "azure" ]] + then cat < - benchmarks/constellation-${{ inputs.cloudProvider }}.json + benchmarks/constellation-${{ inputs.attestationVariant }}.json name: "benchmarks-${{ inputs.artifactNameSuffix }}" encryptionSecret: ${{ inputs.encryptionSecret }} @@ -166,12 +179,10 @@ runs: - name: Get previous benchmark records from S3 shell: bash - env: - CSP: ${{ inputs.cloudProvider }} run: | - aws s3 cp --recursive ${S3_PATH} ./ --no-progress - if [[ -f constellation-${CSP}.json ]]; then - mv constellation-${CSP}.json benchmarks/constellation-${CSP}-previous.json + if aws s3 cp "${S3_PATH}/constellation-${{ inputs.attestationVariant }}.json" ./ --no-progress + then + mv "constellation-${{ inputs.attestationVariant }}.json" "benchmarks/constellation-${{ inputs.attestationVariant }}-previous.json" else echo "::warning::Couldn't retrieve previous benchmark records from s3" fi @@ -180,15 +191,15 @@ runs: shell: bash env: # Paths to benchmark results as JSON of the previous run and the current run - PREV_BENCH: benchmarks/constellation-${{ inputs.cloudProvider }}-previous.json - CURR_BENCH: benchmarks/constellation-${{ inputs.cloudProvider }}.json + PREV_BENCH: benchmarks/constellation-${{ inputs.attestationVariant }}-previous.json + CURR_BENCH: benchmarks/constellation-${{ inputs.attestationVariant }}.json run: | if [[ -f "$PREV_BENCH" ]]; then # Fails if the results are outside the threshold range python .github/actions/e2e_benchmark/evaluate/compare.py >> $GITHUB_STEP_SUMMARY fi - - name: Upload benchmark results to opensearch + - name: Upload benchmark results to OpenSearch if: (!env.ACT) shell: bash env: @@ -198,14 +209,12 @@ runs: run: | curl -XPOST \ -u "${OPENSEARCH_USER}:${OPENSEARCH_PWD}" \ - "${OPENSEARCH_DOMAIN}/benchmarks-${{ inputs.cloudProvider }}-$(date '+%Y')"/_doc \ - --data-binary @benchmarks/constellation-${{ inputs.cloudProvider }}.json \ + "${OPENSEARCH_DOMAIN}/benchmarks-${{ inputs.attestationVariant }}-$(date '+%Y')"/_doc \ + --data-binary @benchmarks/constellation-${{ inputs.attestationVariant }}.json \ -H 'Content-Type: application/json' - name: Update benchmark records in S3 if: github.ref_name == 'main' shell: bash - env: - CSP: ${{ inputs.cloudProvider }} run: | - aws s3 cp benchmarks/constellation-${CSP}.json ${S3_PATH}/constellation-${CSP}.json + aws s3 cp benchmarks/constellation-${{ inputs.attestationVariant }}.json ${S3_PATH}/constellation-${{ inputs.attestationVariant }}.json diff --git a/.github/actions/e2e_benchmark/evaluate/compare.py b/.github/actions/e2e_benchmark/evaluate/compare.py index 59d10a186..87faac09e 100644 --- a/.github/actions/e2e_benchmark/evaluate/compare.py +++ b/.github/actions/e2e_benchmark/evaluate/compare.py @@ -94,18 +94,18 @@ class BenchmarkComparer: raise ValueError('Failed reading benchmark file: {e}'.format(e=e)) try: - name = bench_curr['provider'] + name = bench_curr['attestationVariant'] except KeyError: raise ValueError( - 'Current benchmark record file does not contain provider.') + 'Current benchmark record file does not contain attestationVariant.') try: - prev_name = bench_prev['provider'] + prev_name = bench_prev['attestationVariant'] except KeyError: raise ValueError( - 'Previous benchmark record file does not contain provider.') + 'Previous benchmark record file does not contain attestationVariant.') if name != prev_name: raise ValueError( - 'Cloud providers of previous and current benchmark data do not match.') + 'Cloud attestationVariants of previous and current benchmark data do not match.') if 'fio' not in bench_prev.keys() or 'fio' not in bench_curr.keys(): raise ValueError('Benchmarks do not both contain fio records.') diff --git a/.github/actions/e2e_benchmark/evaluate/parse.py b/.github/actions/e2e_benchmark/evaluate/parse.py index fedce5c70..8d9353343 100644 --- a/.github/actions/e2e_benchmark/evaluate/parse.py +++ b/.github/actions/e2e_benchmark/evaluate/parse.py @@ -7,7 +7,7 @@ from datetime import datetime from evaluators import fio, knb -def configure() -> Tuple[str, str, str, str | None, str, str, str, str]: +def configure() -> Tuple[str, str, str, str, str | None, str, str, str, str]: """Read the benchmark data paths. Expects ENV vars (required): @@ -25,27 +25,29 @@ def configure() -> Tuple[str, str, str, str | None, str, str, str, str]: """ base_path = os.environ.get('BENCH_RESULTS', None) csp = os.environ.get('CSP', None) + attestation_variant = os.environ.get('ATTESTATION_VARIANT', None) out_dir = os.environ.get('BDIR', None) - if not base_path or not csp or not out_dir: + if not base_path or not csp or not out_dir or not attestation_variant: raise TypeError( - 'ENV variables BENCH_RESULTS, CSP, BDIR are required.') + 'ENV variables BENCH_RESULTS, CSP, BDIR, ATTESTATION_VARIANT are required.') ext_provider_name = os.environ.get('EXT_NAME', None) commit_hash = os.environ.get('GITHUB_SHA', 'N/A') commit_ref = os.environ.get('GITHUB_REF_NAME', 'N/A') actor = os.environ.get('GITHUB_ACTOR', 'N/A') workflow = os.environ.get('GITHUB_WORKFLOW', 'N/A') - return base_path, csp, out_dir, ext_provider_name, commit_hash, commit_ref, actor, workflow + return base_path, csp, attestation_variant, out_dir, ext_provider_name, commit_hash, commit_ref, actor, workflow class BenchmarkParser: - def __init__(self, base_path, csp, out_dir, ext_provider_name=None, commit_hash="N/A", commit_ref="N/A", actor="N/A", workflow="N/A"): + def __init__(self, base_path, csp, attestation_variant, out_dir, ext_provider_name=None, commit_hash="N/A", commit_ref="N/A", actor="N/A", workflow="N/A"): self.base_path = base_path self.csp = csp + self.attestation_variant = attestation_variant self.out_dir = out_dir self.ext_provider_name = ext_provider_name if not self.ext_provider_name: - self.ext_provider_name = f'constellation-{csp}' + self.ext_provider_name = f'constellation-{attestation_variant}' self.commit_hash = commit_hash self.commit_ref = commit_ref self.actor = actor @@ -88,6 +90,7 @@ class BenchmarkParser: }, '@timestamp': str(timestamp), 'provider': self.ext_provider_name, + 'attestationVariant': self.attestation_variant, 'fio': {}, 'knb': {}} @@ -101,8 +104,8 @@ class BenchmarkParser: def main(): - base_path, csp, out_dir, ext_provider_name, commit_hash, commit_ref, actor, workflow = configure() - p = BenchmarkParser(base_path, csp, out_dir, ext_provider_name, + base_path, csp, attestation_variant, out_dir, ext_provider_name, commit_hash, commit_ref, actor, workflow = configure() + p = BenchmarkParser(base_path, csp, attestation_variant, out_dir, ext_provider_name, commit_hash, commit_ref, actor, workflow) p.parse() diff --git a/.github/actions/e2e_benchmark/evaluate/requirements.txt b/.github/actions/e2e_benchmark/evaluate/requirements.txt index 7f2f1bd57..ea9316757 100644 --- a/.github/actions/e2e_benchmark/evaluate/requirements.txt +++ b/.github/actions/e2e_benchmark/evaluate/requirements.txt @@ -1,3 +1,3 @@ numpy ==1.26.4 matplotlib ==3.8.3 -Pillow ==10.2.0 \ No newline at end of file +Pillow ==10.3.0 \ No newline at end of file diff --git a/.github/actions/e2e_benchmark/fio.ini b/.github/actions/e2e_benchmark/fio.ini index c956bc7b4..33960341a 100644 --- a/.github/actions/e2e_benchmark/fio.ini +++ b/.github/actions/e2e_benchmark/fio.ini @@ -7,7 +7,7 @@ size=10Gi time_based=1 group_reporting thread -cpus_allowed=1 +cpus_allowed=0 [read_iops] diff --git a/.github/actions/e2e_cleanup_timeframe/action.yml b/.github/actions/e2e_cleanup_timeframe/action.yml index 869148705..bfe40cbf3 100644 --- a/.github/actions/e2e_cleanup_timeframe/action.yml +++ b/.github/actions/e2e_cleanup_timeframe/action.yml @@ -31,11 +31,13 @@ runs: with: service_account: "destroy-e2e@constellation-e2e.iam.gserviceaccount.com" - - name: Install 7zip + - name: Install tools uses: ./.github/actions/setup_bazel_nix with: nixTools: | _7zz + terraform + - name: Run cleanup run: ./.github/actions/e2e_cleanup_timeframe/e2e-cleanup.sh shell: bash diff --git a/.github/actions/e2e_mini/action.yml b/.github/actions/e2e_mini/action.yml index 2efd3a9a4..45352203e 100644 --- a/.github/actions/e2e_mini/action.yml +++ b/.github/actions/e2e_mini/action.yml @@ -11,6 +11,9 @@ inputs: azureTenantID: description: "Azure tenant to use for login with OIDC" required: true + azureIAMCredentials: + description: "Azure IAM credentials used for cleaning up resources" + required: true registry: description: "Container registry to use" required: true @@ -22,7 +25,7 @@ runs: using: "composite" steps: - name: Install terraform - uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1 + uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 with: terraform_wrapper: false @@ -38,9 +41,25 @@ runs: - name: MiniConstellation E2E shell: bash + id: e2e-test env: ARM_CLIENT_ID: ${{ inputs.azureClientID }} ARM_SUBSCRIPTION_ID: ${{ inputs.azureSubscriptionID }} ARM_TENANT_ID: ${{ inputs.azureTenantID }} run: | bazel run --test_timeout=14400 //e2e/miniconstellation:push_remote_test + + - name: Log in to azure + # only log in if e2e test failed or if the run was cancelled + if: (failure() && steps.e2e-test.conclusion == 'failure') || cancelled() + uses: ./.github/actions/login_azure + with: + azure_credentials: ${{ inputs.azureIAMCredentials }} + + - name: Clean up after failure + shell: bash + # clean up if e2e test failed or if the run was cancelled + if: (failure() && steps.e2e-test.conclusion == 'failure') || cancelled() + run: | + echo "[*] Deleting resource group ${{ steps.e2e-test.outputs.rgname }}" + az group delete -y --resource-group "${{ steps.e2e-test.outputs.rgname }}" diff --git a/.github/actions/e2e_sonobuoy/action.yml b/.github/actions/e2e_sonobuoy/action.yml index 6d03e9072..5671e7c9c 100644 --- a/.github/actions/e2e_sonobuoy/action.yml +++ b/.github/actions/e2e_sonobuoy/action.yml @@ -48,6 +48,12 @@ runs: sonobuoy results *_sonobuoy_*.tar.gz sonobuoy results *_sonobuoy_*.tar.gz --mode detailed | jq 'select(.status!="passed")' | jq 'select(.status!="skipped")' || true + - name: Cleanup sonobuoy deployment + env: + KUBECONFIG: ${{ inputs.kubeconfig }} + shell: bash + run: sonobuoy delete --wait + - name: Upload test results if: always() && !env.ACT uses: ./.github/actions/artifact_upload @@ -64,7 +70,7 @@ runs: - name: Publish test results if: (!env.ACT) && contains(inputs.sonobuoyTestSuiteCmd, '--plugin e2e') - uses: mikepenz/action-junit-report@9379f0ccddcab154835d4e2487555ee79614fe95 # v4.2.1 + uses: mikepenz/action-junit-report@db71d41eb79864e25ab0337e395c352e84523afe # v4.3.1 with: report_paths: "**/junit_01.xml" fail_on_failure: true diff --git a/.github/actions/e2e_test/action.yml b/.github/actions/e2e_test/action.yml index 05ccbd016..c2cca982d 100644 --- a/.github/actions/e2e_test/action.yml +++ b/.github/actions/e2e_test/action.yml @@ -46,6 +46,9 @@ inputs: description: "AWS OpenSearch User to upload the benchmark results." awsOpenSearchPwd: description: "AWS OpenSearch Password to upload the benchmark results." + azureSubscriptionID: + description: "Azure subscription ID to deploy Constellation in." + required: true azureClusterCreateCredentials: description: "Azure credentials authorized to create a Constellation cluster." required: true @@ -53,7 +56,7 @@ inputs: description: "Azure credentials authorized to create an IAM configuration." required: true test: - description: "The test to run. Can currently be one of [sonobuoy full, sonobuoy quick, autoscaling, lb, perf-bench, verify, recover, malicious join, nop, upgrade]." + description: "The test to run. Can currently be one of [sonobuoy full, sonobuoy quick, sonobuoy conformance, autoscaling, lb, perf-bench, verify, recover, malicious join, nop, upgrade]." required: true sonobuoyTestSuiteCmd: description: "The sonobuoy test suite to run." @@ -103,7 +106,7 @@ runs: using: "composite" steps: - name: Check input - if: (!contains(fromJson('["sonobuoy full", "sonobuoy quick", "autoscaling", "perf-bench", "verify", "lb", "recover", "malicious join", "s3proxy", "nop", "upgrade"]'), inputs.test)) + if: (!contains(fromJson('["sonobuoy full", "sonobuoy quick", "sonobuoy conformance", "autoscaling", "perf-bench", "verify", "lb", "recover", "malicious join", "s3proxy", "nop", "upgrade"]'), inputs.test)) shell: bash run: | echo "::error::Invalid input for test field: ${{ inputs.test }}" @@ -249,6 +252,7 @@ runs: attestationVariant: ${{ inputs.attestationVariant }} namePrefix: ${{ steps.create-prefix.outputs.prefix }} awsZone: ${{ inputs.regionZone || 'us-east-2c' }} + azureSubscriptionID: ${{ inputs.azureSubscriptionID }} azureRegion: ${{ inputs.regionZone || steps.pick-az-region.outputs.region }} gcpProjectID: ${{ inputs.gcpProject }} gcpZone: ${{ inputs.regionZone || 'europe-west3-b' }} @@ -348,6 +352,15 @@ runs: artifactNameSuffix: ${{ steps.create-prefix.outputs.prefix }} encryptionSecret: ${{ inputs.encryptionSecret }} + - name: Run sonobuoy conformance + if: inputs.test == 'sonobuoy conformance' + uses: ./.github/actions/e2e_sonobuoy + with: + sonobuoyTestSuiteCmd: "--plugin e2e --mode certified-conformance" + kubeconfig: ${{ steps.constellation-create.outputs.kubeconfig }} + artifactNameSuffix: ${{ steps.create-prefix.outputs.prefix }} + encryptionSecret: ${{ inputs.encryptionSecret }} + - name: Run autoscaling test if: inputs.test == 'autoscaling' uses: ./.github/actions/e2e_autoscaling diff --git a/.github/actions/e2e_verify/action.yml b/.github/actions/e2e_verify/action.yml index f330751f5..22b86e893 100644 --- a/.github/actions/e2e_verify/action.yml +++ b/.github/actions/e2e_verify/action.yml @@ -68,9 +68,9 @@ runs: case "${{ inputs.attestationVariant }}" in - "azure-sev-snp"|"aws-sev-snp"|"gcp-sev-snp") + "azure-sev-snp"|"azure-tdx"|"aws-sev-snp"|"gcp-sev-snp") echo "Extracting TCB versions for API update" - constellation verify --cluster-id "${clusterID}" --node-endpoint localhost:9090 -o json > "snp-report-${node}.json" + constellation verify --cluster-id "${clusterID}" --node-endpoint localhost:9090 -o json > "attestation-report-${node}.json" ;; *) constellation verify --cluster-id "${clusterID}" --node-endpoint localhost:9090 @@ -88,22 +88,24 @@ runs: aws-region: eu-central-1 - name: Upload extracted TCBs - if: github.ref_name == 'main' && (inputs.attestationVariant == 'azure-sev-snp' || inputs.attestationVariant == 'aws-sev-snp' || inputs.attestationVariant == 'gcp-sev-snp') + if: github.ref_name == 'main' && (inputs.attestationVariant == 'azure-sev-snp' || inputs.attestationVariant == 'azure-tdx' || inputs.attestationVariant == 'aws-sev-snp' || inputs.attestationVariant == 'gcp-sev-snp') shell: bash env: COSIGN_PASSWORD: ${{ inputs.cosignPassword }} COSIGN_PRIVATE_KEY: ${{ inputs.cosignPrivateKey }} run: | - reports=(snp-report-*.json) - if [ -z ${#reports[@]} ]; then - exit 1 - fi + reports=attestation-report-*.json - attestationVariant=${{ inputs.attestationVariant }} - cloudProvider=${attestationVariant%%-*} - - for file in "${reports[@]}"; do - path=$(realpath "${file}") - cat "${path}" - bazel run //internal/api/attestationconfigapi/cli -- upload "${cloudProvider}" snp-report "${path}" + # bazel run changes the working directory + # convert the relative paths to absolute paths to avoid issues + absolute_reports="" + for report in ${reports}; do + absolute_reports="${absolute_reports} $(realpath "${report}")" done + + report=$(bazel run //internal/api/attestationconfigapi/cli -- compare ${{ inputs.attestationVariant }} ${absolute_reports}) + + path=$(realpath "${report}") + cat "${path}" + + bazel run //internal/api/attestationconfigapi/cli -- upload ${{ inputs.attestationVariant }} attestation-report "${path}" diff --git a/.github/actions/find_latest_image/action.yml b/.github/actions/find_latest_image/action.yml index 71dfd2180..2c15f2327 100644 --- a/.github/actions/find_latest_image/action.yml +++ b/.github/actions/find_latest_image/action.yml @@ -26,13 +26,13 @@ runs: steps: - name: Checkout head if: inputs.imageVersion == '' && inputs.git-ref == 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Checkout ref if: inputs.imageVersion == '' && inputs.git-ref != 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.git-ref }} @@ -43,6 +43,8 @@ runs: role-to-assume: arn:aws:iam::795746500882:role/GithubConstellationVersionsAPIRead aws-region: eu-central-1 + - uses: ./.github/actions/setup_bazel_nix + - name: Find latest image id: find-latest-image if: inputs.imageVersion == '' diff --git a/.github/actions/gcpccm_vers_to_build/findvers.sh b/.github/actions/gcpccm_vers_to_build/findvers.sh index dd35c582a..1b148d4f4 100755 --- a/.github/actions/gcpccm_vers_to_build/findvers.sh +++ b/.github/actions/gcpccm_vers_to_build/findvers.sh @@ -82,4 +82,4 @@ for major in "${allMajorVersions[@]}"; do done # Print one elem per line | quote elems | create array | remove empty elems and print compact. -printf '%s' "${versionsToBuild[@]}" | jq -R | jq -s | jq -c 'map(select(length > 0))' +printf '%s\n' "${versionsToBuild[@]}" | jq -R | jq -s | jq -c 'map(select(length > 0))' diff --git a/.github/actions/login_azure/action.yml b/.github/actions/login_azure/action.yml index 4e370b27b..c7934d19f 100644 --- a/.github/actions/login_azure/action.yml +++ b/.github/actions/login_azure/action.yml @@ -10,6 +10,6 @@ runs: # As described at: # https://github.com/Azure/login#configure-deployment-credentials - name: Login to Azure - uses: azure/login@6b2456866fc08b011acb422a92a4aa20e2c4de32 # v2.1.0 + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 with: creds: ${{ inputs.azure_credentials }} diff --git a/.github/actions/login_gcp/action.yml b/.github/actions/login_gcp/action.yml index daf0e6685..f6c19524f 100644 --- a/.github/actions/login_gcp/action.yml +++ b/.github/actions/login_gcp/action.yml @@ -20,11 +20,11 @@ runs: echo "GOOGLE_CLOUD_PROJECT=" >> "$GITHUB_ENV" - name: Authorize GCP access - uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3 + uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2.1.7 with: - workload_identity_provider: projects/796962942582/locations/global/workloadIdentityPools/constellation-ci-pool/providers/constellation-ci-provider + workload_identity_provider: projects/1052692473304/locations/global/workloadIdentityPools/constellation-ci-pool/providers/constellation-ci-provider service_account: ${{ inputs.service_account }} # Even if preinstalled in Github Actions runner image, this setup does some magic authentication required for gsutil. - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@98ddc00a17442e89a24bbf282954a3b65ce6d200 # v2.1.0 + uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 diff --git a/.github/actions/notify_teams/README.md b/.github/actions/notify_teams/README.md new file mode 100644 index 000000000..5fb6d724b --- /dev/null +++ b/.github/actions/notify_teams/README.md @@ -0,0 +1,27 @@ +# notify Teams action + +This action is used to send a message to our Teams channel in case of a failure in the CI/CD pipeline. +The action will automatically choose an engineer to assign to the issue and tag them in the message. + +Engineers are identified by their GitHub username and bound to a Microsoft Teams ID in `.attachments[0].content.msteams.entities`. +To add a new engineer, add a new entry to the entity list in the format: + +```json +{ + "type": "mention", + "text": "${github_username}", + "mentioned": { + "id": "${msteams_id}", + "name": "${name}" + } +} +``` + +Where `${github_username}` is the GitHub username of the engineer, `${msteams_id}` is the Microsoft Teams ID of the engineer, and `${name}` is the name of the engineer. +To find the Microsoft Teams ID use the following command: + +```bash +az ad user show --id ${email} --query id +``` + +Where `${email}` is the email address of the engineer. diff --git a/.github/actions/notify_teams/action.yml b/.github/actions/notify_teams/action.yml index 956a3a889..e94a266a9 100644 --- a/.github/actions/notify_teams/action.yml +++ b/.github/actions/notify_teams/action.yml @@ -25,7 +25,7 @@ runs: continue-on-error: true shell: bash run: | - cp .github/teams_payload_template.json teams_payload.json + cp .github/actions/notify_teams/teams_payload_template.json teams_payload.json # Add workflow name to the notification yq -oj -iP '.attachments[0].content.body[0].columns[1].items[0].text = "${{ inputs.title }}"' teams_payload.json diff --git a/.github/teams_payload_template.json b/.github/actions/notify_teams/teams_payload_template.json similarity index 96% rename from .github/teams_payload_template.json rename to .github/actions/notify_teams/teams_payload_template.json index 145d6a28c..fbef4d36e 100644 --- a/.github/teams_payload_template.json +++ b/.github/actions/notify_teams/teams_payload_template.json @@ -1,5 +1,5 @@ { - "type": "message", + "type": "AdaptiveCard", "attachments": [ { "contentType": "application/vnd.microsoft.card.adaptive", @@ -61,10 +61,10 @@ }, { "type": "mention", - "text": "malt3", + "text": "burgerdev", "mentioned": { - "id": "3012fe21-cff7-499d-88cf-48cf12f2e90c", - "name": "Malte Poll" + "id": "c9efc581-58ca-4da6-93ce-79f69f89deeb", + "name": "Markus Rudy" } } ] diff --git a/.github/actions/pick_assignee/action.yml b/.github/actions/pick_assignee/action.yml index 3e9cd4d64..e6838c89e 100644 --- a/.github/actions/pick_assignee/action.yml +++ b/.github/actions/pick_assignee/action.yml @@ -15,8 +15,6 @@ runs: run: | possibleAssignees=( "elchead" - "malt3" - "3u13r" "daniel-weisse" "msanft" "burgerdev" diff --git a/.github/actions/publish_helmchart/action.yml b/.github/actions/publish_helmchart/action.yml index 4c7a8eb57..6e8a9f762 100644 --- a/.github/actions/publish_helmchart/action.yml +++ b/.github/actions/publish_helmchart/action.yml @@ -13,7 +13,7 @@ runs: using: "composite" steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: edgelesssys/helm ref: main @@ -29,7 +29,7 @@ runs: echo version=$(yq eval ".version" ${{ inputs.chartPath }}/Chart.yaml) | tee -a $GITHUB_OUTPUT - name: Create pull request - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 + uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 with: path: helm branch: "release/s3proxy/${{ steps.update-chart-version.outputs.version }}" diff --git a/.github/actions/select_image/action.yml b/.github/actions/select_image/action.yml index 391814256..e36e145ed 100644 --- a/.github/actions/select_image/action.yml +++ b/.github/actions/select_image/action.yml @@ -3,15 +3,15 @@ description: Resolve string presets and shortpaths to shortpaths only inputs: osImage: - description: "Shortpath or main-debug or release-stable" + description: "Shortpath, main-debug, main-nightly, or release-stable" required: true outputs: osImage: - description: "Shortpath of for input string, original input if that was already a shortpath" + description: "Shortpath of input string, original input if that was already a shortpath" value: ${{ steps.set-output.outputs.osImage }} isDebugImage: - description: "Input represents a debug image or not" + description: "Input is a debug image or not" value: ${{ steps.set-output.outputs.isDebugImage }} runs: @@ -27,7 +27,7 @@ runs: id: input-is-preset shell: bash run: | - if [[ "${{ inputs.osImage }}" == "ref/main/stream/debug/?" || "${{ inputs.osImage }}" == "ref/release/stream/stable/?" ]]; then + if [[ "${{ inputs.osImage }}" == "ref/main/stream/debug/?" || "${{ inputs.osImage }}" == "ref/main/stream/nightly/?" || "${{ inputs.osImage }}" == "ref/release/stream/stable/?" ]]; then echo "result=true" | tee -a "$GITHUB_OUTPUT" else echo "result=false" | tee -a "$GITHUB_OUTPUT" @@ -43,6 +43,10 @@ runs: echo "ref=$(echo $REFSTREAM | cut -d/ -f2)" | tee -a "$GITHUB_OUTPUT" echo "stream=$(echo $REFSTREAM | cut -d/ -f4)" | tee -a "$GITHUB_OUTPUT" + - name: Setup Bazel & Nix + if: steps.input-is-preset.outputs.result == 'true' + uses: ./.github/actions/setup_bazel_nix + - name: Find latest image if: steps.input-is-preset.outputs.result == 'true' id: find-latest-image diff --git a/.github/actions/setup_bazel_nix/action.yml b/.github/actions/setup_bazel_nix/action.yml index 8ef8403d6..87a2d1802 100644 --- a/.github/actions/setup_bazel_nix/action.yml +++ b/.github/actions/setup_bazel_nix/action.yml @@ -113,7 +113,9 @@ runs: - name: Install nix if: steps.check_inputs.outputs.nixPreinstalled == 'false' - uses: cachix/install-nix-action@8887e596b4ee1134dae06b98d573bd674693f47c # v26 + uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30 + with: + install_url: "https://releases.nixos.org/nix/nix-2.25.2/install" - name: Set $USER if not set shell: bash diff --git a/.github/actions/terraform_apply/action.yml b/.github/actions/terraform_apply/action.yml index ef6e92020..885950ac9 100644 --- a/.github/actions/terraform_apply/action.yml +++ b/.github/actions/terraform_apply/action.yml @@ -26,10 +26,9 @@ runs: "gcpSEVES") attestationVariant="gcp-sev-es" ;; - # TODO(msanft): Enable once stable GCP SEV-SNP images exist. - # "gcpSEVSNP") - # attestationVariant="gcp-sev-snp" - # ;; + "gcpSEVSNP") + attestationVariant="gcp-sev-snp" + ;; *) echo "Unknown attestation variant: $(yq '.attestation | keys | .[0]' constellation-conf.yaml)" exit 1 @@ -45,7 +44,7 @@ runs: } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } } } diff --git a/.github/actions/upload_terraform_module/action.yml b/.github/actions/upload_terraform_module/action.yml index bab20a0e0..18dd61280 100644 --- a/.github/actions/upload_terraform_module/action.yml +++ b/.github/actions/upload_terraform_module/action.yml @@ -15,7 +15,7 @@ runs: zip -r terraform-module.zip terraform-module - name: Upload artifact - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: terraform-module path: terraform-module.zip @@ -23,4 +23,4 @@ runs: - name: Cleanup Terraform module dir shell: bash run: | - rm -f terraform-module terraform-module.zip + rm -rf terraform-module terraform-module.zip diff --git a/.github/actions/versionsapi/Dockerfile b/.github/actions/versionsapi/Dockerfile deleted file mode 100644 index 6c735fcee..000000000 --- a/.github/actions/versionsapi/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM golang:1.22.3@sha256:b1e05e2c918f52c59d39ce7d5844f73b2f4511f7734add8bb98c9ecdd4443365 as builder - -# Download project root dependencies -WORKDIR /workspace -COPY go.mod go.mod -COPY go.sum go.sum -# cache deps before building and copying source so that we don't need to re-download as much -# and so that source changes don't invalidate our downloaded layer -RUN go mod download - -COPY . . - -# Build -WORKDIR /workspace/internal/api/versionsapi/cli -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o versionsapi . - -FROM scratch as release - -COPY --from=builder /workspace/internal/api/versionsapi/cli/versionsapi . - -CMD ["/notIntendedToBeExecuted"] diff --git a/.github/actions/versionsapi/action.yml b/.github/actions/versionsapi/action.yml index fd236dec1..817064334 100644 --- a/.github/actions/versionsapi/action.yml +++ b/.github/actions/versionsapi/action.yml @@ -52,19 +52,12 @@ outputs: runs: using: composite steps: - - name: Get versionsapi binary - shell: bash - # TODO: This should probably be `bazel run`. - run: | - containerID=$(docker create "ghcr.io/edgelesssys/constellation/versionsapi-ci-cli:latest") - docker cp ${containerID}:/versionsapi . - - name: Run versionsapi id: run shell: bash run: | out=$( - ./versionsapi \ + bazel run //internal/api/versionsapi/cli:cli -- \ ${{ inputs.command }} \ ${{ inputs.ref != '' && format('--ref="{0}"', inputs.ref) || '' }} \ ${{ inputs.stream != '' && format('--stream="{0}"', inputs.stream) || '' }} \ diff --git a/.github/workflows/assign_reviewer.yml b/.github/workflows/assign_reviewer.yml index 0ca55fcf4..ed87296d8 100644 --- a/.github/workflows/assign_reviewer.yml +++ b/.github/workflows/assign_reviewer.yml @@ -2,7 +2,13 @@ name: Assign Reviewer on: pull_request: - types: ["labeled"] + types: + - opened + - reopened + - edited + - synchronize + - review_request_removed + - labeled permissions: pull-requests: write @@ -10,9 +16,9 @@ permissions: jobs: assign_reviewer: runs-on: ubuntu-latest - if: github.event.label.name == 'dependencies' && github.event.pull_request.user.login == 'app/renovate' + if: contains(github.event.pull_request.labels.*.name, 'dependencies') && toJson(github.event.pull_request.requested_reviewers) == '[]' && github.event.pull_request.user.login == 'renovate[bot]' steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Pick assignee id: pick-assignee uses: ./.github/actions/pick_assignee diff --git a/.github/workflows/aws-snp-launchmeasurement.yml b/.github/workflows/aws-snp-launchmeasurement.yml index 6acbe0e07..1c2c981a2 100644 --- a/.github/workflows/aws-snp-launchmeasurement.yml +++ b/.github/workflows/aws-snp-launchmeasurement.yml @@ -8,26 +8,20 @@ on: jobs: run: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout repository - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.head_ref }} path: constellation - - name: Install necessary tools - run: | - sudo apt-get update - sudo apt-get install -y python3 python3-pip - sudo python3 -m pip install --user --require-hashes -r constellation/.github/workflows/aws-snp-launchmeasurements-requirements.txt - - name: Install Nix - uses: cachix/install-nix-action@8887e596b4ee1134dae06b98d573bd674693f47c # v26 + uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30 - name: Download Firmware release id: download-firmware - uses: robinraju/release-downloader@c39a3b234af58f0cf85888573d361fb6fa281534 # v1.10 + uses: robinraju/release-downloader@a96f54c1b5f5e09e47d9504526e96febd949d4c2 # v1.11 with: repository: aws/uefi latest: true @@ -50,7 +44,7 @@ jobs: echo "ovmfPath=${ovmfPath}" | tee -a "$GITHUB_OUTPUT" popd || exit 1 - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: virtee/sev-snp-measure-go.git ref: e42b6f8991ed5a671d5d1e02a6b61f6373f9f8d8 diff --git a/.github/workflows/aws-snp-launchmeasurements-requirements.txt b/.github/workflows/aws-snp-launchmeasurements-requirements.txt deleted file mode 100644 index 6d4195056..000000000 --- a/.github/workflows/aws-snp-launchmeasurements-requirements.txt +++ /dev/null @@ -1,106 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --generate-hashes --output-file=aws-snp-launchmeasurements-requirements.txt input.txt -# -cffi==1.16.0 \ - --hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \ - --hash=sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a \ - --hash=sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 \ - --hash=sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab \ - --hash=sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520 \ - --hash=sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36 \ - --hash=sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743 \ - --hash=sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8 \ - --hash=sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed \ - --hash=sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684 \ - --hash=sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56 \ - --hash=sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324 \ - --hash=sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d \ - --hash=sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235 \ - --hash=sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e \ - --hash=sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088 \ - --hash=sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000 \ - --hash=sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7 \ - --hash=sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e \ - --hash=sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673 \ - --hash=sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c \ - --hash=sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe \ - --hash=sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2 \ - --hash=sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098 \ - --hash=sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8 \ - --hash=sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a \ - --hash=sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0 \ - --hash=sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b \ - --hash=sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896 \ - --hash=sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e \ - --hash=sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9 \ - --hash=sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2 \ - --hash=sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b \ - --hash=sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6 \ - --hash=sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 \ - --hash=sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f \ - --hash=sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0 \ - --hash=sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4 \ - --hash=sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc \ - --hash=sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 \ - --hash=sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba \ - --hash=sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872 \ - --hash=sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb \ - --hash=sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614 \ - --hash=sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1 \ - --hash=sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d \ - --hash=sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969 \ - --hash=sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b \ - --hash=sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4 \ - --hash=sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627 \ - --hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \ - --hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357 - # via cryptography -cryptography==42.0.4 \ - --hash=sha256:01911714117642a3f1792c7f376db572aadadbafcd8d75bb527166009c9f1d1b \ - --hash=sha256:0e89f7b84f421c56e7ff69f11c441ebda73b8a8e6488d322ef71746224c20fce \ - --hash=sha256:12d341bd42cdb7d4937b0cabbdf2a94f949413ac4504904d0cdbdce4a22cbf88 \ - --hash=sha256:15a1fb843c48b4a604663fa30af60818cd28f895572386e5f9b8a665874c26e7 \ - --hash=sha256:1cdcdbd117681c88d717437ada72bdd5be9de117f96e3f4d50dab3f59fd9ab20 \ - --hash=sha256:1df6fcbf60560d2113b5ed90f072dc0b108d64750d4cbd46a21ec882c7aefce9 \ - --hash=sha256:3c6048f217533d89f2f8f4f0fe3044bf0b2090453b7b73d0b77db47b80af8dff \ - --hash=sha256:3e970a2119507d0b104f0a8e281521ad28fc26f2820687b3436b8c9a5fcf20d1 \ - --hash=sha256:44a64043f743485925d3bcac548d05df0f9bb445c5fcca6681889c7c3ab12764 \ - --hash=sha256:4e36685cb634af55e0677d435d425043967ac2f3790ec652b2b88ad03b85c27b \ - --hash=sha256:5f8907fcf57392cd917892ae83708761c6ff3c37a8e835d7246ff0ad251d9298 \ - --hash=sha256:69b22ab6506a3fe483d67d1ed878e1602bdd5912a134e6202c1ec672233241c1 \ - --hash=sha256:6bfadd884e7280df24d26f2186e4e07556a05d37393b0f220a840b083dc6a824 \ - --hash=sha256:6d0fbe73728c44ca3a241eff9aefe6496ab2656d6e7a4ea2459865f2e8613257 \ - --hash=sha256:6ffb03d419edcab93b4b19c22ee80c007fb2d708429cecebf1dd3258956a563a \ - --hash=sha256:810bcf151caefc03e51a3d61e53335cd5c7316c0a105cc695f0959f2c638b129 \ - --hash=sha256:831a4b37accef30cccd34fcb916a5d7b5be3cbbe27268a02832c3e450aea39cb \ - --hash=sha256:887623fe0d70f48ab3f5e4dbf234986b1329a64c066d719432d0698522749929 \ - --hash=sha256:a0298bdc6e98ca21382afe914c642620370ce0470a01e1bef6dd9b5354c36854 \ - --hash=sha256:a1327f280c824ff7885bdeef8578f74690e9079267c1c8bd7dc5cc5aa065ae52 \ - --hash=sha256:c1f25b252d2c87088abc8bbc4f1ecbf7c919e05508a7e8628e6875c40bc70923 \ - --hash=sha256:c3a5cbc620e1e17009f30dd34cb0d85c987afd21c41a74352d1719be33380885 \ - --hash=sha256:ce8613beaffc7c14f091497346ef117c1798c202b01153a8cc7b8e2ebaaf41c0 \ - --hash=sha256:d2a27aca5597c8a71abbe10209184e1a8e91c1fd470b5070a2ea60cafec35bcd \ - --hash=sha256:dad9c385ba8ee025bb0d856714f71d7840020fe176ae0229de618f14dae7a6e2 \ - --hash=sha256:db4b65b02f59035037fde0998974d84244a64c3265bdef32a827ab9b63d61b18 \ - --hash=sha256:e09469a2cec88fb7b078e16d4adec594414397e8879a4341c6ace96013463d5b \ - --hash=sha256:e53dc41cda40b248ebc40b83b31516487f7db95ab8ceac1f042626bc43a2f992 \ - --hash=sha256:f1e85a178384bf19e36779d91ff35c7617c885da487d689b05c1366f9933ad74 \ - --hash=sha256:f47be41843200f7faec0683ad751e5ef11b9a56a220d57f300376cd8aba81660 \ - --hash=sha256:fb0cef872d8193e487fc6bdb08559c3aa41b659a7d9be48b2e10747f47863925 \ - --hash=sha256:ffc73996c4fca3d2b6c1c8c12bfd3ad00def8621da24f547626bf06441400449 - # via sev-snp-measure -pycparser==2.21 \ - --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ - --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 - # via cffi -sev-snp-measure==0.0.9 \ - --hash=sha256:32ac67a0db6b639186116d8806a730aac4743584e6ca810c65e8fc57b875f87d \ - --hash=sha256:a1796822e15430c2db7749d1da269819b8cec1330600bb5589ed0ed61400dc41 - # via -r input.txt -types-cryptography==3.3.23.2 \ - --hash=sha256:09cc53f273dd4d8c29fa7ad11fefd9b734126d467960162397bc5e3e604dea75 \ - --hash=sha256:b965d548f148f8e87f353ccf2b7bd92719fdf6c845ff7cedf2abb393a0643e4f - # via sev-snp-measure diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index 8b6455e3a..a9ed3b89b 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -22,7 +22,7 @@ jobs: runs-on: [arc-runner-set] steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} diff --git a/.github/workflows/build-ccm-gcp.yml b/.github/workflows/build-ccm-gcp.yml index bef3a42ea..75e8ce0a7 100644 --- a/.github/workflows/build-ccm-gcp.yml +++ b/.github/workflows/build-ccm-gcp.yml @@ -13,30 +13,30 @@ on: jobs: find-ccm-versions: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 outputs: versions: ${{ steps.find-versions.outputs.versions }} latest: ${{ steps.find-latest.outputs.latest }} steps: - name: Checkout Constellation - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Checkout kubernetes/cloud-provider-gcp - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: "kubernetes/cloud-provider-gcp" path: "cloud-provider-gcp" fetch-depth: 0 - name: Setup Go environment - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 with: - go-version: "1.22.3" + go-version: "1.23.2" cache: false - name: Install Crane run: | - go install github.com/google/go-containerregistry/cmd/crane@latest + go install github.com/google/go-containerregistry/cmd/crane@c195f151efe3369874c72662cd69ad43ee485128 # v0.20.2 - name: Find versions id: find-versions @@ -54,7 +54,7 @@ jobs: build-ccm-gcp: # matrix cannot handle empty lists if: needs.find-ccm-versions.outputs.versions != '[]' - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: contents: read packages: write @@ -65,10 +65,10 @@ jobs: version: ${{ fromJson(needs.find-ccm-versions.outputs.versions) }} steps: - name: Checkout Constellation - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Checkout kubernetes/cloud-provider-gcp - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: "kubernetes/cloud-provider-gcp" path: "cloud-provider-gcp" @@ -76,7 +76,7 @@ jobs: - name: Docker meta id: meta - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1 with: images: | ghcr.io/edgelesssys/cloud-provider-gcp @@ -113,7 +113,7 @@ jobs: - name: Build and push container image id: build - uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 + uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 with: context: ./cloud-provider-gcp push: ${{ github.ref_name == 'main' }} diff --git a/.github/workflows/build-gcp-guest-agent.yml b/.github/workflows/build-gcp-guest-agent.yml index 203d784dc..f5b734f00 100644 --- a/.github/workflows/build-gcp-guest-agent.yml +++ b/.github/workflows/build-gcp-guest-agent.yml @@ -10,7 +10,7 @@ env: jobs: build-gcp-guest-agent: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: contents: read packages: write @@ -69,7 +69,7 @@ jobs: - name: Checkout GoogleCloudPlatform/guest-agent if: steps.needs-build.outputs.out == 'true' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: "GoogleCloudPlatform/guest-agent" ref: refs/tags/${{ steps.latest-release.outputs.latest }} @@ -77,7 +77,7 @@ jobs: - name: Checkout Constellation if: steps.needs-build.outputs.out == 'true' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: "constellation" ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} @@ -85,7 +85,7 @@ jobs: - name: Docker meta id: meta if: steps.needs-build.outputs.out == 'true' - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1 with: images: | ${{ env.REGISTRY }}/edgelesssys/gcp-guest-agent @@ -114,7 +114,7 @@ jobs: - name: Build and push container image if: steps.needs-build.outputs.out == 'true' id: build - uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 + uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 with: context: ./guest-agent file: ./constellation/3rdparty/gcp-guest-agent/Dockerfile diff --git a/.github/workflows/build-libvirt-container.yml b/.github/workflows/build-libvirt-container.yml index fabd396b8..625d6939d 100644 --- a/.github/workflows/build-libvirt-container.yml +++ b/.github/workflows/build-libvirt-container.yml @@ -13,13 +13,13 @@ on: jobs: build-container: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: contents: read packages: write steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup bazel uses: ./.github/actions/setup_bazel_nix diff --git a/.github/workflows/build-logcollector-images.yml b/.github/workflows/build-logcollector-images.yml index 383a196ff..15517975f 100644 --- a/.github/workflows/build-logcollector-images.yml +++ b/.github/workflows/build-logcollector-images.yml @@ -13,14 +13,14 @@ on: jobs: build-logcollector-debugd-images: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: contents: read packages: write steps: - name: Check out repository id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} diff --git a/.github/workflows/build-os-image-scheduled.yml b/.github/workflows/build-os-image-scheduled.yml index 4f3b88fdb..b4376d67b 100644 --- a/.github/workflows/build-os-image-scheduled.yml +++ b/.github/workflows/build-os-image-scheduled.yml @@ -4,15 +4,15 @@ on: workflow_dispatch: schedule: - cron: "0 21 * * 2" # At 21:00 on Tuesday. - - cron: "10 21 * * 2" # At 21:10 on Tuesday. - cron: "20 21 * * 2" # At 21:20 on Tuesday. + - cron: "40 21 * * 2" # At 21:40 on Tuesday. - cron: "0 21 * * 4" # At 21:00 on Thursday. - - cron: "10 21 * * 4" # At 21:10 on Thursday. - cron: "20 21 * * 4" # At 21:20 on Thursday. + - cron: "40 21 * * 4" # At 21:40 on Thursday. jobs: stream: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 outputs: stream: ${{ steps.stream.outputs.stream }} steps: @@ -28,10 +28,10 @@ jobs: "0 21 * * 4" | "0 21 * * 2") echo "stream=debug" | tee -a "$GITHUB_OUTPUT" ;; - "10 21 * * 4" | "10 21 * * 2") + "20 21 * * 4" | "20 21 * * 2") echo "stream=console" | tee -a "$GITHUB_OUTPUT" ;; - "20 21 * * 4" | "20 21 * * 2") + "40 21 * * 4" | "40 21 * * 2") echo "stream=nightly" | tee -a "$GITHUB_OUTPUT" ;; *) @@ -54,22 +54,20 @@ jobs: update-code: # On nightly stream only. - if: | - github.event_name == 'workflow_dispatch' || - github.event.schedule == '20 21 * * 4' || - github.event.schedule == '20 21 * * 2' - needs: build-image - runs-on: ubuntu-22.04 + if: needs.stream.outputs.stream == 'nightly' + needs: ["build-image", "stream"] + runs-on: ubuntu-24.04 steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.head_ref }} + token: ${{ secrets.CI_COMMIT_PUSH_PR }} - name: Setup Go environment - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 with: - go-version: "1.22.3" + go-version: "1.23.2" cache: false - name: Determine version @@ -99,7 +97,7 @@ jobs: run: rm -f internal/attestation/measurements/measurement-generator/generate - name: Create pull request - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 + uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 with: branch: "image/automated/update-measurements-${{ github.run_number }}" base: main @@ -111,6 +109,7 @@ jobs: It updates the hardcoded measurements and the image version (for QEMU/MiniConstellation). commit-message: "image: update measurements and image version" committer: edgelessci + author: edgelessci labels: no changelog # We need to push changes using a token, otherwise triggers like on:push and on:pull_request won't work. token: ${{ !github.event.pull_request.head.repo.fork && secrets.CI_COMMIT_PUSH_PR || '' }} @@ -118,10 +117,10 @@ jobs: notify-failure: if: failure() needs: [ "stream", "build-image", "update-code" ] - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.head_ref }} diff --git a/.github/workflows/build-os-image.yml b/.github/workflows/build-os-image.yml index dc0035e96..f19419ead 100644 --- a/.github/workflows/build-os-image.yml +++ b/.github/workflows/build-os-image.yml @@ -47,7 +47,7 @@ on: jobs: build-settings: name: "Determine build settings" - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 outputs: ref: ${{ steps.ref.outputs.ref }} stream: ${{ steps.stream.outputs.stream }} @@ -59,7 +59,7 @@ jobs: cliApiBasePath: ${{ steps.image-version.outputs.cliApiBasePath }} steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} @@ -138,7 +138,7 @@ jobs: contents: read steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} diff --git a/.github/workflows/build-versionsapi-ci-image.yml b/.github/workflows/build-versionsapi-ci-image.yml deleted file mode 100644 index 563e2837f..000000000 --- a/.github/workflows/build-versionsapi-ci-image.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Build and upload versionsapi CI image - -on: - workflow_dispatch: - push: - branches: - - main - paths: - - "internal/api/versionsapi/**" - - ".github/workflows/build-versionsapi-ci-image.yml" - - ".github/actions/versionsapi/**" - - "go.mod" - -jobs: - build-versionsapi-ci-cli: - runs-on: ubuntu-22.04 - permissions: - contents: read - packages: write - steps: - - name: Check out repository - id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - with: - ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - - - name: Build and upload container image - uses: ./.github/actions/build_micro_service - with: - name: versionsapi-ci-cli - dockerfile: .github/actions/versionsapi/Dockerfile - githubToken: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml index e756e2aed..d9f97cfaa 100644 --- a/.github/workflows/check-links.yml +++ b/.github/workflows/check-links.yml @@ -17,15 +17,15 @@ on: jobs: linkChecker: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Link Checker - uses: lycheeverse/lychee-action@2b973e86fc7b1f6b36a93795fe2c9c6ae1118621 # v1.10.0 + uses: lycheeverse/lychee-action@f81112d0d2814ded911bd23e3beaa9dda9093915 # v2.1.0 with: args: "--config ./.lychee.toml './**/*.md' './**/*.html'" fail: true diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index daeec6dfa..5ffd4cd78 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,7 +17,7 @@ on: jobs: codeql: name: CodeQL - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: # Force CodeQL to run the extraction on the files compiled by our custom # build command, as opposed to letting the autobuilder figure it out. @@ -34,17 +34,17 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Go environment if: matrix.language == 'go' - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 with: - go-version: "1.22.3" + go-version: "1.23.2" cache: false - name: Initialize CodeQL - uses: github/codeql-action/init@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5 + uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 with: languages: ${{ matrix.language }} @@ -63,6 +63,6 @@ jobs: echo "::endgroup::" - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5 + uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 with: category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/docs-vale.yml b/.github/workflows/docs-vale.yml index f83400b3b..a9f58cc04 100644 --- a/.github/workflows/docs-vale.yml +++ b/.github/workflows/docs-vale.yml @@ -13,15 +13,19 @@ on: jobs: vale: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - + # Work around https://github.com/errata-ai/vale-action/issues/128. + - run: | + venv="$HOME/.local/share/venv" + python3 -m venv "$venv" + echo "$venv/bin" >> "$GITHUB_PATH" - name: Vale - uses: errata-ai/vale-action@38bf078c328061f59879b347ca344a718a736018 # tag=reviewdog + uses: errata-ai/vale-action@2690bc95f0ed3cb5220492575af09c51b04fbea9 # tag=reviewdog with: files: docs/docs fail_on_error: true diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index 3ab075138..c77719367 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -50,7 +50,7 @@ on: jobs: build-cli: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -72,7 +72,7 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} @@ -92,7 +92,7 @@ jobs: cosignPassword: ${{ inputs.key == 'release' && secrets.COSIGN_PASSWORD || secrets.COSIGN_DEV_PASSWORD }} - name: Upload CLI as artifact (unix) - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if : ${{ matrix.os != 'windows' }} with: name: constellation-${{ matrix.os }}-${{ matrix.arch }} @@ -101,7 +101,7 @@ jobs: build/constellation-${{ matrix.os }}-${{ matrix.arch }}.sig - name: Upload CLI as artifact (windows) - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if : ${{ matrix.os == 'windows' }} with: name: constellation-${{ matrix.os }}-${{ matrix.arch }} @@ -110,7 +110,7 @@ jobs: build/constellation-${{ matrix.os }}-${{ matrix.arch }}.exe.sig build-terraform-provider: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -133,7 +133,7 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} @@ -149,7 +149,7 @@ jobs: targetArch: ${{ matrix.arch }} - name: Upload Terraform Provider Binary as artifact (unix) - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if : ${{ matrix.os != 'windows' }} with: name: terraform-provider-constellation-${{ matrix.os }}-${{ matrix.arch }} @@ -157,7 +157,7 @@ jobs: build/terraform-provider-constellation-${{ matrix.os }}-${{ matrix.arch }} - name: Upload Terraform Provider Binary as artifact (windows) - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if : ${{ matrix.os == 'windows' }} with: name: terraform-provider-constellation-${{ matrix.os }}-${{ matrix.arch }} @@ -165,11 +165,11 @@ jobs: build/terraform-provider-constellation-${{ matrix.os }}-${{ matrix.arch }}.exe upload-terraform-module: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} @@ -177,7 +177,7 @@ jobs: uses: ./.github/actions/upload_terraform_module push-containers: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 if: inputs.pushContainers permissions: actions: read @@ -187,7 +187,7 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} @@ -208,7 +208,7 @@ jobs: run: bazel run //bazel/release:push provenance-subjects: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: - build-cli - signed-sbom @@ -219,7 +219,7 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} @@ -227,7 +227,7 @@ jobs: uses: ./.github/actions/download_release_binaries - name: Download CLI SBOM - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: constellation.spdx.sbom @@ -252,16 +252,16 @@ jobs: echo provenance-subjects="${HASHESB64}" >> "$GITHUB_OUTPUT" signed-sbom: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} - name: Install Cosign - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 - name: Download Syft & Grype uses: ./.github/actions/install_syft_grype @@ -296,13 +296,13 @@ jobs: COSIGN_PASSWORD: ${{ inputs.key == 'release' && secrets.COSIGN_PASSWORD || secrets.COSIGN_DEV_PASSWORD }} - name: Upload Constellation CLI SBOM - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: constellation.spdx.sbom path: constellation.spdx.sbom - name: Upload Constellation CLI SBOM's signature - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: constellation.spdx.sbom.sig path: constellation.spdx.sbom.sig @@ -321,7 +321,7 @@ jobs: base64-subjects: "${{ needs.provenance-subjects.outputs.provenance-subjects }}" provenance-verify: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: SLSA_VERIFIER_VERSION: "2.5.1" needs: @@ -332,7 +332,7 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} @@ -340,12 +340,12 @@ jobs: uses: ./.github/actions/download_release_binaries - name: Download CLI SBOM - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: constellation.spdx.sbom - name: Download provenance - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: ${{ needs.provenance.outputs.provenance-name }} @@ -395,7 +395,7 @@ jobs: release: permissions: contents: write - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: - build-cli - provenance @@ -405,7 +405,7 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} @@ -418,17 +418,17 @@ jobs: uses: ./.github/actions/download_release_binaries - name: Download CLI SBOM - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: constellation.spdx.sbom - name: Download Constellation CLI SBOM's signature - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: constellation.spdx.sbom.sig - name: Download Constellation provenance - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: ${{ needs.provenance.outputs.provenance-name }} @@ -472,7 +472,7 @@ jobs: - name: Create release with artifacts id: create-release # GitHub endorsed release project. See: https://github.com/actions/create-release - uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # v2.0.5 + uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0 with: draft: true generate_release_notes: true @@ -487,7 +487,7 @@ jobs: terraform-module.zip - name: Create Terraform provider release with artifcats - uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # v2.0.5 + uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0 with: draft: true generate_release_notes: false diff --git a/.github/workflows/e2e-attestationconfigapi.yml b/.github/workflows/e2e-attestationconfigapi.yml index f2c4b7d2c..3c3d233c1 100644 --- a/.github/workflows/e2e-attestationconfigapi.yml +++ b/.github/workflows/e2e-attestationconfigapi.yml @@ -17,8 +17,8 @@ jobs: fail-fast: false max-parallel: 1 matrix: - csp: ["azure", "aws", "gcp"] - runs-on: ubuntu-22.04 + attestationVariant: ["azure-sev-snp", "azure-tdx", "aws-sev-snp", "gcp-sev-snp"] + runs-on: ubuntu-24.04 permissions: id-token: write contents: read @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: # Don't trigger in forks, use head on pull requests, use default otherwise. ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || github.event.pull_request.head.sha || '' }} @@ -36,4 +36,4 @@ jobs: with: cosignPrivateKey: ${{ secrets.COSIGN_DEV_PRIVATE_KEY }} cosignPassword: ${{ secrets.COSIGN_DEV_PASSWORD }} - csp: ${{ matrix.csp }} + attestationVariant: ${{ matrix.attestationVariant }} diff --git a/.github/workflows/e2e-cleanup-weekly.yml b/.github/workflows/e2e-cleanup-weekly.yml index ce75c226d..e8e5ffa92 100644 --- a/.github/workflows/e2e-cleanup-weekly.yml +++ b/.github/workflows/e2e-cleanup-weekly.yml @@ -14,7 +14,7 @@ jobs: id-token: write steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Cleanup uses: ./.github/actions/e2e_cleanup_timeframe diff --git a/.github/workflows/e2e-mini.yml b/.github/workflows/e2e-mini.yml index f82dbb0aa..7e03ffd53 100644 --- a/.github/workflows/e2e-mini.yml +++ b/.github/workflows/e2e-mini.yml @@ -20,7 +20,7 @@ on: jobs: e2e-mini: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 environment: e2e permissions: id-token: write @@ -29,12 +29,12 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.event.workflow_run.head_branch || github.head_ref }} - name: Azure login OIDC - uses: azure/login@6b2456866fc08b011acb422a92a4aa20e2c4de32 # v2.1.0 + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 with: client-id: ${{ secrets.AZURE_E2E_MINI_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -46,5 +46,6 @@ jobs: azureClientID: ${{ secrets.AZURE_E2E_MINI_CLIENT_ID }} azureSubscriptionID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} azureTenantID: ${{ secrets.AZURE_TENANT_ID }} + azureIAMCredentials: ${{ secrets.AZURE_E2E_IAM_CREDENTIALS }} registry: ghcr.io githubToken: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/e2e-test-daily.yml b/.github/workflows/e2e-test-daily.yml index e1b329bbf..5e36add52 100644 --- a/.github/workflows/e2e-test-daily.yml +++ b/.github/workflows/e2e-test-daily.yml @@ -12,7 +12,7 @@ jobs: matrix: refStream: ["ref/main/stream/debug/?", "ref/release/stream/stable/?"] name: Find latest image - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write contents: read @@ -21,7 +21,7 @@ jobs: image-release-stable: ${{ steps.relabel-output.outputs.image-release-stable }} steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} @@ -49,13 +49,7 @@ jobs: attestationVariant: ["gcp-sev-es", "gcp-sev-snp", "azure-sev-snp", "azure-tdx", "aws-sev-snp"] refStream: ["ref/main/stream/debug/?", "ref/release/stream/stable/?"] test: ["sonobuoy quick"] - exclude: - # TODO(v2.18 msanft): Remove exclude rule for GCP SEV-SNP stable once images exist. - - kubernetesVersion: "1.28" - attestationVariant: "gcp-sev-snp" - refStream: "ref/release/stream/stable/?" - test: "sonobuoy quick" - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write checks: write @@ -65,7 +59,7 @@ jobs: needs: [find-latest-image] steps: - name: Check out repository - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} @@ -96,6 +90,7 @@ jobs: gcpIAMCreateServiceAccount: "iam-e2e@constellation-e2e.iam.gserviceaccount.com" kubernetesVersion: ${{ matrix.kubernetesVersion }} test: ${{ matrix.test }} + azureSubscriptionID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} azureClusterCreateCredentials: ${{ secrets.AZURE_E2E_CLUSTER_CREDENTIALS }} azureIAMCreateCredentials: ${{ secrets.AZURE_E2E_IAM_CREDENTIALS }} registry: ghcr.io @@ -155,7 +150,7 @@ jobs: e2e-mini: name: Run miniconstellation E2E test - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 environment: e2e permissions: id-token: write @@ -164,12 +159,12 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Azure login OIDC - uses: azure/login@6b2456866fc08b011acb422a92a4aa20e2c4de32 # v2.1.0 + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 with: client-id: ${{ secrets.AZURE_E2E_MINI_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -181,6 +176,7 @@ jobs: azureClientID: ${{ secrets.AZURE_E2E_MINI_CLIENT_ID }} azureSubscriptionID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} azureTenantID: ${{ secrets.AZURE_TENANT_ID }} + azureIAMCredentials: ${{ secrets.AZURE_E2E_IAM_CREDENTIALS }} registry: ghcr.io githubToken: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/e2e-test-internal-lb.yml b/.github/workflows/e2e-test-internal-lb.yml index b9a27949c..cee93f7eb 100644 --- a/.github/workflows/e2e-test-internal-lb.yml +++ b/.github/workflows/e2e-test-internal-lb.yml @@ -22,9 +22,9 @@ on: description: "Architecture of the runner that executes the CLI" type: choice options: - - "ubuntu-22.04" + - "ubuntu-24.04" - "macos-12" - default: "ubuntu-22.04" + default: "ubuntu-24.04" test: description: "The test to run." type: choice diff --git a/.github/workflows/e2e-test-marketplace-image.yml b/.github/workflows/e2e-test-marketplace-image.yml index 3338c1384..760df932b 100644 --- a/.github/workflows/e2e-test-marketplace-image.yml +++ b/.github/workflows/e2e-test-marketplace-image.yml @@ -22,9 +22,9 @@ on: description: "Architecture of the runner that executes the CLI" type: choice options: - - "ubuntu-22.04" + - "ubuntu-24.04" - "macos-12" - default: "ubuntu-22.04" + default: "ubuntu-24.04" test: description: "The test to run." type: choice diff --git a/.github/workflows/e2e-test-provider-example.yml b/.github/workflows/e2e-test-provider-example.yml index 6642e409f..df52b2341 100644 --- a/.github/workflows/e2e-test-provider-example.yml +++ b/.github/workflows/e2e-test-provider-example.yml @@ -63,7 +63,7 @@ on: jobs: provider-example-test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write contents: read @@ -71,7 +71,7 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.ref || github.head_ref }} @@ -306,6 +306,19 @@ jobs: cat >> _override.tf <> _override.tf <> /etc/hosts' terraform init if [[ "${{ inputs.attestationVariant }}" == "azure-sev-snp" ]]; then - terraform apply -target module.azure_iam -auto-approve - terraform apply -target module.azure_infrastructure -auto-approve + timeout 1h terraform apply -target module.azure_iam -auto-approve + timeout 1h terraform apply -target module.azure_infrastructure -auto-approve ${{ github.workspace }}/build/constellation maa-patch "$(terraform output -raw maa_url)" - terraform apply -target constellation_cluster.azure_example -auto-approve + timeout 1h terraform apply -target constellation_cluster.azure_example -auto-approve else - terraform apply -auto-approve + timeout 1h terraform apply -auto-approve fi - name: Cleanup Terraform Cluster on failure @@ -340,7 +353,7 @@ jobs: shell: bash run: | terraform init - terraform destroy -auto-approve + terraform destroy -auto-approve -lock=false - name: Add Provider to local Terraform registry # needed if release version was used before if: inputs.providerVersion != '' @@ -394,7 +407,7 @@ jobs: shell: bash run: | terraform init --upgrade - terraform apply -auto-approve + timeout 1h terraform apply -auto-approve - name: Assert upgrade successful working-directory: ${{ github.workspace }}/cluster @@ -462,11 +475,11 @@ jobs: shell: bash run: | terraform init - terraform destroy -auto-approve + terraform destroy -auto-approve -lock=false - name: Notify about failure if: | - failure() && + (failure() || cancelled()) && github.ref == 'refs/heads/main' && github.event_name == 'schedule' continue-on-error: true diff --git a/.github/workflows/e2e-test-release.yml b/.github/workflows/e2e-test-release.yml index f8ca947e7..dce7c9913 100644 --- a/.github/workflows/e2e-test-release.yml +++ b/.github/workflows/e2e-test-release.yml @@ -47,241 +47,256 @@ jobs: # sonobuoy full test on all k8s versions - test: "sonobuoy full" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" - - test: "sonobuoy full" - attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" - clusterCreation: "cli" - - test: "sonobuoy full" - attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" - clusterCreation: "cli" - - test: "sonobuoy full" - attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" - clusterCreation: "cli" - - test: "sonobuoy full" - attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" - clusterCreation: "cli" - - - - test: "sonobuoy full" - attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.28" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "sonobuoy full" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.28" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "sonobuoy full" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.28" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "sonobuoy full" attestationVariant: "azure-tdx" - kubernetes-version: "v1.28" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "sonobuoy full" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.28" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "sonobuoy full" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.27" - runner: "ubuntu-22.04" + kubernetes-version: "v1.29" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "sonobuoy full" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.27" - runner: "ubuntu-22.04" + kubernetes-version: "v1.29" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "sonobuoy full" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.27" - runner: "ubuntu-22.04" + kubernetes-version: "v1.29" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "sonobuoy full" attestationVariant: "azure-tdx" - kubernetes-version: "v1.27" - runner: "ubuntu-22.04" + kubernetes-version: "v1.29" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "sonobuoy full" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.27" - runner: "ubuntu-22.04" + kubernetes-version: "v1.29" + runner: "ubuntu-24.04" + clusterCreation: "cli" + + - test: "sonobuoy full" + attestationVariant: "gcp-sev-es" + kubernetes-version: "v1.28" + runner: "ubuntu-24.04" + clusterCreation: "cli" + - test: "sonobuoy full" + attestationVariant: "gcp-sev-snp" + kubernetes-version: "v1.28" + runner: "ubuntu-24.04" + clusterCreation: "cli" + - test: "sonobuoy full" + attestationVariant: "azure-sev-snp" + kubernetes-version: "v1.28" + runner: "ubuntu-24.04" + clusterCreation: "cli" + - test: "sonobuoy full" + attestationVariant: "azure-tdx" + kubernetes-version: "v1.28" + runner: "ubuntu-24.04" + clusterCreation: "cli" + - test: "sonobuoy full" + attestationVariant: "aws-sev-snp" + kubernetes-version: "v1.28" + runner: "ubuntu-24.04" clusterCreation: "cli" # verify test on latest k8s version - test: "verify" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "verify" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "verify" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "verify" attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "verify" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" # recover test on latest k8s version - test: "recover" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "recover" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "recover" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "recover" attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "recover" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" # lb test on latest k8s version - test: "lb" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "lb" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "lb" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "lb" attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "lb" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" # autoscaling test on latest k8s version - test: "autoscaling" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "autoscaling" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "autoscaling" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "autoscaling" attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "autoscaling" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - # perf-bench test on latest k8s version, not supported on AWS + # perf-bench test on latest k8s version - test: "perf-bench" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "perf-bench" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" - test: "perf-bench" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" + clusterCreation: "cli" + - test: "perf-bench" + attestationVariant: "azure-tdx" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" + clusterCreation: "cli" + - test: "perf-bench" + attestationVariant: "aws-sev-snp" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" # s3proxy test on latest k8s version - test: "s3proxy" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" - runner: "ubuntu-22.04" + kubernetes-version: "v1.30" + runner: "ubuntu-24.04" clusterCreation: "cli" # malicious join test on latest k8s version - test: "malicious join" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" + runner: "ubuntu-24.04" - test: "malicious join" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" + runner: "ubuntu-24.04" - test: "malicious join" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" + runner: "ubuntu-24.04" - test: "malicious join" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" + runner: "ubuntu-24.04" - test: "malicious join" refStream: "ref/main/stream/debug/?" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" + runner: "ubuntu-24.04" # # Tests on macOS runner @@ -290,11 +305,11 @@ jobs: # TODO(3u13r): Update verify test to work on MacOS runners # - test: "verify" # attestationVariant: "azure-sev-snp" - # kubernetes-version: "v1.29" + # kubernetes-version: "v1.30" # runner: "macos-12" - test: "recover" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" runner: "macos-12" clusterCreation: "cli" runs-on: ${{ matrix.runner }} @@ -311,7 +326,7 @@ jobs: run: brew install coreutils kubectl bash - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 ref: ${{ inputs.ref || github.head_ref }} @@ -327,7 +342,7 @@ jobs: - name: Set up gcloud CLI (macOS) if: steps.split-attestationVariant.outputs.provider == 'gcp' && runner.os == 'macOS' - uses: google-github-actions/setup-gcloud@98ddc00a17442e89a24bbf282954a3b65ce6d200 # v2.1.0 + uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 - name: Run E2E test id: e2e_test @@ -349,6 +364,7 @@ jobs: gcpClusterCreateServiceAccount: "infrastructure-e2e@constellation-e2e.iam.gserviceaccount.com" gcpIAMCreateServiceAccount: "iam-e2e@constellation-e2e.iam.gserviceaccount.com" test: ${{ matrix.test }} + azureSubscriptionID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} azureClusterCreateCredentials: ${{ secrets.AZURE_E2E_CLUSTER_CREDENTIALS }} azureIAMCreateCredentials: ${{ secrets.AZURE_E2E_IAM_CREDENTIALS }} registry: ghcr.io @@ -393,8 +409,8 @@ jobs: fail-fast: false max-parallel: 1 matrix: - fromVersion: ["v2.16.2"] - attestationVariant: ["gcp-sev-es", "azure-sev-snp", "azure-tdx", "aws-sev-snp"] + fromVersion: ["v2.19.3"] + attestationVariant: ["gcp-sev-snp", "azure-sev-snp", "azure-tdx", "aws-sev-snp"] name: Run upgrade tests secrets: inherit permissions: diff --git a/.github/workflows/e2e-test-terraform-provider.yml b/.github/workflows/e2e-test-terraform-provider.yml index 585ffe6b9..3c465ab97 100644 --- a/.github/workflows/e2e-test-terraform-provider.yml +++ b/.github/workflows/e2e-test-terraform-provider.yml @@ -22,9 +22,9 @@ on: description: "Architecture of the runner that executes the CLI" type: choice options: - - "ubuntu-22.04" + - "ubuntu-24.04" - "macos-12" - default: "ubuntu-22.04" + default: "ubuntu-24.04" test: description: "The test to run." type: choice diff --git a/.github/workflows/e2e-test-weekly.yml b/.github/workflows/e2e-test-weekly.yml index f3d8468e2..587abd129 100644 --- a/.github/workflows/e2e-test-weekly.yml +++ b/.github/workflows/e2e-test-weekly.yml @@ -12,7 +12,7 @@ jobs: matrix: refStream: ["ref/main/stream/nightly/?","ref/main/stream/debug/?", "ref/release/stream/stable/?"] name: Find latest image - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write contents: read @@ -22,7 +22,7 @@ jobs: image-main-nightly: ${{ steps.relabel-output.outputs.image-main-nightly }} steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} @@ -55,80 +55,87 @@ jobs: - test: "sonobuoy full" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "sonobuoy full" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "sonobuoy full" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "sonobuoy full" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "sonobuoy full" refStream: "ref/main/stream/debug/?" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" + clusterCreation: "cli" + + # Sonobuoy conformance test + - test: "sonobuoy conformance" + refStream: "ref/main/stream/debug/?" + attestationVariant: "gcp-sev-snp" + kubernetes-version: "v1.30" clusterCreation: "cli" # Sonobuoy quick test on all but the latest k8s versions - test: "sonobuoy quick" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.28" + kubernetes-version: "v1.29" clusterCreation: "cli" - test: "sonobuoy quick" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.28" + kubernetes-version: "v1.29" clusterCreation: "cli" - test: "sonobuoy quick" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.28" + kubernetes-version: "v1.29" clusterCreation: "cli" - test: "sonobuoy quick" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-tdx" - kubernetes-version: "v1.28" + kubernetes-version: "v1.29" clusterCreation: "cli" - test: "sonobuoy quick" refStream: "ref/main/stream/debug/?" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.28" + kubernetes-version: "v1.29" clusterCreation: "cli" - test: "sonobuoy quick" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.27" + kubernetes-version: "v1.28" clusterCreation: "cli" - test: "sonobuoy quick" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.27" + kubernetes-version: "v1.28" clusterCreation: "cli" - test: "sonobuoy quick" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.27" + kubernetes-version: "v1.28" clusterCreation: "cli" - test: "sonobuoy quick" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-tdx" - kubernetes-version: "v1.27" + kubernetes-version: "v1.28" clusterCreation: "cli" - test: "sonobuoy quick" refStream: "ref/main/stream/debug/?" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.27" + kubernetes-version: "v1.28" clusterCreation: "cli" @@ -136,139 +143,143 @@ jobs: - test: "verify" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "verify" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "verify" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" azureSNPEnforcementPolicy: "equal" # This run checks for unknown ID Key disgests. clusterCreation: "cli" - test: "verify" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "verify" attestationVariant: "aws-sev-snp" refStream: "ref/main/stream/debug/?" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" # recover test on latest k8s version - test: "recover" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "recover" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "recover" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "recover" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "recover" refStream: "ref/main/stream/debug/?" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" # lb test on latest k8s version - test: "lb" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "lb" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "lb" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "lb" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "lb" refStream: "ref/main/stream/debug/?" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" # autoscaling test on latest k8s version - test: "autoscaling" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "autoscaling" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "autoscaling" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "autoscaling" refStream: "ref/main/stream/debug/?" attestationVariant: "azure-tdx" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "autoscaling" refStream: "ref/main/stream/debug/?" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - # perf-bench test on latest k8s version, not supported on AWS + # perf-bench test on latest k8s version - test: "perf-bench" - refStream: "ref/main/stream/debug/?" + refStream: "ref/main/stream/nightly/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "perf-bench" - refStream: "ref/main/stream/debug/?" + refStream: "ref/main/stream/nightly/?" attestationVariant: "gcp-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" - test: "perf-bench" - refStream: "ref/main/stream/debug/?" + refStream: "ref/main/stream/nightly/?" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" + clusterCreation: "cli" + - test: "perf-bench" + refStream: "ref/main/stream/nightly/?" + attestationVariant: "azure-tdx" + kubernetes-version: "v1.30" + clusterCreation: "cli" + - test: "perf-bench" + refStream: "ref/main/stream/nightly/?" + attestationVariant: "aws-sev-snp" + kubernetes-version: "v1.30" clusterCreation: "cli" - # TODO: check what needs to be done for perf-bench on Azure TDX - #- test: "perf-bench" - # refStream: "ref/main/stream/debug/?" - # attestationVariant: "azure-tdx" - # kubernetes-version: "v1.29" - # clusterCreation: "cli" # s3proxy test on latest k8s version - test: "s3proxy" refStream: "ref/main/stream/debug/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.29" + kubernetes-version: "v1.30" clusterCreation: "cli" # @@ -279,31 +290,30 @@ jobs: - test: "verify" refStream: "ref/release/stream/stable/?" attestationVariant: "gcp-sev-es" - kubernetes-version: "v1.28" + kubernetes-version: "v1.29" + clusterCreation: "cli" + - test: "verify" + refStream: "ref/release/stream/stable/?" + attestationVariant: "gcp-sev-snp" + kubernetes-version: "v1.29" clusterCreation: "cli" - # TODO(msanft): Enable once stable GCP SEV-SNP images exist. - # - test: "verify" - # refStream: "ref/release/stream/stable/?" - # attestationVariant: "gcp-sev-snp" - # kubernetes-version: "v1.28" - # clusterCreation: "cli" - test: "verify" refStream: "ref/release/stream/stable/?" attestationVariant: "azure-sev-snp" - kubernetes-version: "v1.28" + kubernetes-version: "v1.29" clusterCreation: "cli" - test: "verify" refStream: "ref/release/stream/stable/?" attestationVariant: "azure-tdx" - kubernetes-version: "v1.28" + kubernetes-version: "v1.29" clusterCreation: "cli" - test: "verify" refStream: "ref/release/stream/stable/?" attestationVariant: "aws-sev-snp" - kubernetes-version: "v1.28" + kubernetes-version: "v1.29" clusterCreation: "cli" - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write checks: write @@ -313,7 +323,7 @@ jobs: needs: [find-latest-image] steps: - name: Check out repository - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} @@ -335,7 +345,7 @@ jobs: controlNodesCount: "3" cloudProvider: ${{ steps.split-attestationVariant.outputs.cloudProvider }} attestationVariant: ${{ matrix.attestationVariant }} - osImage: ${{ matrix.refStream == 'ref/release/stream/stable/?' && needs.find-latest-image.outputs.image-release-stable || needs.find-latest-image.outputs.image-main-debug }} + osImage: ${{ matrix.refStream == 'ref/release/stream/stable/?' && needs.find-latest-image.outputs.image-release-stable || matrix.refStream == 'ref/main/stream/nightly/?' && needs.find-latest-image.outputs.image-main-nightly || needs.find-latest-image.outputs.image-main-debug }} isDebugImage: ${{ matrix.refStream == 'ref/main/stream/debug/?' }} cliVersion: ${{ matrix.refStream == 'ref/release/stream/stable/?' && needs.find-latest-image.outputs.image-release-stable || '' }} kubernetesVersion: ${{ matrix.kubernetes-version }} @@ -347,6 +357,7 @@ jobs: gcpClusterCreateServiceAccount: "infrastructure-e2e@constellation-e2e.iam.gserviceaccount.com" gcpIAMCreateServiceAccount: "iam-e2e@constellation-e2e.iam.gserviceaccount.com" test: ${{ matrix.test }} + azureSubscriptionID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} azureClusterCreateCredentials: ${{ secrets.AZURE_E2E_CLUSTER_CREDENTIALS }} azureIAMCreateCredentials: ${{ secrets.AZURE_E2E_IAM_CREDENTIALS }} registry: ghcr.io @@ -409,8 +420,8 @@ jobs: fail-fast: false max-parallel: 1 matrix: - fromVersion: ["v2.16.2"] - attestationVariant: ["gcp-sev-es", "azure-sev-snp", "azure-tdx", "aws-sev-snp"] + fromVersion: ["v2.19.3"] + attestationVariant: ["gcp-sev-snp", "azure-sev-snp", "azure-tdx", "aws-sev-snp"] name: Run upgrade tests secrets: inherit permissions: @@ -428,7 +439,7 @@ jobs: e2e-mini: name: Run miniconstellation E2E test - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 environment: e2e permissions: id-token: write @@ -437,12 +448,12 @@ jobs: steps: - name: Checkout id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Azure login OIDC - uses: azure/login@6b2456866fc08b011acb422a92a4aa20e2c4de32 # v2.1.0 + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 with: client-id: ${{ secrets.AZURE_E2E_MINI_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -454,6 +465,7 @@ jobs: azureClientID: ${{ secrets.AZURE_E2E_MINI_CLIENT_ID }} azureSubscriptionID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} azureTenantID: ${{ secrets.AZURE_TENANT_ID }} + azureIAMCredentials: ${{ secrets.AZURE_E2E_IAM_CREDENTIALS }} registry: ghcr.io githubToken: ${{ secrets.GITHUB_TOKEN }} @@ -487,7 +499,7 @@ jobs: strategy: fail-fast: false matrix: - attestationVariant: ["gcp-sev-es", "azure-sev-snp", "azure-tdx", "aws-sev-snp"] + attestationVariant: ["gcp-sev-snp", "azure-sev-snp", "azure-tdx", "aws-sev-snp"] permissions: id-token: write contents: read diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 3ddffb56c..6efdd03b5 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -22,15 +22,16 @@ on: description: "Architecture of the runner that executes the CLI" type: choice options: - - "ubuntu-22.04" + - "ubuntu-24.04" - "macos-12" - default: "ubuntu-22.04" + default: "ubuntu-24.04" test: - description: "The test to run." + description: "The test to run. The conformance test is only supported for clusterCreation=cli." type: choice options: - "sonobuoy quick" - "sonobuoy full" + - "sonobuoy conformance" - "autoscaling" - "lb" - "perf-bench" @@ -42,7 +43,7 @@ on: required: true kubernetesVersion: description: "Kubernetes version to create the cluster from." - default: "1.28" + default: "1.29" required: true cliVersion: description: "Version of a released CLI to download. Leave empty to build the CLI from the checked out ref." @@ -82,7 +83,7 @@ on: type: string required: true test: - description: "The test to run." + description: "The test to run. The conformance test is only supported for clusterCreation=cli." type: string required: true kubernetesVersion: @@ -128,7 +129,7 @@ on: jobs: generate-input-parameters: name: Generate input parameters - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write contents: read @@ -164,7 +165,7 @@ jobs: find-latest-image: name: Select image - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write contents: read @@ -174,13 +175,13 @@ jobs: steps: - name: Checkout head if: inputs.git-ref == 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Checkout ref if: inputs.git-ref != 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.git-ref }} @@ -211,19 +212,19 @@ jobs: - name: Checkout head if: inputs.git-ref == 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Checkout ref if: inputs.git-ref != 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.git-ref }} - name: Set up gcloud CLI (macOS) if: needs.generate-input-parameters.outputs.cloudProvider == 'gcp' && runner.os == 'macOS' - uses: google-github-actions/setup-gcloud@98ddc00a17442e89a24bbf282954a3b65ce6d200 # v2.1.0 + uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 - name: Run manual E2E test id: e2e_test @@ -246,6 +247,7 @@ jobs: osImage: ${{ needs.find-latest-image.outputs.image }} cliVersion: ${{ inputs.cliVersion }} isDebugImage: ${{ needs.find-latest-image.outputs.isDebugImage }} + azureSubscriptionID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} azureClusterCreateCredentials: ${{ secrets.AZURE_E2E_CLUSTER_CREDENTIALS }} azureIAMCreateCredentials: ${{ secrets.AZURE_E2E_IAM_CREDENTIALS }} registry: ghcr.io diff --git a/.github/workflows/e2e-upgrade.yml b/.github/workflows/e2e-upgrade.yml index 18bab8697..5e50ec87e 100644 --- a/.github/workflows/e2e-upgrade.yml +++ b/.github/workflows/e2e-upgrade.yml @@ -22,6 +22,10 @@ on: description: CLI version to create a new cluster with. This has to be a released version, e.g., 'v2.1.3'. type: string required: true + fromKubernetes: + description: Kubernetes version for the origin cluster, empty for origin target's default version. + type: string + required: false gitRef: description: Ref to build upgrading CLI on, empty for HEAD. type: string @@ -32,11 +36,11 @@ on: type: string required: false toKubernetes: - description: Kubernetes version to target for the upgrade, empty for target's default version. + description: Kubernetes version to target for the upgrade, empty for upgrade target's default version. type: string required: false toMicroservices: - description: Microservice version to target for the upgrade, empty for target's default version. + description: Microservice version to target for the upgrade, empty for upgrade target's default version. type: string required: false simulatedTargetVersion: @@ -60,6 +64,10 @@ on: description: CLI version to create a new cluster with. This has to be a released version, e.g., 'v2.1.3'. type: string required: true + fromKubernetes: + description: Kubernetes version for the origin cluster, empty for origin target's default version. + type: string + required: false gitRef: description: Ref to build upgrading CLI on. type: string @@ -90,7 +98,7 @@ on: jobs: generate-input-parameters: name: Generate input parameters - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write contents: read @@ -124,60 +132,9 @@ jobs: echo "cloudProvider=${cloudProvider}" | tee -a "$GITHUB_OUTPUT" - build-target-cli: - name: Build upgrade target version CLI - runs-on: ubuntu-22.04 - permissions: - id-token: write - checks: write - contents: read - packages: write - steps: - - name: Checkout - if: inputs.gitRef == 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - with: - fetch-depth: 0 - ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - - - name: Checkout ref - if: inputs.gitRef != 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - with: - fetch-depth: 0 - ref: ${{ inputs.gitRef }} - - - name: Setup Bazel & Nix - uses: ./.github/actions/setup_bazel_nix - - - name: Log in to the Container registry - uses: ./.github/actions/container_registry_login - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Simulate patch upgrade - if: inputs.simulatedTargetVersion != '' - run: | - echo ${{ inputs.simulatedTargetVersion }} > version.txt - - - name: Build CLI - uses: ./.github/actions/build_cli - with: - enterpriseCLI: true - outputPath: "build/constellation" - push: true - - - name: Upload CLI binary - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 - with: - name: constellation-upgrade-${{ inputs.attestationVariant }} - path: build/constellation - create-cluster: name: Create upgrade origin version cluster - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write checks: write @@ -190,14 +147,14 @@ jobs: steps: - name: Checkout if: inputs.gitRef == 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Checkout ref if: inputs.gitRef != 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 ref: ${{ inputs.gitRef }} @@ -215,11 +172,13 @@ jobs: osImage: ${{ inputs.fromVersion }} isDebugImage: "false" cliVersion: ${{ inputs.fromVersion }} + kubernetesVersion: ${{ inputs.fromKubernetes }} regionZone: ${{ inputs.regionZone }} gcpProject: constellation-e2e gcpClusterCreateServiceAccount: "infrastructure-e2e@constellation-e2e.iam.gserviceaccount.com" gcpIAMCreateServiceAccount: "iam-e2e@constellation-e2e.iam.gserviceaccount.com" test: "upgrade" + azureSubscriptionID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} azureClusterCreateCredentials: ${{ secrets.AZURE_E2E_CLUSTER_CREDENTIALS }} azureIAMCreateCredentials: ${{ secrets.AZURE_E2E_IAM_CREDENTIALS }} registry: ghcr.io @@ -261,7 +220,7 @@ jobs: e2e-upgrade: name: Run upgrade test - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write checks: write @@ -269,19 +228,18 @@ jobs: packages: write needs: - generate-input-parameters - - build-target-cli - create-cluster steps: - name: Checkout if: inputs.gitRef == 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Checkout ref if: inputs.gitRef != 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 ref: ${{ inputs.gitRef }} @@ -289,6 +247,32 @@ jobs: - name: Setup Bazel & Nix uses: ./.github/actions/setup_bazel_nix + - name: Log in to the Container registry + uses: ./.github/actions/container_registry_login + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # applying the version manipulation here so that the upgrade test tool is also on the simulated target version + - name: Simulate patch upgrade + if: inputs.simulatedTargetVersion != '' + run: | + echo ${{ inputs.simulatedTargetVersion }} > version.txt + + - name: Build CLI + uses: ./.github/actions/build_cli + with: + enterpriseCLI: true + outputPath: "build/constellation" + push: true + + - name: Upload CLI binary # is needed for the cleanup step + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + with: + name: constellation-upgrade-${{ inputs.attestationVariant }} + path: build/constellation + - name: Login to AWS uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 with: @@ -325,11 +309,6 @@ jobs: with: azure_credentials: ${{ secrets.AZURE_E2E_IAM_CREDENTIALS }} - - name: Download CLI - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 - with: - name: constellation-upgrade-${{ inputs.attestationVariant }} - path: build - name: Download Working Directory (Pre-test) uses: ./.github/actions/artifact_download @@ -394,15 +373,9 @@ jobs: echo "K8s target: $KUBERNETES" echo "Microservice target: $MICROSERVICES" - if [[ -n ${MICROSERVICES} ]]; then - MICROSERVICES_FLAG="--target-microservices=$MICROSERVICES" - fi - if [[ -n ${KUBERNETES} ]]; then - KUBERNETES_FLAG="--target-kubernetes=$KUBERNETES" - fi - sudo sh -c 'echo "127.0.0.1 license.confidential.cloud" >> /etc/hosts' - bazel run --test_timeout=14400 //e2e/internal/upgrade:upgrade_test -- --want-worker "$WORKERNODES" --want-control "$CONTROLNODES" --target-image "$IMAGE" "$KUBERNETES_FLAG" "$MICROSERVICES_FLAG" + CLI=$(realpath ./build/constellation) + bazel run --test_timeout=14400 //e2e/internal/upgrade:upgrade_test -- --want-worker "$WORKERNODES" --want-control "$CONTROLNODES" --target-image "$IMAGE" --target-kubernetes "$KUBERNETES" --target-microservices "$MICROSERVICES" --cli "$CLI" - name: Remove Terraform plugin cache if: always() @@ -426,7 +399,7 @@ jobs: clean-up: name: Clean up resources - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write checks: write @@ -438,20 +411,20 @@ jobs: steps: - name: Checkout if: inputs.gitRef == 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Checkout ref if: inputs.gitRef != 'head' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 ref: ${{ inputs.gitRef }} - name: Download CLI - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: constellation-upgrade-${{ inputs.attestationVariant }} path: build diff --git a/.github/workflows/e2e-windows.yml b/.github/workflows/e2e-windows.yml index 1d026263b..26ee8833b 100644 --- a/.github/workflows/e2e-windows.yml +++ b/.github/workflows/e2e-windows.yml @@ -13,7 +13,7 @@ on: jobs: build-cli: name: Build Windows CLI - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write checks: write @@ -21,7 +21,7 @@ jobs: packages: write steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} @@ -45,7 +45,7 @@ jobs: push: true - name: Upload CLI artifact - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: path: build/constellation.exe name: "constell-exe" @@ -56,12 +56,12 @@ jobs: needs: build-cli steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Download CLI artifact - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: "constell-exe" @@ -84,7 +84,7 @@ jobs: $rgName = "e2e-win-${{ github.run_id }}-${{ github.run_attempt }}-$uid" "rgName=$($rgName)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append .\constellation.exe config generate azure -t "workflow=${{ github.run_id }}" - .\constellation.exe iam create azure --region=westus --resourceGroup=$rgName-rg --servicePrincipal=$rgName-sp --update-config --debug -y + .\constellation.exe iam create azure --subscriptionID=${{ secrets.AZURE_SUBSCRIPTION_ID }} --region=westus --resourceGroup=$rgName-rg --servicePrincipal=$rgName-sp --update-config --debug -y - name: Login to Azure (Cluster service principal) uses: ./.github/actions/login_azure @@ -178,7 +178,7 @@ jobs: notify-failure: name: Notify about failure - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: e2e-test if: | failure() && @@ -186,7 +186,7 @@ jobs: inputs.scheduled steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} diff --git a/.github/workflows/on-release.yml b/.github/workflows/on-release.yml index c2cb79f93..1d46df5c9 100644 --- a/.github/workflows/on-release.yml +++ b/.github/workflows/on-release.yml @@ -15,7 +15,7 @@ on: jobs: complete-release-branch-transaction: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write contents: write @@ -26,7 +26,7 @@ jobs: WORKING_BRANCH: ${{ env.WORKING_BRANCH }} steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 # fetch all history @@ -44,12 +44,12 @@ jobs: git push origin "${WORKING_BRANCH}":"${RELEASE_BRANCH}" update: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 outputs: latest: ${{ steps.input-passthrough.outputs.latest }}${{ steps.check-last-release.outputs.latest }} steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Override latest if: github.event.inputs.latest == 'true' @@ -117,13 +117,13 @@ jobs: add-image-version-to-versionsapi, add-cli-version-to-versionsapi, ] - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write contents: write steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Remove temporary branch run: git push origin --delete "${{needs.complete-release-branch-transaction.outputs.WORKING_BRANCH}}" @@ -131,13 +131,13 @@ jobs: mirror-gcp-mpi: name: "Mirror GCP Marketplace Image" needs: [add-image-version-to-versionsapi] - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write contents: read steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/setup_bazel_nix @@ -159,9 +159,8 @@ jobs: id: fetch-reference shell: bash run: | - # TODO(msanft): Implement marketplace images for GCP SEV-SNP aws s3 cp s3://cdn-constellation-backend/constellation/v2/ref/-/stream/stable/${{ steps.fetch-version.outputs.output }}/image/info.json . - FULL_REF=$(yq e -r -oy '.list.[] | select(.attestationVariant == "gcp-sev-es") | .reference' info.json) + FULL_REF=$(yq e -r -oy '.list.[] | select(.attestationVariant == "gcp-sev-snp") | .reference' info.json) IMAGE_NAME=$(echo "${FULL_REF}" | cut -d / -f 5) echo "reference=$IMAGE_NAME" | tee -a "$GITHUB_OUTPUT" diff --git a/.github/workflows/purge-main.yml b/.github/workflows/purge-main.yml index c25a57549..b2d9403c9 100644 --- a/.github/workflows/purge-main.yml +++ b/.github/workflows/purge-main.yml @@ -10,7 +10,7 @@ on: jobs: find-version: name: Delete version from main ref - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 outputs: version: ${{ steps.find.outputs.version }} permissions: @@ -18,7 +18,7 @@ jobs: contents: read steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.head_ref }} @@ -47,6 +47,8 @@ jobs: ;; esac + - uses: ./.github/actions/setup_bazel_nix + - name: List versions id: list uses: ./.github/actions/versionsapi diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml new file mode 100644 index 000000000..2699b0895 --- /dev/null +++ b/.github/workflows/release-publish.yml @@ -0,0 +1,79 @@ +name: 'Release: on-publish' + +on: + release: + types: + - published + workflow_dispatch: + inputs: + tag: + description: 'Semantic version tag of the release (vX.Y.Z).' + required: true + +jobs: + post-release-actions: + runs-on: ubuntu-24.04 + permissions: + issues: write + env: + FULL_VERSION: ${{ github.event.release.tag_name }}${{ github.event.inputs.tag }} + GH_TOKEN: ${{ github.token }} + steps: + - name: Mark milestone as complete + run: | + milestones=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/edgelesssys/constellation/milestones) + + current_milestone=$(echo "${milestones}" | jq -r ".[] | select(.title == \"${FULL_VERSION}\")") + echo "current milestone: ${current_milestone}" + if [[ -z "${current_milestone}" ]]; then + echo "milestone ${FULL_VERSION} does not exist, nothing to do..." + exit 0 + fi + + current_milestone_state=$(echo "${current_milestone}" | jq -r '.state') + echo "current milestone state: ${current_milestone_state}" + if [[ "${current_milestone_state}" != "open" ]]; then + echo "milestone ${FULL_VERSION} is already closed, nothing to do..." + exit 0 + fi + + milestone_number=$(echo "${current_milestone}" | jq -r '.number') + echo "milestone number: ${milestone_number}" + if [[ -z "${milestone_number}" ]]; then + echo "failed parsing milestone number" + exit 1 + fi + + gh api \ + --method PATCH \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/edgelesssys/constellation/milestones/${milestone_number}" \ + -f state=closed + + - name: Create next milestone + run: | + WITHOUT_V=${FULL_VERSION#v} + PART_MAJOR=${WITHOUT_V%%.*} + PART_MINOR=${WITHOUT_V#*.} + PART_MINOR=${PART_MINOR%%.*} + NEXT_MINOR=v${PART_MAJOR}.$((PART_MINOR + 1)).0 + + gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/edgelesssys/constellation/milestones | + jq -r '.[].title' | \ + grep -xqF "${NEXT_MINOR}" && exit 0 + + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/edgelesssys/constellation/milestones \ + -f title="${NEXT_MINOR}" \ + -f state='open' \ + -f "due_on=$(date -d '2 months' +'%Y-%m-%dT00:00:00Z')" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5e9e28083..2db0f9eee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ concurrency: jobs: verify-inputs: name: Verify inputs - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: FULL_VERSION: ${{ inputs.version }} outputs: @@ -33,7 +33,7 @@ jobs: RELEASE_BRANCH: ${{ steps.version-info.outputs.RELEASE_BRANCH }} WORKING_BRANCH: ${{ steps.version-info.outputs.WORKING_BRANCH }} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Working branch run: echo "WORKING_BRANCH=$(git branch --show-current)" | tee -a "$GITHUB_ENV" @@ -72,10 +72,9 @@ jobs: echo "WORKING_BRANCH=${WORKING_BRANCH}" } | tee -a "$GITHUB_OUTPUT" - docs: - name: Create docs release (from main) - runs-on: ubuntu-22.04 - if: inputs.kind == 'minor' + update-main-branch: + name: Update main branch with release changes + runs-on: ubuntu-24.04 needs: verify-inputs permissions: contents: write @@ -85,36 +84,61 @@ jobs: MAJOR_MINOR: ${{ needs.verify-inputs.outputs.MAJOR_MINOR }} BRANCH: docs/${{ needs.verify-inputs.outputs.MAJOR_MINOR }} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: main + - name: Configure git + run: | + git config --global user.name "edgelessci" + git config --global user.email "edgelessci@users.noreply.github.com" + - name: Create docs release + if: inputs.kind == 'minor' working-directory: docs run: | - npm install + npm ci npm run docusaurus docs:version "${MAJOR_MINOR}" + git add . + git commit -am "docs: release ${MAJOR_MINOR}" + # Clean up auxiliary files, so next steps run on a clean tree + git clean -fdx :/ + + - name: Update version.txt + if: inputs.kind == 'minor' + run: | + pre_release_version="v${{ needs.verify-inputs.outputs.PART_MAJOR }}.$((${{ needs.verify-inputs.outputs.PART_MINOR }} + 1)).0-pre" + echo "${pre_release_version}" > version.txt + git add version.txt + git commit -m "chore: update version.txt to ${pre_release_version}" + + - name: Update CI for new version + run: | + sed -i 's/fromVersion: \["[^"]*"\]/fromVersion: ["${{ inputs.version }}"]/g' .github/workflows/e2e-test-release.yml + sed -i 's/fromVersion: \["[^"]*"\]/fromVersion: ["${{ inputs.version }}"]/g' .github/workflows/e2e-test-weekly.yml - name: Create docs pull request - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 + uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 with: branch: ${{ env.BRANCH }} base: main - title: "docs: add release ${{ env.VERSION }}" + title: "Post ${{ env.VERSION }} release updates to main" body: | :robot: *This is an automated PR.* :robot: The PR is triggered as part of the automated release process of version ${{ env.VERSION }}. - It releases a new version of the documentation. - commit-message: "docs: add release ${{ env.VERSION }}" + commit-message: "chore: update CI for ${{ env.VERSION }}" committer: edgelessci + author: edgelessci labels: no changelog + assignees: ${{ github.actor }} + reviewers: ${{ github.actor }} # We need to push changes using a token, otherwise triggers like on:push and on:pull_request won't work. token: ${{ !github.event.pull_request.head.repo.fork && secrets.CI_COMMIT_PUSH_PR || '' }} check-working-branch: name: Check temporary working branch - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: verify-inputs permissions: contents: write @@ -123,7 +147,7 @@ jobs: WORKING_BRANCH: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} @@ -152,7 +176,7 @@ jobs: update-versions: name: Update container image versions needs: [verify-inputs, check-working-branch] - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: contents: write packages: read @@ -161,7 +185,7 @@ jobs: WITHOUT_V: ${{ needs.verify-inputs.outputs.WITHOUT_V }} steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} @@ -220,20 +244,20 @@ jobs: needs: [verify-inputs, os-image] permissions: contents: write - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: VERSION: ${{ inputs.version }} WITHOUT_V: ${{ needs.verify-inputs.outputs.WITHOUT_V }} steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} - name: Setup Go environment - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 with: - go-version: "1.22.3" + go-version: "1.23.2" cache: true - name: Build generateMeasurements tool @@ -250,8 +274,12 @@ jobs: run: | git config --global user.name "edgelessci" git config --global user.email "edgelessci@users.noreply.github.com" - git commit -m "attestation: hardcode measurements for ${VERSION}" - git push + if git diff-index --quiet HEAD --; then + echo "No changes to commit" + else + git commit -m "attestation: hardcode measurements for ${VERSION}" + git push + fi draft-release: name: Draft release (CLI) @@ -278,6 +306,7 @@ jobs: packages: write id-token: write contents: read + actions: write secrets: inherit with: ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} diff --git a/.github/workflows/reproducible-builds.yml b/.github/workflows/reproducible-builds.yml index bb2ee475a..d0faa32b7 100644 --- a/.github/workflows/reproducible-builds.yml +++ b/.github/workflows/reproducible-builds.yml @@ -1,8 +1,9 @@ # Verify that Constellation builds are reproducible. # -# The build-* jobs' matrix has two dimensions: a list of targets to build and -# a list of runners to build on. The produced binaries and OS images are -# expected to be bit-for-bit identical, regardless of the chosen build runner. +# The build-* jobs' matrix has three dimensions: a list of targets to build, a +# list of runners to build on and a method of installing dependencies. The +# produced binaries and OS images are expected to be bit-for-bit identical, +# without any dependencies on the runtime setup details. # # The compare-* jobs only have the target dimension. They obtain the built # targets from all runners and check that there are no diffs between them. @@ -24,19 +25,38 @@ jobs: - "cli_enterprise_linux_amd64" - "cli_enterprise_linux_arm64" - "cli_enterprise_windows_amd64" - runner: ["ubuntu-22.04", "ubuntu-20.04"] + runner: + - "ubuntu-24.04" + - "ubuntu-22.04" + deps: + - conventional + - eccentric env: bazel_target: "//cli:${{ matrix.target }}" - binary: "${{ matrix.target }}-${{ matrix.runner }}" + binary: "${{ matrix.target }}-${{ matrix.runner }}-${{ matrix.deps }}" runs-on: ${{ matrix.runner }} steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - - name: Setup bazel + - name: Setup dependencies uses: ./.github/actions/setup_bazel_nix + if: matrix.deps == 'conventional' + + - name: Setup dependencies (eccentric) + if: matrix.deps == 'eccentric' + run: | + version=$(cat .bazelversion) + mkdir -p "$HOME/.local/bin" + curl -fsSL -o "$HOME/.local/bin/bazel" "https://github.com/bazelbuild/bazel/releases/download/$version/bazel-$version-linux-x86_64" + chmod a+x "$HOME/.local/bin/bazel" + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + + curl -fsSL -o "$HOME/.local/bin/nix-installer" https://github.com/DeterminateSystems/nix-installer/releases/download/v0.26.3/nix-installer-x86_64-linux # renovate:github-release + chmod a+x "$HOME/.local/bin/nix-installer" + "$HOME/.local/bin/nix-installer" install --no-confirm - name: Build shell: bash @@ -57,15 +77,15 @@ jobs: run: shasum -a 256 "${binary}" | tee "${binary}.sha256" - name: Upload binary artifact - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: - name: "binaries-${{ matrix.target }}-${{ matrix.runner }}" + name: "binaries-${{ matrix.target }}-${{ matrix.runner }}-${{ matrix.deps }}" path: "${{ env.binary }}" - name: Upload hash artifact - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: - name: "sha256sums-${{ matrix.target }}-${{ matrix.runner }}" + name: "sha256sums-${{ matrix.target }}-${{ matrix.runner }}-${{ matrix.deps }}" path: "${{ env.binary }}.sha256" build-osimages: @@ -77,14 +97,26 @@ jobs: - "aws_aws-nitro-tpm_console" - "qemu_qemu-vtpm_debug" - "gcp_gcp-sev-snp_nightly" - runner: ["ubuntu-22.04", "ubuntu-20.04"] + runner: ["ubuntu-24.04", "ubuntu-22.04"] env: bazel_target: "//image/system:${{ matrix.target }}" binary: "osimage-${{ matrix.target }}-${{ matrix.runner }}" runs-on: ${{ matrix.runner }} steps: + - name: Remove security hardening features + if: matrix.runner == 'ubuntu-24.04' + shell: bash + run: | + # Taken from https://github.com/systemd/mkosi/blob/fcacc94b9f72d9b6b1f03779b0c6e07209ceb54b/action.yaml#L42-L57. + sudo sysctl --ignore --write kernel.apparmor_restrict_unprivileged_unconfined=0 + sudo sysctl --ignore --write kernel.apparmor_restrict_unprivileged_userns=0 + # This command fails with a non-zero error code even though it unloads the apparmor profiles. + # https://gitlab.com/apparmor/apparmor/-/issues/403 + sudo aa-teardown || true + sudo apt-get remove -y apparmor + - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} @@ -110,13 +142,13 @@ jobs: run: shasum -a 256 "${binary}" | tee "${binary}.sha256" - name: Upload binary artifact - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: "osimages-${{ matrix.target }}-${{ matrix.runner }}" path: "${{ env.binary }}" - name: Upload hash artifact - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: "sha256sums-${{ matrix.target }}-${{ matrix.runner }}" path: "${{ env.binary }}.sha256" @@ -132,14 +164,14 @@ jobs: - "cli_enterprise_linux_amd64" - "cli_enterprise_linux_arm64" - "cli_enterprise_windows_amd64" - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Download binaries - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: pattern: "binaries-${{ matrix.target }}-*" merge-multiple: true @@ -166,14 +198,14 @@ jobs: - "aws_aws-nitro-tpm_console" - "qemu_qemu-vtpm_debug" - "gcp_gcp-sev-snp_nightly" - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Download os images - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: pattern: "osimages-${{ matrix.target }}-*" merge-multiple: true diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 666517bb8..f5c996507 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -9,7 +9,7 @@ on: jobs: analysis: name: Scorecard analysis - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: # Needed to upload the results to code-scanning dashboard. security-events: write @@ -18,25 +18,25 @@ jobs: steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: Run analysis - uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3 + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 with: results_file: results.sarif results_format: sarif publish_results: true - name: Upload artifact - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: SARIF file path: results.sarif retention-days: 5 - name: Upload to code-scanning - uses: github/codeql-action/upload-sarif@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5 + uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 with: sarif_file: results.sarif diff --git a/.github/workflows/sync-terraform-docs.yml b/.github/workflows/sync-terraform-docs.yml index 657c49d2f..6b9be623d 100644 --- a/.github/workflows/sync-terraform-docs.yml +++ b/.github/workflows/sync-terraform-docs.yml @@ -18,14 +18,14 @@ jobs: pull-requests: write steps: - name: Checkout constellation repo - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} fetch-depth: 0 path: constellation - name: Checkout terraform-provider-constellation repo - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: edgelesssys/terraform-provider-constellation ref: main @@ -40,7 +40,7 @@ jobs: - name: Create pull request id: create-pull-request - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 + uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 with: path: terraform-provider-constellation branch: "feat/docs/update" diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index ef36a5530..c6908ff3d 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -20,12 +20,12 @@ on: jobs: integration-test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: CTEST_OUTPUT_ON_FAILURE: True steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} diff --git a/.github/workflows/test-operator-codegen.yml b/.github/workflows/test-operator-codegen.yml index c8064bfe9..06a7129d9 100644 --- a/.github/workflows/test-operator-codegen.yml +++ b/.github/workflows/test-operator-codegen.yml @@ -18,17 +18,17 @@ on: jobs: govulncheck: name: check-codegen - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Setup Go environment - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 with: - go-version: "1.22.3" + go-version: "1.23.2" cache: true - name: Run code generation diff --git a/.github/workflows/test-tfsec.yml b/.github/workflows/test-tfsec.yml index 1818ec5c7..5517ac887 100644 --- a/.github/workflows/test-tfsec.yml +++ b/.github/workflows/test-tfsec.yml @@ -17,13 +17,13 @@ on: jobs: tfsec: name: tfsec - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: contents: read pull-requests: write steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} diff --git a/.github/workflows/test-tidy.yml b/.github/workflows/test-tidy.yml index eb0fa204d..99585ddaf 100644 --- a/.github/workflows/test-tidy.yml +++ b/.github/workflows/test-tidy.yml @@ -17,7 +17,7 @@ jobs: contents: read steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} # No token available for forks, so we can't push changes @@ -51,7 +51,9 @@ jobs: - name: Run Bazel tidy shell: bash - run: bazel run //:tidy + run: | + bazel run //:tidy + bazel mod deps --lockfile_mode=update - name: Check if untidy id: untidy @@ -96,10 +98,11 @@ jobs: exit 0 fi + # Use quadruple backticks to escape triple backticks in diff'ed files. cat << EOF >> "${GITHUB_STEP_SUMMARY}" - \`\`\`diff + \`\`\`\`diff ${diff} - \`\`\` + \`\`\`\` EOF if [[ "${{ steps.untidy.outputs.untidy }}" == "true" ]] && diff --git a/.github/workflows/test-unittest.yml b/.github/workflows/test-unittest.yml index c3bb14c04..b676e7dca 100644 --- a/.github/workflows/test-unittest.yml +++ b/.github/workflows/test-unittest.yml @@ -30,7 +30,7 @@ jobs: pull-requests: write steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} fetch-depth: 0 diff --git a/.github/workflows/update-rpms.yml b/.github/workflows/update-rpms.yml index ef8a42a55..bd30519ef 100644 --- a/.github/workflows/update-rpms.yml +++ b/.github/workflows/update-rpms.yml @@ -7,13 +7,15 @@ on: jobs: update-rpms: - runs-on: "ubuntu-22.04" + runs-on: "ubuntu-24.04" permissions: id-token: write contents: read steps: - name: Checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + token: ${{ secrets.CI_COMMIT_PUSH_PR }} - name: Assume AWS role to upload Bazel dependencies to S3 uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 @@ -37,7 +39,7 @@ jobs: fi - name: Create pull request - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 + uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 with: branch: "image/automated/update-rpms-${{ github.run_number }}" base: main @@ -49,6 +51,7 @@ jobs: It updates the locked rpm packages that form the Constellation OS images. commit-message: "image: update locked rpms" committer: edgelessci + author: edgelessci labels: dependencies # We need to push changes using a token, otherwise triggers like on:push and on:pull_request won't work. token: ${{ !github.event.pull_request.head.repo.fork && secrets.CI_COMMIT_PUSH_PR || '' }} diff --git a/.github/workflows/versionsapi.yml b/.github/workflows/versionsapi.yml index 4d193bf0a..c4e62d412 100644 --- a/.github/workflows/versionsapi.yml +++ b/.github/workflows/versionsapi.yml @@ -106,7 +106,7 @@ concurrency: jobs: versionsapi: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: id-token: write contents: read @@ -115,7 +115,7 @@ jobs: steps: - name: Check out repository id: checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} @@ -180,6 +180,8 @@ jobs: with: service_account: "image-deleter@constellation-images.iam.gserviceaccount.com" + - uses: ./.github/actions/setup_bazel_nix + - name: Execute versionsapi CLI id: run uses: ./.github/actions/versionsapi diff --git a/.lychee.toml b/.lychee.toml index 9106ef457..70b1a2652 100644 --- a/.lychee.toml +++ b/.lychee.toml @@ -33,6 +33,10 @@ exclude = [ '^https://portal\.azure\.com/', # The Wireguard website sproadically returns 500. '^https://www\.wireguard\.com/', + # venturebeat detects our link checker + '^https://venturebeat\.com/', + # dev-docs reference the internal wiki + '^https://github\.com/edgelesssys/wiki', ] # Exclude these filesystem paths from getting checked. diff --git a/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.need b/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.need index d3cf0338e..8542c18a4 100644 --- a/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.need +++ b/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.need @@ -8,10 +8,7 @@ go_library( "internal_cross.go", ], cgo = True, - cdeps = select({ - "@//bazel/settings:tpm_simulator_enabled": ["//simulator/ms-tpm-20-ref:ms_tpm_20_ref"], - "//conditions:default": ["@//3rdparty/bazel/com_github_google_go_tpm_tools/placeholder:ms_tpm_20_ref_disabled"], - }), + cdeps = ["//simulator/ms-tpm-20-ref:ms_tpm_20_ref"], copts = [ "-fno-sanitize=all", # relax sanitizer checks for this test-only dependency ], diff --git a/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.orig b/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.orig index 3fc9a7d32..bb03b408a 100644 --- a/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.orig +++ b/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.orig @@ -73,9 +73,15 @@ go_library( "@io_bazel_rules_go//go/platform:openbsd": [ "-fstack-protector-all", ], + "@io_bazel_rules_go//go/platform:osx": [ + "-fstack-protector-all", + ], "@io_bazel_rules_go//go/platform:plan9": [ "-fstack-protector-all", ], + "@io_bazel_rules_go//go/platform:qnx": [ + "-fstack-protector-all", + ], "@io_bazel_rules_go//go/platform:solaris": [ "-fstack-protector-all", ], diff --git a/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.patch b/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.patch index 238e50f9e..ad04c2292 100644 --- a/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.patch +++ b/3rdparty/bazel/com_github_google_go_tpm_tools/com_github_google_go_tpm_tools.patch @@ -1,6 +1,6 @@ --- simulator/internal/BUILD.bazel +++ simulator/internal/BUILD.bazel -@@ -4,83 +4,17 @@ +@@ -4,89 +4,14 @@ go_library( name = "internal", srcs = [ "doc.go", @@ -17,10 +17,8 @@ - "-L/usr/local/opt/openssl/lib", - ], - "//conditions:default": [], -+ cdeps = select({ -+ "@//bazel/settings:tpm_simulator_enabled": ["//simulator/ms-tpm-20-ref:ms_tpm_20_ref"], -+ "//conditions:default": ["@//3rdparty/bazel/com_github_google_go_tpm_tools/placeholder:ms_tpm_20_ref_disabled"], - }), +- }), ++ cdeps = ["//simulator/ms-tpm-20-ref:ms_tpm_20_ref"], copts = [ - "-DALG_SHA512=ALG_YES", - "-DCERTIFYX509_DEBUG=NO", @@ -76,9 +74,15 @@ - "@io_bazel_rules_go//go/platform:openbsd": [ - "-fstack-protector-all", - ], +- "@io_bazel_rules_go//go/platform:osx": [ +- "-fstack-protector-all", +- ], - "@io_bazel_rules_go//go/platform:plan9": [ - "-fstack-protector-all", - ], +- "@io_bazel_rules_go//go/platform:qnx": [ +- "-fstack-protector-all", +- ], - "@io_bazel_rules_go//go/platform:solaris": [ - "-fstack-protector-all", - ], diff --git a/3rdparty/bazel/com_github_google_go_tpm_tools/ms_tpm_20_ref.need b/3rdparty/bazel/com_github_google_go_tpm_tools/ms_tpm_20_ref.need index 83b388537..7758874e6 100644 --- a/3rdparty/bazel/com_github_google_go_tpm_tools/ms_tpm_20_ref.need +++ b/3rdparty/bazel/com_github_google_go_tpm_tools/ms_tpm_20_ref.need @@ -229,8 +229,10 @@ cc_library( ], deps = [ ":ms_tpm_20_ref_google_samples", - "@//nix/cc:org_openssl", - ], + ] + select({ + "@io_bazel_rules_go//go/platform:linux_arm64": ["@@org_openssl_aarch64-linux//:org_openssl"], + "@io_bazel_rules_go//go/platform:linux_amd64": ["@@org_openssl_x86_64-linux//:org_openssl"], + }), target_compatible_with = [ "@platforms//os:linux", ] diff --git a/3rdparty/bazel/com_github_google_go_tpm_tools/ms_tpm_20_ref.patch b/3rdparty/bazel/com_github_google_go_tpm_tools/ms_tpm_20_ref.patch index e98141b8a..8340c947f 100644 --- a/3rdparty/bazel/com_github_google_go_tpm_tools/ms_tpm_20_ref.patch +++ b/3rdparty/bazel/com_github_google_go_tpm_tools/ms_tpm_20_ref.patch @@ -1,6 +1,6 @@ --- simulator/ms-tpm-20-ref/BUILD.bazel +++ simulator/ms-tpm-20-ref/BUILD.bazel -@@ -0,0 +1,512 @@ +@@ -0,0 +1,516 @@ +cc_library( + name = "ms_tpm_20_ref", + visibility = ["//visibility:public"], @@ -229,10 +229,14 @@ + ], + deps = [ + ":ms_tpm_20_ref_google_samples", -+ "@//nix/cc:org_openssl", -+ ], ++ ] + select({ ++ "@io_bazel_rules_go//go/platform:darwin_arm64": ["@@org_openssl_aarch64-darwin//:org_openssl"], ++ "@io_bazel_rules_go//go/platform:darwin_amd64": ["@@org_openssl_x86_64-darwin//:org_openssl"], ++ "@io_bazel_rules_go//go/platform:linux_arm64": ["@@org_openssl_aarch64-linux//:org_openssl"], ++ "@io_bazel_rules_go//go/platform:linux_amd64": ["@@org_openssl_x86_64-linux//:org_openssl"], ++ }), + target_compatible_with = [ -+ "@platforms//os:linux", ++ "@@platforms//os:linux", + ], +) + diff --git a/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/BUILD.bazel b/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/BUILD.bazel deleted file mode 100644 index 07d713e46..000000000 --- a/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/BUILD.bazel +++ /dev/null @@ -1,12 +0,0 @@ -load("@rules_cc//cc:defs.bzl", "cc_library") - -cc_library( - name = "ms_tpm_20_ref_disabled", - srcs = ["ms_tpm_20_disabled.c"], - hdrs = [ - "Platform.h", - "Tpm.h", - ], - includes = ["."], - visibility = ["//visibility:public"], -) diff --git a/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/Platform.h b/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/Platform.h deleted file mode 100644 index 8aaa55d10..000000000 --- a/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/Platform.h +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include - -extern int g_inFailureMode; - -typedef union { - uint16_t size; - uint8_t *buffer; -} TPM2B, TPM2B_SEED; -typedef struct -{ - TPM2B_SEED EPSeed; - TPM2B_SEED SPSeed; - TPM2B_SEED PPSeed; -} PERSISTENT_DATA; - -extern PERSISTENT_DATA gp; - -void _plat__Reset(bool forceManufacture); -void _plat__RunCommand(uint32_t requestSize, unsigned char *request, - uint32_t *responseSize, unsigned char **response); diff --git a/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/Tpm.h b/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/Tpm.h deleted file mode 100644 index 2e94e1749..000000000 --- a/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/Tpm.h +++ /dev/null @@ -1,27 +0,0 @@ -#undef TRUE -#define TRUE 1 -#undef FALSE -#define FALSE 0 -#undef YES -#define YES 1 -#undef NO -#define NO 0 -#undef SET -#define SET 1 -#undef CLEAR -#define CLEAR 0 -#ifndef MAX_RESPONSE_SIZE -#define MAX_RESPONSE_SIZE 4096 -#endif - -#ifndef EPSeed -#define EPSeed 1 -#endif -#ifndef SPSeed -#define SPSeed 1 -#endif -#ifndef PPSeed -#define PPSeed 1 -#endif - -#define NV_SYNC_PERSISTENT(x) diff --git a/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/ms_tpm_20_disabled.c b/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/ms_tpm_20_disabled.c deleted file mode 100644 index a56d7f43c..000000000 --- a/3rdparty/bazel/com_github_google_go_tpm_tools/placeholder/ms_tpm_20_disabled.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "Platform.h" -#include "Tpm.h" - -int g_inFailureMode = 0; - -void _plat__Reset(bool forceManufacture) {} - -void _plat__RunCommand(uint32_t requestSize, unsigned char *request, - uint32_t *responseSize, unsigned char **response) {} diff --git a/3rdparty/bazel/com_github_martinjungblut_go_cryptsetup/com_github_martinjungblut_go_cryptsetup.patch b/3rdparty/bazel/com_github_martinjungblut_go_cryptsetup/com_github_martinjungblut_go_cryptsetup.patch index f87c1a730..0319cc797 100644 --- a/3rdparty/bazel/com_github_martinjungblut_go_cryptsetup/com_github_martinjungblut_go_cryptsetup.patch +++ b/3rdparty/bazel/com_github_martinjungblut_go_cryptsetup/com_github_martinjungblut_go_cryptsetup.patch @@ -4,9 +4,9 @@ "plain.go", ], cgo = True, -+ cdeps = [ -+ "@//nix/cc:cryptsetup", -+ ], ++ cdeps = select({ ++ "@io_bazel_rules_go//go/platform:linux_amd64": ["@@cryptsetup_x86_64-linux//:cryptsetup"], ++ }), importpath = "github.com/martinjungblut/go-cryptsetup", visibility = ["//visibility:public"], ) diff --git a/3rdparty/bazel/com_github_medik8s_node_maintainance_operator/source.bzl b/3rdparty/bazel/com_github_medik8s_node_maintainance_operator/source.bzl index a9d20a08c..aa81fc947 100644 --- a/3rdparty/bazel/com_github_medik8s_node_maintainance_operator/source.bzl +++ b/3rdparty/bazel/com_github_medik8s_node_maintainance_operator/source.bzl @@ -6,10 +6,10 @@ def node_maintainance_operator_deps(): http_archive( name = "com_github_medik8s_node_maintainance_operator", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/df5ea2f9d982dd78770f2549333fd40aaf40e50a28deec9d7892f83cf9d1bdb2", - "https://github.com/medik8s/node-maintenance-operator/archive/refs/tags/v0.15.0.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/6ccc7f152e5c595ab24eaadcda77870101eccc482694dc6f0d93be2528406ae2", + "https://github.com/medik8s/node-maintenance-operator/archive/refs/tags/v0.17.0.tar.gz", ], - strip_prefix = "node-maintenance-operator-0.15.0", + strip_prefix = "node-maintenance-operator-0.17.0", build_file_content = """ api_v1beta1 = glob(["api/v1beta1/*.go"]) filegroup( @@ -19,5 +19,5 @@ filegroup( ) """, type = "tar.gz", - sha256 = "df5ea2f9d982dd78770f2549333fd40aaf40e50a28deec9d7892f83cf9d1bdb2", + sha256 = "6ccc7f152e5c595ab24eaadcda77870101eccc482694dc6f0d93be2528406ae2", ) diff --git a/3rdparty/bazel/org_golang/go_tls_max_handshake_size.patch b/3rdparty/bazel/org_golang/go_tls_max_handshake_size.patch index ac2da752f..5370f99e7 100644 --- a/3rdparty/bazel/org_golang/go_tls_max_handshake_size.patch +++ b/3rdparty/bazel/org_golang/go_tls_max_handshake_size.patch @@ -1,11 +1,11 @@ --- src/crypto/tls/common.go +++ src/crypto/tls/common.go -@@ -62,7 +62,7 @@ - maxCiphertext = 16384 + 2048 // maximum ciphertext payload length - maxCiphertextTLS13 = 16384 + 256 // maximum ciphertext length in TLS 1.3 - recordHeaderLen = 5 // record header length -- maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) -+ maxHandshake = 262144 // maximum handshake we support (protocol max is 16 MB) - maxUselessRecords = 16 // maximum number of consecutive non-advancing records +@@ -64,7 +64,7 @@ const ( + maxCiphertext = 16384 + 2048 // maximum ciphertext payload length + maxCiphertextTLS13 = 16384 + 256 // maximum ciphertext length in TLS 1.3 + recordHeaderLen = 5 // record header length +- maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) ++ maxHandshake = 262144 // maximum handshake we support (protocol max is 16 MB) + maxHandshakeCertificateMsg = 262144 // maximum certificate message size (256 KiB) + maxUselessRecords = 16 // maximum number of consecutive non-advancing records ) - diff --git a/3rdparty/bazel/org_libvirt_go_libvirt/go_libvirt.patch b/3rdparty/bazel/org_libvirt_go_libvirt/go_libvirt.patch index d2c799cae..78150041c 100644 --- a/3rdparty/bazel/org_libvirt_go_libvirt/go_libvirt.patch +++ b/3rdparty/bazel/org_libvirt_go_libvirt/go_libvirt.patch @@ -5,7 +5,7 @@ "typedparams.go", ], + cdeps = [ -+ "@//nix/cc:libvirt", ++ "@@libvirt_x86_64-linux//:libvirt", + ], cgo = True, importpath = "libvirt.org/go/libvirt", diff --git a/3rdparty/gcp-guest-agent/Dockerfile b/3rdparty/gcp-guest-agent/Dockerfile index c3dbeb507..0276f8259 100644 --- a/3rdparty/gcp-guest-agent/Dockerfile +++ b/3rdparty/gcp-guest-agent/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04@sha256:a6d2b38300ce017add71440577d5b0a90460d0e57fd7aec21dd0d1b0761bbfb2 as build +FROM ubuntu:22.04@sha256:0e5e4a57c2499249aafc3b40fcd541e9a456aab7296681a3994d631587203f97 as build # Install packages RUN apt-get update && apt-get install -y \ diff --git a/BUILD.bazel b/BUILD.bazel index b2443e4b5..6e09ef814 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,5 +1,5 @@ exports_files([ - "WORKSPACE.bazel", + "WORKSPACE.bzlmod", ]) alias( diff --git a/CODEOWNERS b/CODEOWNERS index 69c1ac3e1..fd7e2d8a0 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,7 +1,7 @@ # keep-sorted start .golangci.yml @katexochen -/3rdparty/gcp-guest-agent @malt3 -/bazel @malt3 +/3rdparty/gcp-guest-agent @3u13r +/bazel @burgerdev /bazel/ci @katexochen /bazel/sh @katexochen /bootstrapper @3u13r @@ -10,58 +10,57 @@ /cli/internal/libvirt @daniel-weisse /cli/internal/terraform @elchead /csi @daniel-weisse -/debugd @malt3 +/debugd @daniel-weisse /disk-mapper @daniel-weisse /docs @thomasten /e2e @3u13r /hack/azure-snp-report-verify @derpsteb -/hack/bazel-deps-mirror @malt3 +/hack/bazel-deps-mirror @burgerdev /hack/cli-k8s-compatibility @derpsteb /hack/clidocgen @thomasten /hack/fetch-broken-e2e @katexochen /hack/gocoverage @katexochen -/hack/oci-pin @malt3 +/hack/oci-pin @burgerdev /hack/qemu-metadata-api @daniel-weisse /hack/remove-tf-providers @katexochen /hack/terraform @3u13r /hack/tools @katexochen /hack/versioninfogen @daniel-weisse -/image @malt3 +/image @msanft /internal/api @derpsteb /internal/atls @thomasten /internal/attestation @daniel-weisse /internal/cloud @3u13r /internal/compatibility @derpsteb /internal/config @derpsteb -/internal/constellation/featureset @malt3 -/internal/constellation/helm @derpsteb +/internal/constellation/featureset @thomasten +/internal/constellation/helm @burgerdev /internal/constellation/kubecmd @daniel-weisse /internal/constellation/state @elchead -/internal/containerimage @malt3 +/internal/containerimage @burgerdev /internal/crypto @thomasten /internal/cryptsetup @daniel-weisse /internal/file @daniel-weisse /internal/grpc @thomasten -/internal/imagefetcher @malt3 +/internal/imagefetcher @msanft /internal/installer @3u13r /internal/kms @daniel-weisse -/internal/kubernetes @malt3 +/internal/kubernetes @3u13r /internal/license @thomasten /internal/logger @daniel-weisse /internal/nodestate @daniel-weisse -/internal/osimage @malt3 +/internal/osimage @msanft /internal/retry @katexochen /internal/semver @derpsteb /internal/sigstore @elchead -/internal/staticupload @malt3 +/internal/staticupload @msanft /internal/versions @3u13r /joinservice @daniel-weisse /keyservice @daniel-weisse /measurement-reader @daniel-weisse -/operators @malt3 -/rpm @malt3 +/operators @3u13r /terraform-provider-constellation @msanft @elchead -/tools @malt3 +/tools @burgerdev /upgrade-agent @3u13r /verify @daniel-weisse # keep-sorted end diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 000000000..111a0f6ad --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,208 @@ +module(name = "constellation") + +bazel_dep(name = "aspect_bazel_lib", version = "2.9.4") + +bazel_lib = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "toolchains") +bazel_lib.yq() +use_repo(bazel_lib, "jq_toolchains") +use_repo(bazel_lib, "yq_toolchains") + +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "gazelle", version = "0.39.1") +bazel_dep(name = "hermetic_cc_toolchain", version = "3.1.1") +bazel_dep(name = "rules_cc", version = "0.1.0") +bazel_dep(name = "rules_go", version = "0.50.1", repo_name = "io_bazel_rules_go") +bazel_dep(name = "rules_pkg", version = "0.10.1") +bazel_dep(name = "rules_proto", version = "6.0.2") +bazel_dep(name = "rules_python", version = "0.40.0") + +bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True) + +go_sdk = use_extension("@io_bazel_rules_go//go:extensions.bzl", "go_sdk") +go_sdk.download( + name = "go_sdk", + patches = ["//3rdparty/bazel/org_golang:go_tls_max_handshake_size.patch"], + version = "1.23.2", +) + +python = use_extension("@rules_python//python/extensions:python.bzl", "python") +python.toolchain( + ignore_root_user_error = True, + python_version = "3.11", +) + +# the use_repo rule needs to list all top-level go dependencies +# update automatically using `bazel mod tidy`. +go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps") +go_deps.from_file(go_work = "//:go.work") +use_repo( + go_deps, + "cat_dario_mergo", + "com_github_aws_aws_sdk_go", + "com_github_aws_aws_sdk_go_v2", + "com_github_aws_aws_sdk_go_v2_config", + "com_github_aws_aws_sdk_go_v2_credentials", + "com_github_aws_aws_sdk_go_v2_feature_ec2_imds", + "com_github_aws_aws_sdk_go_v2_feature_s3_manager", + "com_github_aws_aws_sdk_go_v2_service_autoscaling", + "com_github_aws_aws_sdk_go_v2_service_cloudfront", + "com_github_aws_aws_sdk_go_v2_service_ec2", + "com_github_aws_aws_sdk_go_v2_service_elasticloadbalancingv2", + "com_github_aws_aws_sdk_go_v2_service_resourcegroupstaggingapi", + "com_github_aws_aws_sdk_go_v2_service_s3", + "com_github_aws_aws_sdk_go_v2_service_secretsmanager", + "com_github_aws_smithy_go", + "com_github_azure_azure_sdk_for_go", + "com_github_azure_azure_sdk_for_go_sdk_azcore", + "com_github_azure_azure_sdk_for_go_sdk_azidentity", + "com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v6", + "com_github_azure_azure_sdk_for_go_sdk_resourcemanager_network_armnetwork_v6", + "com_github_azure_azure_sdk_for_go_sdk_security_keyvault_azsecrets", + "com_github_azure_azure_sdk_for_go_sdk_storage_azblob", + "com_github_bazelbuild_buildtools", + "com_github_burntsushi_toml", + "com_github_coreos_go_systemd_v22", + "com_github_docker_docker", + "com_github_edgelesssys_go_azguestattestation", + "com_github_edgelesssys_go_tdx_qpl", + "com_github_foxboron_go_uefi", + "com_github_fsnotify_fsnotify", + "com_github_go_playground_locales", + "com_github_go_playground_universal_translator", + "com_github_go_playground_validator_v10", + "com_github_golang_jwt_jwt_v5", + "com_github_google_go_licenses", + "com_github_google_go_sev_guest", + "com_github_google_go_tdx_guest", + "com_github_google_go_tpm", + "com_github_google_go_tpm_tools", + "com_github_google_keep_sorted", + "com_github_google_uuid", + "com_github_googleapis_gax_go_v2", + "com_github_gophercloud_gophercloud_v2", + "com_github_gophercloud_utils_v2", + "com_github_grpc_ecosystem_go_grpc_middleware_v2", + "com_github_hashicorp_go_kms_wrapping_v2", + "com_github_hashicorp_go_kms_wrapping_wrappers_awskms_v2", + "com_github_hashicorp_go_kms_wrapping_wrappers_azurekeyvault_v2", + "com_github_hashicorp_go_kms_wrapping_wrappers_gcpckms_v2", + "com_github_hashicorp_go_version", + "com_github_hashicorp_hc_install", + "com_github_hashicorp_hcl_v2", + "com_github_hashicorp_terraform_exec", + "com_github_hashicorp_terraform_json", + "com_github_hashicorp_terraform_plugin_framework", + "com_github_hashicorp_terraform_plugin_framework_validators", + "com_github_hashicorp_terraform_plugin_go", + "com_github_hashicorp_terraform_plugin_log", + "com_github_hashicorp_terraform_plugin_testing", + "com_github_hexops_gotextdiff", + "com_github_katexochen_sh_v3", + "com_github_martinjungblut_go_cryptsetup", + "com_github_mattn_go_isatty", + "com_github_mitchellh_go_homedir", + "com_github_onsi_ginkgo_v2", + "com_github_onsi_gomega", + "com_github_pkg_errors", + "com_github_regclient_regclient", + "com_github_rogpeppe_go_internal", + "com_github_samber_slog_multi", + "com_github_schollz_progressbar_v3", + "com_github_secure_systems_lab_go_securesystemslib", + "com_github_siderolabs_talos_pkg_machinery", + "com_github_sigstore_rekor", + "com_github_sigstore_sigstore", + "com_github_spf13_afero", + "com_github_spf13_cobra", + "com_github_spf13_pflag", + "com_github_stretchr_testify", + "com_github_tink_crypto_tink_go_v2", + "com_github_vincent_petithory_dataurl", + "com_google_cloud_go_compute", + "com_google_cloud_go_compute_metadata", + "com_google_cloud_go_kms", + "com_google_cloud_go_secretmanager", + "com_google_cloud_go_storage", + "in_gopkg_yaml_v3", + "io_etcd_go_etcd_api_v3", + "io_etcd_go_etcd_client_pkg_v3", + "io_etcd_go_etcd_client_v3", + "io_k8s_api", + "io_k8s_apiextensions_apiserver", + "io_k8s_apimachinery", + "io_k8s_apiserver", + "io_k8s_client_go", + "io_k8s_cluster_bootstrap", + "io_k8s_kubelet", + "io_k8s_kubernetes", + "io_k8s_mount_utils", + "io_k8s_sigs_controller_runtime", + "io_k8s_sigs_yaml", + "io_k8s_utils", + "org_golang_google_api", + "org_golang_google_grpc", + "org_golang_google_protobuf", + "org_golang_x_crypto", + "org_golang_x_exp", + "org_golang_x_mod", + "org_golang_x_sys", + "org_golang_x_text", + "org_golang_x_tools", + "org_golang_x_vuln", + "org_libvirt_go_libvirt", + "org_uber_go_goleak", + "sh_helm_helm_v3", +) + +go_deps_with_disabled_proto_generation = [ + "go.etcd.io/etcd/api/v3", + "k8s.io/apiserver", + "github.com/hashicorp/go-plugin", +] + +[ + go_deps.gazelle_override( + directives = [ + "gazelle:go_generate_proto false", + ], + path = path, + ) + for path in go_deps_with_disabled_proto_generation +] + +go_deps.module_override( + patches = [ + "//3rdparty/bazel/com_github_martinjungblut_go_cryptsetup:com_github_martinjungblut_go_cryptsetup.patch", + ], + path = "github.com/martinjungblut/go-cryptsetup", +) +go_deps.module_override( + patches = [ + "//3rdparty/bazel/org_libvirt_go_libvirt:go_libvirt.patch", + ], + path = "libvirt.org/go/libvirt", +) +go_deps.module_override( + patches = [ + "//3rdparty/bazel/com_github_cloudflare_circl:math_fp448_BUILD_bazel.patch", + "//3rdparty/bazel/com_github_cloudflare_circl:math_fp25519_BUILD_bazel.patch", + "//3rdparty/bazel/com_github_cloudflare_circl:dh_x448_BUILD_bazel.patch", + "//3rdparty/bazel/com_github_cloudflare_circl:dh_x25519_BUILD_bazel.patch", + ], + path = "github.com/cloudflare/circl", +) +go_deps.module_override( + patches = [ + "//3rdparty/bazel/com_github_google_go_tpm_tools:com_github_google_go_tpm_tools.patch", + "//3rdparty/bazel/com_github_google_go_tpm_tools:ms_tpm_20_ref.patch", + "//3rdparty/bazel/com_github_google_go_tpm_tools:include.patch", + ], + path = "github.com/google/go-tpm-tools", +) + +# TODO(msanft): +# Remove once https://github.com/cncf/xds/issues/104 is resolved +go_deps.gazelle_override( + build_file_generation = "on", + path = "github.com/cncf/xds/go", +) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock new file mode 100644 index 000000000..4782a3045 --- /dev/null +++ b/MODULE.bazel.lock @@ -0,0 +1,3662 @@ +{ + "lockFileVersion": 11, + "registryFileHashes": { + "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", + "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", + "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", + "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da", + "https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef", + "https://bcr.bazel.build/modules/apple_support/1.5.0/source.json": "eb98a7627c0bc486b57f598ad8da50f6625d974c8f723e9ea71bd39f709c9862", + "https://bcr.bazel.build/modules/aspect_bazel_lib/2.9.4/MODULE.bazel": "ccc41028429f894b02fde7ef67d416cba3ba5084ed9ddb9bb6107aa82d118776", + "https://bcr.bazel.build/modules/aspect_bazel_lib/2.9.4/source.json": "9e20ebe57de2e7657a188af6e132a9562fa26c201b2d999bc0a8981e8f3b6c36", + "https://bcr.bazel.build/modules/bazel_features/1.1.0/MODULE.bazel": "cfd42ff3b815a5f39554d97182657f8c4b9719568eb7fded2b9135f084bf760b", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", + "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", + "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", + "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", + "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", + "https://bcr.bazel.build/modules/bazel_features/1.19.0/source.json": "d7bf14517c1b25b9d9c580b0f8795fceeae08a7590f507b76aace528e941375d", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", + "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", + "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", + "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953", + "https://bcr.bazel.build/modules/buildifier_prebuilt/6.4.0/MODULE.bazel": "37389c6b5a40c59410b4226d3bb54b08637f393d66e2fa57925c6fcf68e64bf4", + "https://bcr.bazel.build/modules/buildifier_prebuilt/6.4.0/source.json": "83eb01b197ed0b392f797860c9da5ed1bf95f4d0ded994d694a3d44731275916", + "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", + "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", + "https://bcr.bazel.build/modules/gazelle/0.32.0/MODULE.bazel": "b499f58a5d0d3537f3cf5b76d8ada18242f64ec474d8391247438bf04f58c7b8", + "https://bcr.bazel.build/modules/gazelle/0.33.0/MODULE.bazel": "a13a0f279b462b784fb8dd52a4074526c4a2afe70e114c7d09066097a46b3350", + "https://bcr.bazel.build/modules/gazelle/0.34.0/MODULE.bazel": "abdd8ce4d70978933209db92e436deb3a8b737859e9354fb5fd11fb5c2004c8a", + "https://bcr.bazel.build/modules/gazelle/0.36.0/MODULE.bazel": "e375d5d6e9a6ca59b0cb38b0540bc9a05b6aa926d322f2de268ad267a2ee74c0", + "https://bcr.bazel.build/modules/gazelle/0.39.1/MODULE.bazel": "1fa3fefad240e535066fd0e6950dfccd627d36dc699ee0034645e51dbde3980f", + "https://bcr.bazel.build/modules/gazelle/0.39.1/source.json": "f2facfa8c8c9a4d2ebf613754023054c2eb793b88675082216c6be0419eb20a1", + "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", + "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4", + "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", + "https://bcr.bazel.build/modules/hermetic_cc_toolchain/3.1.1/MODULE.bazel": "164331a6e73093376a19eaa1eae45a94aad3245e9e79d8f31237f4a8eb6c1c41", + "https://bcr.bazel.build/modules/hermetic_cc_toolchain/3.1.1/source.json": "a2f67694b91ae575e2715fa2c5745c8c9879e7132852ef45c05b4e25a0d3b423", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "https://bcr.bazel.build/modules/platforms/0.0.10/source.json": "f22828ff4cf021a6b577f1bf6341cb9dcd7965092a439f64fc1bb3b7a5ae4bd5", + "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", + "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", + "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", + "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", + "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", + "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", + "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", + "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2/source.json": "52101bfd37e38f0d159dee47b71ccbd1f22f7a32192cef5ef2533bb6212f410f", + "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/protobuf/3.19.2/MODULE.bazel": "532ffe5f2186b69fdde039efe6df13ba726ff338c6bc82275ad433013fa10573", + "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4", + "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", + "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", + "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", + "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", + "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac", + "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", + "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", + "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", + "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", + "https://bcr.bazel.build/modules/rules_cc/0.1.0/MODULE.bazel": "2fef03775b9ba995ec543868840041cc69e8bc705eb0cb6604a36eee18c87d8b", + "https://bcr.bazel.build/modules/rules_cc/0.1.0/source.json": "8a4e832d75e073ab56c74dd77008cf7a81e107dec4544019eb1eefc1320d55be", + "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e", + "https://bcr.bazel.build/modules/rules_go/0.41.0/MODULE.bazel": "55861d8e8bb0e62cbd2896f60ff303f62ffcb0eddb74ecb0e5c0cbe36fc292c8", + "https://bcr.bazel.build/modules/rules_go/0.42.0/MODULE.bazel": "8cfa875b9aa8c6fce2b2e5925e73c1388173ea3c32a0db4d2b4804b453c14270", + "https://bcr.bazel.build/modules/rules_go/0.46.0/MODULE.bazel": "3477df8bdcc49e698b9d25f734c4f3a9f5931ff34ee48a2c662be168f5f2d3fd", + "https://bcr.bazel.build/modules/rules_go/0.50.1/MODULE.bazel": "b91a308dc5782bb0a8021ad4330c81fea5bda77f96b9e4c117b9b9c8f6665ee0", + "https://bcr.bazel.build/modules/rules_go/0.50.1/source.json": "205765fd30216c70321f84c9a967267684bdc74350af3f3c46c857d9f80a4fa2", + "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", + "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", + "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39", + "https://bcr.bazel.build/modules/rules_java/6.3.0/MODULE.bazel": "a97c7678c19f236a956ad260d59c86e10a463badb7eb2eda787490f4c969b963", + "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6", + "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", + "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", + "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", + "https://bcr.bazel.build/modules/rules_java/7.12.2/source.json": "b0890f9cda8ff1b8e691a3ac6037b5c14b7fd4134765a3946b89f31ea02e5884", + "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", + "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", + "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", + "https://bcr.bazel.build/modules/rules_java/7.6.5/MODULE.bazel": "481164be5e02e4cab6e77a36927683263be56b7e36fef918b458d7a8a1ebadb1", + "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", + "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", + "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d", + "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", + "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", + "https://bcr.bazel.build/modules/rules_license/0.0.4/MODULE.bazel": "6a88dd22800cf1f9f79ba32cacad0d3a423ed28efa2c2ed5582eaa78dd3ac1e5", + "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", + "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", + "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", + "https://bcr.bazel.build/modules/rules_pkg/0.10.1/MODULE.bazel": "d6e593e048db5f1028f1f05ceb64b123aa6f1c2d43cba049c036443ab2cc2044", + "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", + "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", + "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", + "https://bcr.bazel.build/modules/rules_proto/6.0.0/MODULE.bazel": "b531d7f09f58dce456cd61b4579ce8c86b38544da75184eadaf0a7cb7966453f", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1", + "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", + "https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7", + "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", + "https://bcr.bazel.build/modules/rules_python/0.24.0/MODULE.bazel": "4bff7f583653d0762cda21303da0643cc4c545ddfd9593337f18dad8d1787801", + "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", + "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", + "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", + "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", + "https://bcr.bazel.build/modules/rules_python/0.40.0/source.json": "939d4bd2e3110f27bfb360292986bb79fd8dcefb874358ccd6cdaa7bda029320", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95", + "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", + "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", + "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", + "https://bcr.bazel.build/modules/stardoc/0.6.2/MODULE.bazel": "7060193196395f5dd668eda046ccbeacebfd98efc77fed418dbe2b82ffaa39fd", + "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", + "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7", + "https://bcr.bazel.build/modules/stardoc/0.7.1/source.json": "b6500ffcd7b48cd72c29bb67bcac781e12701cc0d6d55d266a652583cfcdab01", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", + "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", + "https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d", + "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" + }, + "selectedYankedVersions": {}, + "moduleExtensions": { + "@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": { + "general": { + "bzlTransitiveDigest": "PjIds3feoYE8SGbbIq2SFTZy3zmxeO2tQevJZNDo7iY=", + "usagesDigest": "aLmqbvowmHkkBPve05yyDNGN7oh7QE9kBADr3QIZTZs=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "local_config_apple_cc": { + "bzlFile": "@@apple_support~//crosstool:setup.bzl", + "ruleClassName": "_apple_cc_autoconf", + "attributes": {} + }, + "local_config_apple_cc_toolchains": { + "bzlFile": "@@apple_support~//crosstool:setup.bzl", + "ruleClassName": "_apple_cc_autoconf_toolchains", + "attributes": {} + } + }, + "recordedRepoMappingEntries": [ + [ + "apple_support~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@aspect_bazel_lib~//lib:extensions.bzl%toolchains": { + "general": { + "bzlTransitiveDigest": "NQSsfq2SQcHqmSrdUz3fctBGq66C56eokoZzu0MOhBU=", + "usagesDigest": "E1/WNi/RvQIo2JMDoqkXAe3ImUnQhegOYDC/dY2DVAk=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "expand_template_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "copy_to_directory_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "jq_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "1.7" + } + }, + "copy_to_directory_freebsd_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "expand_template_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "jq_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_platform_repo", + "attributes": { + "platform": "linux_arm64", + "version": "1.7" + } + }, + "coreutils_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "0.0.27" + } + }, + "copy_to_directory_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "bsd_tar_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "bsdtar_binary_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "copy_directory_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "coreutils_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "0.0.27" + } + }, + "coreutils_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_platform_repo", + "attributes": { + "platform": "linux_arm64", + "version": "0.0.27" + } + }, + "zstd_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:zstd_toolchain.bzl", + "ruleClassName": "zstd_binary_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "yq_linux_s390x": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "linux_s390x", + "version": "4.25.2" + } + }, + "yq": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_host_alias_repo", + "attributes": {} + }, + "expand_template_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "copy_directory_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "jq_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "1.7" + } + }, + "yq_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "4.25.2" + } + }, + "copy_directory_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "expand_template_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_toolchains_repo", + "attributes": { + "user_repository_name": "expand_template" + } + }, + "bats_assert": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "98ca3b685f8b8993e48ec057565e6e2abcc541034ed5b0e81f191505682037fd", + "urls": [ + "https://github.com/bats-core/bats-assert/archive/v2.1.0.tar.gz" + ], + "strip_prefix": "bats-assert-2.1.0", + "build_file_content": "load(\"@aspect_bazel_lib//lib:copy_to_directory.bzl\", \"copy_to_directory\")\n\ncopy_to_directory(\n name = \"assert\",\n hardlink = \"on\",\n srcs = glob([\n \"src/**\",\n \"load.bash\",\n ]),\n out = \"bats-assert\",\n visibility = [\"//visibility:public\"]\n)\n" + } + }, + "copy_to_directory_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "zstd_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:zstd_toolchain.bzl", + "ruleClassName": "zstd_binary_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "bsd_tar_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "bsdtar_binary_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "yq_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_toolchains_repo", + "attributes": { + "user_repository_name": "yq" + } + }, + "zstd_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:zstd_toolchain.bzl", + "ruleClassName": "zstd_binary_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "bats_support": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "7815237aafeb42ddcc1b8c698fc5808026d33317d8701d5ec2396e9634e2918f", + "urls": [ + "https://github.com/bats-core/bats-support/archive/v0.3.0.tar.gz" + ], + "strip_prefix": "bats-support-0.3.0", + "build_file_content": "load(\"@aspect_bazel_lib//lib:copy_to_directory.bzl\", \"copy_to_directory\")\n\ncopy_to_directory(\n name = \"support\",\n hardlink = \"on\",\n srcs = glob([\n \"src/**\",\n \"load.bash\",\n ]),\n out = \"bats-support\",\n visibility = [\"//visibility:public\"]\n)\n" + } + }, + "bsd_tar_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "bsdtar_binary_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "jq": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_host_alias_repo", + "attributes": {} + }, + "expand_template_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "bsd_tar_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "bsdtar_binary_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "copy_to_directory_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "coreutils_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "0.0.27" + } + }, + "copy_directory_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_toolchains_repo", + "attributes": { + "user_repository_name": "copy_directory" + } + }, + "yq_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "4.25.2" + } + }, + "copy_to_directory_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "coreutils_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_toolchains_repo", + "attributes": { + "user_repository_name": "coreutils" + } + }, + "copy_directory_freebsd_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "zstd_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:zstd_toolchain.bzl", + "ruleClassName": "zstd_binary_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "zstd_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:zstd_toolchain.bzl", + "ruleClassName": "zstd_toolchains_repo", + "attributes": { + "user_repository_name": "zstd" + } + }, + "bats_file": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "9b69043241f3af1c2d251f89b4fcafa5df3f05e97b89db18d7c9bdf5731bb27a", + "urls": [ + "https://github.com/bats-core/bats-file/archive/v0.4.0.tar.gz" + ], + "strip_prefix": "bats-file-0.4.0", + "build_file_content": "load(\"@aspect_bazel_lib//lib:copy_to_directory.bzl\", \"copy_to_directory\")\n\ncopy_to_directory(\n name = \"file\",\n hardlink = \"on\",\n srcs = glob([\n \"src/**\",\n \"load.bash\",\n ]),\n out = \"bats-file\",\n visibility = [\"//visibility:public\"]\n)\n" + } + }, + "expand_template_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "jq_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "1.7" + } + }, + "bsd_tar_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "bsdtar_binary_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "bsd_tar_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "tar_toolchains_repo", + "attributes": { + "user_repository_name": "bsd_tar" + } + }, + "bats_toolchains": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "a1a9f7875aa4b6a9480ca384d5865f1ccf1b0b1faead6b47aa47d79709a5c5fd", + "urls": [ + "https://github.com/bats-core/bats-core/archive/v1.10.0.tar.gz" + ], + "strip_prefix": "bats-core-1.10.0", + "build_file_content": "load(\"@local_config_platform//:constraints.bzl\", \"HOST_CONSTRAINTS\")\nload(\"@aspect_bazel_lib//lib/private:bats_toolchain.bzl\", \"bats_toolchain\")\nload(\"@aspect_bazel_lib//lib:copy_to_directory.bzl\", \"copy_to_directory\")\n\ncopy_to_directory(\n name = \"core\",\n hardlink = \"on\",\n srcs = glob([\n \"lib/**\",\n \"libexec/**\"\n ]) + [\"bin/bats\"],\n out = \"bats-core\",\n)\n\nbats_toolchain(\n name = \"toolchain\",\n core = \":core\",\n libraries = [\"@bats_support//:support\", \"@bats_assert//:assert\", \"@bats_file//:file\"]\n)\n\ntoolchain(\n name = \"bats_toolchain\",\n exec_compatible_with = HOST_CONSTRAINTS,\n toolchain = \":toolchain\",\n toolchain_type = \"@aspect_bazel_lib//lib:bats_toolchain_type\",\n)\n" + } + }, + "yq_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "4.25.2" + } + }, + "jq_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "1.7" + } + }, + "expand_template_freebsd_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "yq_linux_ppc64le": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "linux_ppc64le", + "version": "4.25.2" + } + }, + "copy_to_directory_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_toolchains_repo", + "attributes": { + "user_repository_name": "copy_to_directory" + } + }, + "jq_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_toolchains_repo", + "attributes": { + "user_repository_name": "jq" + } + }, + "copy_directory_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "copy_directory_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "yq_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "4.25.2" + } + }, + "coreutils_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "0.0.27" + } + }, + "yq_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "linux_arm64", + "version": "4.25.2" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "aspect_bazel_lib~", + "aspect_bazel_lib", + "aspect_bazel_lib~" + ], + [ + "aspect_bazel_lib~", + "bazel_skylib", + "bazel_skylib~" + ], + [ + "aspect_bazel_lib~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@buildifier_prebuilt~//:defs.bzl%buildifier_prebuilt_deps_extension": { + "general": { + "bzlTransitiveDigest": "eXBP0KrRexbBjR0KdxpnbWtfahy0r48xfQb4hBQ4Mcc=", + "usagesDigest": "nThSTPRdiQbhDFl8FRM2nsKJftWMtPBQHrp/mdk716w=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "buildozer_darwin_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildozer-darwin-amd64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "d29e347ecd6b5673d72cb1a8de05bf1b06178dd229ff5eb67fad5100c840cc8e" + } + }, + "buildifier_linux_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildifier-linux-amd64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "be63db12899f48600bad94051123b1fd7b5251e7661b9168582ce52396132e92" + } + }, + "buildozer_darwin_arm64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildozer-darwin-arm64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "9b9e71bdbec5e7223871e913b65d12f6d8fa026684daf991f00e52ed36a6978d" + } + }, + "buildozer_linux_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildozer-linux-amd64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "8dfd6345da4e9042daa738d7fdf34f699c5dfce4632f7207956fceedd8494119" + } + }, + "buildozer_windows_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildozer-windows-amd64.exe" + ], + "downloaded_file_path": "buildozer.exe", + "executable": true, + "sha256": "e7f05bf847f7c3689dd28926460ce6e1097ae97380ac8e6ae7147b7b706ba19b" + } + }, + "buildozer_linux_arm64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildozer-linux-arm64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "6559558fded658c8fa7432a9d011f7c4dcbac6b738feae73d2d5c352e5f605fa" + } + }, + "buildifier_windows_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildifier-windows-amd64.exe" + ], + "downloaded_file_path": "buildifier.exe", + "executable": true, + "sha256": "da8372f35e34b65fb6d997844d041013bb841e55f58b54d596d35e49680fe13c" + } + }, + "buildifier_prebuilt_toolchains": { + "bzlFile": "@@buildifier_prebuilt~//:defs.bzl", + "ruleClassName": "_buildifier_toolchain_setup", + "attributes": { + "assets_json": "[{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"darwin\",\"sha256\":\"eeb47b2de27f60efe549348b183fac24eae80f1479e8b06cac0799c486df5bed\",\"version\":\"v6.4.0\"},{\"arch\":\"arm64\",\"name\":\"buildifier\",\"platform\":\"darwin\",\"sha256\":\"fa07ba0d20165917ca4cc7609f9b19a8a4392898148b7babdf6bb2a7dd963f05\",\"version\":\"v6.4.0\"},{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"linux\",\"sha256\":\"be63db12899f48600bad94051123b1fd7b5251e7661b9168582ce52396132e92\",\"version\":\"v6.4.0\"},{\"arch\":\"arm64\",\"name\":\"buildifier\",\"platform\":\"linux\",\"sha256\":\"18540fc10f86190f87485eb86963e603e41fa022f88a2d1b0cf52ff252b5e1dd\",\"version\":\"v6.4.0\"},{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"windows\",\"sha256\":\"da8372f35e34b65fb6d997844d041013bb841e55f58b54d596d35e49680fe13c\",\"version\":\"v6.4.0\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"darwin\",\"sha256\":\"d29e347ecd6b5673d72cb1a8de05bf1b06178dd229ff5eb67fad5100c840cc8e\",\"version\":\"v6.4.0\"},{\"arch\":\"arm64\",\"name\":\"buildozer\",\"platform\":\"darwin\",\"sha256\":\"9b9e71bdbec5e7223871e913b65d12f6d8fa026684daf991f00e52ed36a6978d\",\"version\":\"v6.4.0\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"linux\",\"sha256\":\"8dfd6345da4e9042daa738d7fdf34f699c5dfce4632f7207956fceedd8494119\",\"version\":\"v6.4.0\"},{\"arch\":\"arm64\",\"name\":\"buildozer\",\"platform\":\"linux\",\"sha256\":\"6559558fded658c8fa7432a9d011f7c4dcbac6b738feae73d2d5c352e5f605fa\",\"version\":\"v6.4.0\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"windows\",\"sha256\":\"e7f05bf847f7c3689dd28926460ce6e1097ae97380ac8e6ae7147b7b706ba19b\",\"version\":\"v6.4.0\"}]" + } + }, + "buildifier_darwin_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildifier-darwin-amd64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "eeb47b2de27f60efe549348b183fac24eae80f1479e8b06cac0799c486df5bed" + } + }, + "buildifier_darwin_arm64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildifier-darwin-arm64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "fa07ba0d20165917ca4cc7609f9b19a8a4392898148b7babdf6bb2a7dd963f05" + } + }, + "buildifier_linux_arm64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildifier-linux-arm64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "18540fc10f86190f87485eb86963e603e41fa022f88a2d1b0cf52ff252b5e1dd" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "buildifier_prebuilt~", + "bazel_skylib", + "bazel_skylib~" + ], + [ + "buildifier_prebuilt~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@hermetic_cc_toolchain~//toolchain:ext.bzl%toolchains": { + "general": { + "bzlTransitiveDigest": "L0EDVXQ1bqh5CxjodeVieW+SjWsjwxFXYEKhUNgMY50=", + "usagesDigest": "dNvS5vmHnd33Wm8wEDdfCELM1fuXE9dmHYK9BLQTjPc=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "zig_sdk": { + "bzlFile": "@@hermetic_cc_toolchain~//toolchain:defs.bzl", + "ruleClassName": "zig_repository", + "attributes": { + "version": "0.12.0", + "url_formats": [ + "https://mirror.bazel.build/ziglang.org/download/{version}/zig-{host_platform}-{version}.{_ext}", + "https://ziglang.org/download/{version}/zig-{host_platform}-{version}.{_ext}" + ], + "host_platform_sha256": { + "linux-aarch64": "754f1029484079b7e0ca3b913a0a2f2a6afd5a28990cb224fe8845e72f09de63", + "linux-x86_64": "c7ae866b8a76a568e2d5cfd31fe89cdb629bdd161fdd5018b29a4a0a17045cad", + "macos-aarch64": "294e224c14fd0822cfb15a35cf39aa14bd9967867999bf8bdfe3db7ddec2a27f", + "macos-x86_64": "4d411bf413e7667821324da248e8589278180dbc197f4f282b7dbb599a689311", + "windows-aarch64": "04c6b92689241ca7a8a59b5f12d2ca2820c09d5043c3c4808b7e93e41c7bf97b", + "windows-x86_64": "2199eb4c2000ddb1fba85ba78f1fcf9c1fb8b3e57658f6a627a8e513131893f5" + }, + "host_platform_ext": { + "linux-aarch64": "tar.xz", + "linux-x86_64": "tar.xz", + "macos-aarch64": "tar.xz", + "macos-x86_64": "tar.xz", + "windows-x86_64": "zip" + } + } + } + }, + "recordedRepoMappingEntries": [ + [ + "hermetic_cc_toolchain~", + "bazel_tools", + "bazel_tools" + ], + [ + "hermetic_cc_toolchain~", + "hermetic_cc_toolchain", + "hermetic_cc_toolchain~" + ] + ] + } + }, + "@@platforms//host:extension.bzl%host_platform": { + "general": { + "bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=", + "usagesDigest": "oS5QVdWCSAWner9adrekJ2fs1FPUng+yVuoJb9mq6e4=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "host_platform": { + "bzlFile": "@@platforms//host:extension.bzl", + "ruleClassName": "host_platform_repo", + "attributes": {} + } + }, + "recordedRepoMappingEntries": [] + } + }, + "@@pybind11_bazel~//:python_configure.bzl%extension": { + "general": { + "bzlTransitiveDigest": "3LPSHhLo7VQLO+x5c48KQmJdPDwEMqMdeng5XVAZm4Y=", + "usagesDigest": "e/EIZlWEpIWcNL1dkob+QepsV4rx7UmnvodvXa76ycY=", + "recordedFileInputs": { + "@@pybind11_bazel~//MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e" + }, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "local_config_python": { + "bzlFile": "@@pybind11_bazel~//:python_configure.bzl", + "ruleClassName": "python_configure", + "attributes": {} + }, + "pybind11": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "build_file": "@@pybind11_bazel~//:pybind11.BUILD", + "strip_prefix": "pybind11-2.11.1", + "urls": [ + "https://github.com/pybind/pybind11/archive/v2.11.1.zip" + ] + } + } + }, + "recordedRepoMappingEntries": [ + [ + "pybind11_bazel~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_fuzzing~//fuzzing/private:extensions.bzl%non_module_dependencies": { + "general": { + "bzlTransitiveDigest": "aN6cDs7sOfBWTyYmCu+aV9nr3VKpDIZprzN+yGEsNO0=", + "usagesDigest": "X26dvBYyk1211bNrYvtOxec7AmnYf6DQEYUw1L0Oo74=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "bazel_skylib": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94", + "urls": [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz" + ] + } + }, + "rules_fuzzing_jazzer": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_jar", + "attributes": { + "sha256": "ee6feb569d88962d59cb59e8a31eb9d007c82683f3ebc64955fd5b96f277eec2", + "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer/0.20.1/jazzer-0.20.1.jar" + } + }, + "rules_python": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "d70cd72a7a4880f0000a6346253414825c19cdd40a28289bdf67b8e6480edff8", + "strip_prefix": "rules_python-0.28.0", + "url": "https://github.com/bazelbuild/rules_python/releases/download/0.28.0/rules_python-0.28.0.tar.gz" + } + }, + "rules_fuzzing_oss_fuzz": { + "bzlFile": "@@rules_fuzzing~//fuzzing/private/oss_fuzz:repository.bzl", + "ruleClassName": "oss_fuzz_repository", + "attributes": {} + }, + "com_google_absl": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "urls": [ + "https://github.com/abseil/abseil-cpp/archive/refs/tags/20240116.1.zip" + ], + "strip_prefix": "abseil-cpp-20240116.1", + "integrity": "sha256-7capMWOvWyoYbUaHF/b+I2U6XLMaHmky8KugWvfXYuk=" + } + }, + "honggfuzz": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "build_file": "@@rules_fuzzing~//:honggfuzz.BUILD", + "sha256": "6b18ba13bc1f36b7b950c72d80f19ea67fbadc0ac0bb297ec89ad91f2eaa423e", + "url": "https://github.com/google/honggfuzz/archive/2.5.zip", + "strip_prefix": "honggfuzz-2.5" + } + }, + "platforms": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "urls": [ + "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz", + "https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz" + ], + "sha256": "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74" + } + }, + "rules_fuzzing_jazzer_api": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_jar", + "attributes": { + "sha256": "f5a60242bc408f7fa20fccf10d6c5c5ea1fcb3c6f44642fec5af88373ae7aa1b", + "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer-api/0.20.1/jazzer-api-0.20.1.jar" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_fuzzing~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_kotlin~//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { + "general": { + "bzlTransitiveDigest": "l//eFZVgEUHSUfuQ1zQw9uxmcJku8ikraA2fv/2Pyh0=", + "usagesDigest": "NXmdQOmIAdsAdtLv3dhkX8UQ+0st9iQ0EkR28lUNdHc=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "rules_android": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", + "strip_prefix": "rules_android-0.1.1", + "urls": [ + "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip" + ] + } + }, + "com_github_pinterest_ktlint": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", + "urls": [ + "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint" + ], + "executable": true + } + }, + "com_github_jetbrains_kotlin": { + "bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:compiler.bzl", + "ruleClassName": "kotlin_capabilities_repository", + "attributes": { + "git_repository_name": "com_github_jetbrains_kotlin_git", + "compiler_version": "1.9.23" + } + }, + "com_github_jetbrains_kotlin_git": { + "bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:compiler.bzl", + "ruleClassName": "kotlin_compiler_git_repository", + "attributes": { + "urls": [ + "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip" + ], + "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88" + } + }, + "com_github_google_ksp": { + "bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:ksp.bzl", + "ruleClassName": "ksp_compiler_plugin_repository", + "attributes": { + "urls": [ + "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip" + ], + "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d", + "strip_version": "1.9.23-1.0.20" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_kotlin~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_python~//python/private/pypi:pip.bzl%pip_internal": { + "general": { + "bzlTransitiveDigest": "NuFWsw0F1ZHsRw6pAHHojBht90U7WPJQr64a2sg5Ib0=", + "usagesDigest": "/5Os1MEbCgZJ42ZFY1UZAhnLguIdryegbkM9Wq+We6Y=", + "recordedFileInputs": { + "@@rules_python~//tools/publish/requirements_linux.txt": "8175b4c8df50ae2f22d1706961884beeb54e7da27bd2447018314a175981997d", + "@@rules_python~//tools/publish/requirements_windows.txt": "7673adc71dc1a81d3661b90924d7a7c0fc998cd508b3cb4174337cef3f2de556", + "@@rules_python~//tools/publish/requirements_darwin.txt": "2994136eab7e57b083c3de76faf46f70fad130bc8e7360a7fed2b288b69e79dc" + }, + "recordedDirentsInputs": {}, + "envVariables": { + "RULES_PYTHON_REPO_DEBUG": null, + "RULES_PYTHON_REPO_DEBUG_VERBOSITY": null + }, + "generatedRepoSpecs": { + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944", + "urls": [ + "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_sdist_1c39c601": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "cffi-1.17.1.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", + "urls": [ + "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee", + "urls": [ + "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl" + ] + } + }, + "rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "urllib3-2.2.3-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "urllib3==2.2.3", + "sha256": "ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", + "urls": [ + "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc", + "urls": [ + "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4", + "urls": [ + "https://files.pythonhosted.org/packages/2a/2c/488776a3dc843f95f86d2f957ca0fc3407d0242b50bede7fad1e339be03f/cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_urllib3_sdist_e7d814a8": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "urllib3-2.2.3.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "urllib3==2.2.3", + "sha256": "e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", + "urls": [ + "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16", + "urls": [ + "https://files.pythonhosted.org/packages/21/ce/b9c9ff56c7164d8e2edfb6c9305045fbc0df4508ccfdb13ee66eb8c95b0e/cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "0411beb0589eacb6734f28d5497ca2ed379eafab8ad8c84b31bb5c34072b7164", + "urls": [ + "https://files.pythonhosted.org/packages/05/2b/85977d9e11713b5747595ee61f381bc820749daf83f07b90b6c9964cf932/nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_sdist_223217c3": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "charset_normalizer-3.4.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", + "urls": [ + "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594", + "urls": [ + "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_ppc64le_46bf4316": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", + "urls": [ + "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c", + "urls": [ + "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_cryptography_sdist_315b9001": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "cryptography-43.0.3.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805", + "urls": [ + "https://files.pythonhosted.org/packages/0d/05/07b55d1fa21ac18c3a8c79f764e2514e6f6a9698f1be44994f5adf0d29db/cryptography-43.0.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "5f36b271dae35c465ef5e9090e1fdaba4a60a56f0bb0ba03e0932a66f28b9189", + "urls": [ + "https://files.pythonhosted.org/packages/72/f2/5c894d5265ab80a97c68ca36f25c8f6f0308abac649aaf152b74e7e854a8/nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl" + ] + } + }, + "rules_python_publish_deps_311_secretstorage_sdist_2403533e": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "SecretStorage-3.3.3.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "secretstorage==3.3.3", + "sha256": "2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77", + "urls": [ + "https://files.pythonhosted.org/packages/53/a4/f48c9d79cb507ed1373477dbceaba7401fd8a23af63b837fa61f1dcd3691/SecretStorage-3.3.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "jaraco_functools-4.1.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-functools==4.1.0", + "sha256": "70f7e0e2ae076498e212562325e805204fc092d7b4c17e0e86c959e249701a9d", + "urls": [ + "https://files.pythonhosted.org/packages/ab/23/9894b3df5d0a6eb44611c36aec777823fc2e07740dabbd0b810e19594013/jaraco_functools-4.1.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "pycparser-2.22-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pycparser==2.22", + "sha256": "c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", + "urls": [ + "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", + "urls": [ + "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_idna_sdist_12f65c9b": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "idna-3.10.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "idna==3.10", + "sha256": "12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", + "urls": [ + "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "19aaba96e0f795bd0a6c56291495ff59364f4300d4a39b29a0abc9cb3774a84b", + "urls": [ + "https://files.pythonhosted.org/packages/c2/a8/3bb02d0c60a03ad3a112b76c46971e9480efa98a8946677b5a59f60130ca/nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl" + ] + } + }, + "rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "pywin32-ctypes-0.2.3.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pywin32-ctypes==0.2.3", + "sha256": "d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", + "urls": [ + "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "readme_renderer-44.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "readme-renderer==44.0", + "sha256": "2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151", + "urls": [ + "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_pygments_sdist_786ff802": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "pygments-2.18.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pygments==2.18.0", + "sha256": "786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", + "urls": [ + "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_ppc64le_f1a2f519": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365", + "urls": [ + "https://files.pythonhosted.org/packages/75/d2/0ab54463d3410709c09266dfb416d032a08f97fd7d60e94b8c6ef54ae14b/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "14c5a72e9fe82aea5fe3072116ad4661af5cf8e8ff8fc5ad3450f123e4925e86", + "urls": [ + "https://files.pythonhosted.org/packages/b3/89/1daff5d9ba5a95a157c092c7c5f39b8dd2b1ddb4559966f808d31cfb67e0/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl" + ] + } + }, + "rules_python_publish_deps_311_zipp_py3_none_any_a817ac80": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "zipp-3.20.2-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "zipp==3.20.2", + "sha256": "a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", + "urls": [ + "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "backports_tarfile-1.2.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "backports-tarfile==1.2.0", + "sha256": "d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", + "urls": [ + "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "jeepney-0.8.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jeepney==0.8.0", + "sha256": "c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755", + "urls": [ + "https://files.pythonhosted.org/packages/ae/72/2a1e2290f1ab1e06f71f3d0f1646c9e4634e70e1d37491535e19266e8dc9/jeepney-0.8.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "SecretStorage-3.3.3-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "secretstorage==3.3.3", + "sha256": "f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99", + "urls": [ + "https://files.pythonhosted.org/packages/54/24/b4293291fa1dd830f353d2cb163295742fa87f179fcc8a20a306a81978b7/SecretStorage-3.3.3-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "jaraco.classes-3.4.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-classes==3.4.0", + "sha256": "47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", + "urls": [ + "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27", + "urls": [ + "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73", + "urls": [ + "https://files.pythonhosted.org/packages/2a/33/b3682992ab2e9476b9c81fff22f02c8b0a1e6e1d49ee1750a67d85fd7ed2/cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "7b7c2a3c9eb1a827d42539aa64091640bd275b81e097cd1d8d82ef91ffa2e811", + "urls": [ + "https://files.pythonhosted.org/packages/2c/b6/42fc3c69cabf86b6b81e4c051a9b6e249c5ba9f8155590222c2622961f58/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "requests-toolbelt-1.0.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "requests-toolbelt==1.0.0", + "sha256": "7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", + "urls": [ + "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_rich_py3_none_any_9836f509": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "rich-13.9.3-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "rich==13.9.3", + "sha256": "9836f5096eb2172c9e77df411c1b009bace4193d6a481d534fea75ebba758283", + "urls": [ + "https://files.pythonhosted.org/packages/9a/e2/10e9819cf4a20bd8ea2f5dabafc2e6bf4a78d6a0965daeb60a4b34d1c11f/rich-13.9.3-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "importlib_metadata-8.5.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "importlib-metadata==8.5.0", + "sha256": "45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", + "urls": [ + "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_twine_py3_none_any_215dbe7b": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "twine-5.1.1-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "twine==5.1.1", + "sha256": "215dbe7b4b94c2c50a7315c0275d2258399280fbb7d04182c7e55e24b5f93997", + "urls": [ + "https://files.pythonhosted.org/packages/5d/ec/00f9d5fd040ae29867355e559a94e9a8429225a0284a3f5f091a3878bfc0/twine-5.1.1-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_docutils_sdist_3a6b1873": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "docutils-0.21.2.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "docutils==0.21.2", + "sha256": "3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", + "urls": [ + "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_keyring_sdist_b07ebc55": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "keyring-25.4.1.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "keyring==25.4.1", + "sha256": "b07ebc55f3e8ed86ac81dd31ef14e81ace9dd9c3d4b5d77a6e9a2016d0d71a1b", + "urls": [ + "https://files.pythonhosted.org/packages/a5/1c/2bdbcfd5d59dc6274ffb175bc29aa07ecbfab196830e0cfbde7bd861a2ea/keyring-25.4.1.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "markdown_it_py-3.0.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "markdown-it-py==3.0.0", + "sha256": "355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", + "urls": [ + "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_certifi_py3_none_any_922820b5": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "certifi-2024.8.30-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "certifi==2024.8.30", + "sha256": "922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", + "urls": [ + "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_more_itertools_sdist_5482bfef": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "more-itertools-10.5.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "more-itertools==10.5.0", + "sha256": "5482bfef7849c25dc3c6dd53a6173ae4795da2a41a80faea6700d9f5846c5da6", + "urls": [ + "https://files.pythonhosted.org/packages/51/78/65922308c4248e0eb08ebcbe67c95d48615cc6f27854b6f2e57143e9178f/more-itertools-10.5.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-win_amd64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "8ce0f819d2f1933953fca255db2471ad58184a60508f03e6285e5114b6254844", + "urls": [ + "https://files.pythonhosted.org/packages/26/8d/53c5b19c4999bdc6ba95f246f4ef35ca83d7d7423e5e38be43ad66544e5d/nh3-0.2.18-cp37-abi3-win_amd64.whl" + ] + } + }, + "rules_python_publish_deps_311_certifi_sdist_bec941d2": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "certifi-2024.8.30.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "certifi==2024.8.30", + "sha256": "bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9", + "urls": [ + "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", + "urls": [ + "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_mdurl_py3_none_any_84008a41": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "mdurl-0.1.2-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "mdurl==0.1.2", + "sha256": "84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", + "urls": [ + "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236", + "urls": [ + "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", + "urls": [ + "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl" + ] + } + }, + "rules_python_publish_deps_311_mdurl_sdist_bb413d29": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "mdurl-0.1.2.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "mdurl==0.1.2", + "sha256": "bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", + "urls": [ + "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_keyring_py3_none_any_5426f817": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "keyring-25.4.1-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "keyring==25.4.1", + "sha256": "5426f817cf7f6f007ba5ec722b1bcad95a75b27d780343772ad76b17cb47b0bf", + "urls": [ + "https://files.pythonhosted.org/packages/83/25/e6d59e5f0a0508d0dca8bb98c7f7fd3772fc943ac3f53d5ab18a218d32c0/keyring-25.4.1-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "42c64511469005058cd17cc1537578eac40ae9f7200bedcfd1fc1a05f4f8c200", + "urls": [ + "https://files.pythonhosted.org/packages/45/b9/833f385403abaf0023c6547389ec7a7acf141ddd9d1f21573723a6eab39a/nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_rfc3986_sdist_97aacf9d": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "rfc3986-2.0.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "rfc3986==2.0.0", + "sha256": "97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c", + "urls": [ + "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_twine_sdist_9aa08251": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "twine-5.1.1.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "twine==5.1.1", + "sha256": "9aa0825139c02b3434d913545c7b847a21c835e11597f5255842d457da2322db", + "urls": [ + "https://files.pythonhosted.org/packages/77/68/bd982e5e949ef8334e6f7dcf76ae40922a8750aa2e347291ae1477a4782b/twine-5.1.1.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_pkginfo_sdist_5df73835": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "pkginfo-1.10.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pkginfo==1.10.0", + "sha256": "5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297", + "urls": [ + "https://files.pythonhosted.org/packages/2f/72/347ec5be4adc85c182ed2823d8d1c7b51e13b9a6b0c1aae59582eca652df/pkginfo-1.10.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "backports.tarfile-1.2.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "backports-tarfile==1.2.0", + "sha256": "77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", + "urls": [ + "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "markdown-it-py-3.0.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "markdown-it-py==3.0.0", + "sha256": "e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", + "urls": [ + "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_ppc64le_ce031db0": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6", + "urls": [ + "https://files.pythonhosted.org/packages/e2/29/d227805bff72ed6d6cb1ce08eec707f7cfbd9868044893617eb331f16295/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "f0eca9ca8628dbb4e916ae2491d72957fdd35f7a5d326b7032a345f111ac07fe", + "urls": [ + "https://files.pythonhosted.org/packages/a3/da/0c4e282bc3cff4a0adf37005fa1fb42257673fbc1bbf7d1ff639ec3d255a/nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "pkginfo-1.10.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pkginfo==1.10.0", + "sha256": "889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097", + "urls": [ + "https://files.pythonhosted.org/packages/56/09/054aea9b7534a15ad38a363a2bd974c20646ab1582a387a95b8df1bfea1c/pkginfo-1.10.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_idna_py3_none_any_946d195a": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "idna-3.10-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "idna==3.10", + "sha256": "946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", + "urls": [ + "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_sdist_94a16692": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "nh3-0.2.18.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "94a166927e53972a9698af9542ace4e38b9de50c34352b962f4d9a7d4c927af4", + "urls": [ + "https://files.pythonhosted.org/packages/62/73/10df50b42ddb547a907deeb2f3c9823022580a7a47281e8eae8e003a9639/nh3-0.2.18.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_requests_sdist_55365417": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "requests-2.32.3.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "requests==2.32.3", + "sha256": "55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", + "urls": [ + "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5", + "urls": [ + "https://files.pythonhosted.org/packages/2f/78/55356eb9075d0be6e81b59f45c7b48df87f76a20e73893872170471f3ee8/cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_pycparser_sdist_491c8be9": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "pycparser-2.22.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pycparser==2.22", + "sha256": "491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", + "urls": [ + "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "de3ceed6e661954871d6cd78b410213bdcb136f79aafe22aa7182e028b8c7307", + "urls": [ + "https://files.pythonhosted.org/packages/1b/63/6ab90d0e5225ab9780f6c9fb52254fa36b52bb7c188df9201d05b647e5e1/nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "pygments-2.18.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pygments==2.18.0", + "sha256": "b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", + "urls": [ + "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_importlib_metadata_sdist_71522656": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "importlib_metadata-8.5.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "importlib-metadata==8.5.0", + "sha256": "71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7", + "urls": [ + "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "3a157ab149e591bb638a55c8c6bcb8cdb559c8b12c13a8affaba6cedfe51713a", + "urls": [ + "https://files.pythonhosted.org/packages/de/81/c291231463d21da5f8bba82c8167a6d6893cc5419b0639801ee5d3aeb8a9/nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl" + ] + } + }, + "rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "jaraco.context-6.0.1-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-context==6.0.1", + "sha256": "f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4", + "urls": [ + "https://files.pythonhosted.org/packages/ff/db/0c52c4cf5e4bd9f5d7135ec7669a3a767af21b3a308e1ed3674881e52b62/jaraco.context-6.0.1-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "more_itertools-10.5.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "more-itertools==10.5.0", + "sha256": "037b0d3203ce90cca8ab1defbbdac29d5f993fc20131f3664dc8d6acfa872aef", + "urls": [ + "https://files.pythonhosted.org/packages/48/7e/3a64597054a70f7c86eb0a7d4fc315b8c1ab932f64883a297bdffeb5f967/more_itertools-10.5.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129", + "urls": [ + "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64le_34c03fa7": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "34c03fa78e328c691f982b7c03d4423bdfd7da69cd707fe572f544cf74ac23ad", + "urls": [ + "https://files.pythonhosted.org/packages/ab/a7/375afcc710dbe2d64cfbd69e31f82f3e423d43737258af01f6a56d844085/nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl" + ] + } + }, + "rules_python_publish_deps_311_rich_sdist_bc1e01b8": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "rich-13.9.3.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "rich==13.9.3", + "sha256": "bc1e01b899537598cf02579d2b9f4a415104d3fc439313a7a2c165d76557a08e", + "urls": [ + "https://files.pythonhosted.org/packages/d9/e9/cf9ef5245d835065e6673781dbd4b8911d352fb770d56cf0879cf11b7ee1/rich-13.9.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "requests_toolbelt-1.0.0-py2.py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "requests-toolbelt==1.0.0", + "sha256": "cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", + "urls": [ + "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", + "urls": [ + "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", + "urls": [ + "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7", + "urls": [ + "https://files.pythonhosted.org/packages/7c/04/2345ca92f7a22f601a9c62961741ef7dd0127c39f7310dffa0041c80f16f/cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "docutils-0.21.2-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "docutils==0.21.2", + "sha256": "dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", + "urls": [ + "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_windows_x86_64" + ], + "filename": "pywin32_ctypes-0.2.3-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pywin32-ctypes==0.2.3", + "sha256": "8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", + "urls": [ + "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "36c95d4b70530b320b365659bb5034341316e6a9b30f0b25fa9c9eff4c27a204", + "urls": [ + "https://files.pythonhosted.org/packages/eb/61/73a007c74c37895fdf66e0edcd881f5eaa17a348ff02f4bb4bc906d61085/nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_jeepney_sdist_5efe48d2": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "jeepney-0.8.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jeepney==0.8.0", + "sha256": "5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806", + "urls": [ + "https://files.pythonhosted.org/packages/d6/f4/154cf374c2daf2020e05c3c6a03c91348d59b23c5366e968feb198306fdf/jeepney-0.8.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405", + "urls": [ + "https://files.pythonhosted.org/packages/ac/25/e715fa0bc24ac2114ed69da33adf451a38abb6f3f24ec207908112e9ba53/cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "rfc3986-2.0.0-py2.py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "rfc3986==2.0.0", + "sha256": "50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", + "urls": [ + "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_zipp_sdist_bc9eb26f": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "zipp-3.20.2.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "zipp==3.20.2", + "sha256": "bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29", + "urls": [ + "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz" + ] + } + }, + "rules_python_publish_deps": { + "bzlFile": "@@rules_python~//python/private/pypi:hub_repository.bzl", + "ruleClassName": "hub_repository", + "attributes": { + "repo_name": "rules_python_publish_deps", + "extra_hub_aliases": {}, + "whl_map": { + "backports_tarfile": "[{\"filename\":\"backports.tarfile-1.2.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7\",\"version\":\"3.11\"},{\"filename\":\"backports_tarfile-1.2.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2\",\"version\":\"3.11\"}]", + "certifi": "[{\"filename\":\"certifi-2024.8.30-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_certifi_py3_none_any_922820b5\",\"version\":\"3.11\"},{\"filename\":\"certifi-2024.8.30.tar.gz\",\"repo\":\"rules_python_publish_deps_311_certifi_sdist_bec941d2\",\"version\":\"3.11\"}]", + "cffi": "[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_ppc64le_46bf4316\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1.tar.gz\",\"repo\":\"rules_python_publish_deps_311_cffi_sdist_1c39c601\",\"version\":\"3.11\"}]", + "charset_normalizer": "[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_ppc64le_ce031db0\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_ppc64le_f1a2f519\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_sdist_223217c3\",\"version\":\"3.11\"}]", + "cryptography": "[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_cryptography_sdist_315b9001\",\"version\":\"3.11\"}]", + "docutils": "[{\"filename\":\"docutils-0.21.2-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9\",\"version\":\"3.11\"},{\"filename\":\"docutils-0.21.2.tar.gz\",\"repo\":\"rules_python_publish_deps_311_docutils_sdist_3a6b1873\",\"version\":\"3.11\"}]", + "idna": "[{\"filename\":\"idna-3.10-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_idna_py3_none_any_946d195a\",\"version\":\"3.11\"},{\"filename\":\"idna-3.10.tar.gz\",\"repo\":\"rules_python_publish_deps_311_idna_sdist_12f65c9b\",\"version\":\"3.11\"}]", + "importlib_metadata": "[{\"filename\":\"importlib_metadata-8.5.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197\",\"version\":\"3.11\"},{\"filename\":\"importlib_metadata-8.5.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_importlib_metadata_sdist_71522656\",\"version\":\"3.11\"}]", + "jaraco_classes": "[{\"filename\":\"jaraco.classes-3.4.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b\",\"version\":\"3.11\"},{\"filename\":\"jaraco.classes-3.4.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5\",\"version\":\"3.11\"}]", + "jaraco_context": "[{\"filename\":\"jaraco.context-6.0.1-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48\",\"version\":\"3.11\"},{\"filename\":\"jaraco_context-6.0.1.tar.gz\",\"repo\":\"rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5\",\"version\":\"3.11\"}]", + "jaraco_functools": "[{\"filename\":\"jaraco.functools-4.1.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13\",\"version\":\"3.11\"},{\"filename\":\"jaraco_functools-4.1.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2\",\"version\":\"3.11\"}]", + "jeepney": "[{\"filename\":\"jeepney-0.8.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad\",\"version\":\"3.11\"},{\"filename\":\"jeepney-0.8.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_jeepney_sdist_5efe48d2\",\"version\":\"3.11\"}]", + "keyring": "[{\"filename\":\"keyring-25.4.1-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_keyring_py3_none_any_5426f817\",\"version\":\"3.11\"},{\"filename\":\"keyring-25.4.1.tar.gz\",\"repo\":\"rules_python_publish_deps_311_keyring_sdist_b07ebc55\",\"version\":\"3.11\"}]", + "markdown_it_py": "[{\"filename\":\"markdown-it-py-3.0.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94\",\"version\":\"3.11\"},{\"filename\":\"markdown_it_py-3.0.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684\",\"version\":\"3.11\"}]", + "mdurl": "[{\"filename\":\"mdurl-0.1.2-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_mdurl_py3_none_any_84008a41\",\"version\":\"3.11\"},{\"filename\":\"mdurl-0.1.2.tar.gz\",\"repo\":\"rules_python_publish_deps_311_mdurl_sdist_bb413d29\",\"version\":\"3.11\"}]", + "more_itertools": "[{\"filename\":\"more-itertools-10.5.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_more_itertools_sdist_5482bfef\",\"version\":\"3.11\"},{\"filename\":\"more_itertools-10.5.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32\",\"version\":\"3.11\"}]", + "nh3": "[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64le_34c03fa7\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-win_amd64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18.tar.gz\",\"repo\":\"rules_python_publish_deps_311_nh3_sdist_94a16692\",\"version\":\"3.11\"}]", + "pkginfo": "[{\"filename\":\"pkginfo-1.10.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2\",\"version\":\"3.11\"},{\"filename\":\"pkginfo-1.10.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_pkginfo_sdist_5df73835\",\"version\":\"3.11\"}]", + "pycparser": "[{\"filename\":\"pycparser-2.22-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d\",\"version\":\"3.11\"},{\"filename\":\"pycparser-2.22.tar.gz\",\"repo\":\"rules_python_publish_deps_311_pycparser_sdist_491c8be9\",\"version\":\"3.11\"}]", + "pygments": "[{\"filename\":\"pygments-2.18.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0\",\"version\":\"3.11\"},{\"filename\":\"pygments-2.18.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_pygments_sdist_786ff802\",\"version\":\"3.11\"}]", + "pywin32_ctypes": "[{\"filename\":\"pywin32-ctypes-0.2.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04\",\"version\":\"3.11\"},{\"filename\":\"pywin32_ctypes-0.2.3-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337\",\"version\":\"3.11\"}]", + "readme_renderer": "[{\"filename\":\"readme_renderer-44.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b\",\"version\":\"3.11\"},{\"filename\":\"readme_renderer-44.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_readme_renderer_sdist_8712034e\",\"version\":\"3.11\"}]", + "requests": "[{\"filename\":\"requests-2.32.3-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_requests_py3_none_any_70761cfe\",\"version\":\"3.11\"},{\"filename\":\"requests-2.32.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_requests_sdist_55365417\",\"version\":\"3.11\"}]", + "requests_toolbelt": "[{\"filename\":\"requests-toolbelt-1.0.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3\",\"version\":\"3.11\"},{\"filename\":\"requests_toolbelt-1.0.0-py2.py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66\",\"version\":\"3.11\"}]", + "rfc3986": "[{\"filename\":\"rfc3986-2.0.0-py2.py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b\",\"version\":\"3.11\"},{\"filename\":\"rfc3986-2.0.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_rfc3986_sdist_97aacf9d\",\"version\":\"3.11\"}]", + "rich": "[{\"filename\":\"rich-13.9.3-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_rich_py3_none_any_9836f509\",\"version\":\"3.11\"},{\"filename\":\"rich-13.9.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_rich_sdist_bc1e01b8\",\"version\":\"3.11\"}]", + "secretstorage": "[{\"filename\":\"SecretStorage-3.3.3-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662\",\"version\":\"3.11\"},{\"filename\":\"SecretStorage-3.3.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_secretstorage_sdist_2403533e\",\"version\":\"3.11\"}]", + "twine": "[{\"filename\":\"twine-5.1.1-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_twine_py3_none_any_215dbe7b\",\"version\":\"3.11\"},{\"filename\":\"twine-5.1.1.tar.gz\",\"repo\":\"rules_python_publish_deps_311_twine_sdist_9aa08251\",\"version\":\"3.11\"}]", + "urllib3": "[{\"filename\":\"urllib3-2.2.3-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0\",\"version\":\"3.11\"},{\"filename\":\"urllib3-2.2.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_urllib3_sdist_e7d814a8\",\"version\":\"3.11\"}]", + "zipp": "[{\"filename\":\"zipp-3.20.2-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_zipp_py3_none_any_a817ac80\",\"version\":\"3.11\"},{\"filename\":\"zipp-3.20.2.tar.gz\",\"repo\":\"rules_python_publish_deps_311_zipp_sdist_bc9eb26f\",\"version\":\"3.11\"}]" + }, + "packages": [ + "backports_tarfile", + "certifi", + "charset_normalizer", + "docutils", + "idna", + "importlib_metadata", + "jaraco_classes", + "jaraco_context", + "jaraco_functools", + "keyring", + "markdown_it_py", + "mdurl", + "more_itertools", + "nh3", + "pkginfo", + "pygments", + "readme_renderer", + "requests", + "requests_toolbelt", + "rfc3986", + "rich", + "twine", + "urllib3", + "zipp" + ], + "groups": {} + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c", + "urls": [ + "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl" + ] + } + }, + "rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "jaraco.classes-3.4.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-classes==3.4.0", + "sha256": "f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", + "urls": [ + "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "jaraco_context-6.0.1.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-context==6.0.1", + "sha256": "9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3", + "urls": [ + "https://files.pythonhosted.org/packages/df/ad/f3777b81bf0b6e7bc7514a1656d3e637b2e8e15fab2ce3235730b3e7a4e6/jaraco_context-6.0.1.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_requests_py3_none_any_70761cfe": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "requests-2.32.3-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "requests==2.32.3", + "sha256": "70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", + "urls": [ + "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_readme_renderer_sdist_8712034e": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "readme_renderer-44.0.tar.gz", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "readme-renderer==44.0", + "sha256": "8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1", + "urls": [ + "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", + "urls": [ + "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea", + "urls": [ + "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl" + ] + } + }, + "rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13": { + "bzlFile": "@@rules_python~//python/private/pypi:whl_library.bzl", + "ruleClassName": "whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "jaraco.functools-4.1.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-functools==4.1.0", + "sha256": "ad159f13428bc4acbf5541ad6dec511f91573b90fba04df61dafa2a1231cf649", + "urls": [ + "https://files.pythonhosted.org/packages/9f/4f/24b319316142c44283d7540e76c7b5a6dbd5db623abd86bb7b3491c21018/jaraco.functools-4.1.0-py3-none-any.whl" + ] + } + } + }, + "recordedRepoMappingEntries": [ + [ + "bazel_features~", + "bazel_features_globals", + "bazel_features~~version_extension~bazel_features_globals" + ], + [ + "bazel_features~", + "bazel_features_version", + "bazel_features~~version_extension~bazel_features_version" + ], + [ + "rules_python~", + "bazel_features", + "bazel_features~" + ], + [ + "rules_python~", + "bazel_skylib", + "bazel_skylib~" + ], + [ + "rules_python~", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_python~", + "pypi__build", + "rules_python~~internal_deps~pypi__build" + ], + [ + "rules_python~", + "pypi__click", + "rules_python~~internal_deps~pypi__click" + ], + [ + "rules_python~", + "pypi__colorama", + "rules_python~~internal_deps~pypi__colorama" + ], + [ + "rules_python~", + "pypi__importlib_metadata", + "rules_python~~internal_deps~pypi__importlib_metadata" + ], + [ + "rules_python~", + "pypi__installer", + "rules_python~~internal_deps~pypi__installer" + ], + [ + "rules_python~", + "pypi__more_itertools", + "rules_python~~internal_deps~pypi__more_itertools" + ], + [ + "rules_python~", + "pypi__packaging", + "rules_python~~internal_deps~pypi__packaging" + ], + [ + "rules_python~", + "pypi__pep517", + "rules_python~~internal_deps~pypi__pep517" + ], + [ + "rules_python~", + "pypi__pip", + "rules_python~~internal_deps~pypi__pip" + ], + [ + "rules_python~", + "pypi__pip_tools", + "rules_python~~internal_deps~pypi__pip_tools" + ], + [ + "rules_python~", + "pypi__pyproject_hooks", + "rules_python~~internal_deps~pypi__pyproject_hooks" + ], + [ + "rules_python~", + "pypi__setuptools", + "rules_python~~internal_deps~pypi__setuptools" + ], + [ + "rules_python~", + "pypi__tomli", + "rules_python~~internal_deps~pypi__tomli" + ], + [ + "rules_python~", + "pypi__wheel", + "rules_python~~internal_deps~pypi__wheel" + ], + [ + "rules_python~", + "pypi__zipp", + "rules_python~~internal_deps~pypi__zipp" + ], + [ + "rules_python~", + "pythons_hub", + "rules_python~~python~pythons_hub" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_10_host", + "rules_python~~python~python_3_10_host" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_11_host", + "rules_python~~python~python_3_11_host" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_12_host", + "rules_python~~python~python_3_12_host" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_8_host", + "rules_python~~python~python_3_8_host" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_9_host", + "rules_python~~python~python_3_9_host" + ] + ] + } + } + } +} diff --git a/README.md b/README.md index a0d4db3ad..170ad1dc6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Constellation](docs/static/img/banner.svg) +![Constellation](docs/static/img/BannerConstellationanimated.svg) # Always Encrypted Kubernetes @@ -51,7 +51,7 @@ Encrypting your K8s is good for: * High availability with multi-master architecture and stacked etcd topology * Dynamic cluster autoscaling with verification and secure bootstrapping of new nodes -* Competitive performance ([see K-Bench comparison with AKS and GKE][performance]) +* Competitive [performance] ### 🧩 Easy to use and integrate @@ -74,15 +74,6 @@ If you're already familiar with Kubernetes, it's easy to get started with Conste Learn more: ["Getting started with Constellation" videos series](https://www.youtube.com/playlist?list=PLEhAl3D5WVvRYxO_yI7KzmtJ7rJUyQgNu). -## Live demos - -We're running public instances of popular software on Constellation: - -* Rocket.Chat: ([blog post](https://www.edgeless.systems/resource-library/rocket-chat)) -* GitLab: ([blog post](https://www.edgeless.systems/resource-library/confidential-gitlab/)) - -These instances run on CVMs in Azure and Constellation keeps them end-to-end confidential. - ## Documentation To learn more, see the [documentation](https://docs.edgeless.systems/constellation). diff --git a/WORKSPACE.bazel b/WORKSPACE.bzlmod similarity index 73% rename from WORKSPACE.bazel rename to WORKSPACE.bzlmod index 45eff59e0..5bf5f4fd9 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bzlmod @@ -1,13 +1,5 @@ workspace(name = "constellation") -load("//bazel/toolchains:skylib_deps.bzl", "skylib_deps") - -skylib_deps() - -load("//bazel/toolchains:cc_deps.bzl", "rules_cc_deps") - -rules_cc_deps() - # nixpkgs deps load("//bazel/toolchains:nixpkgs_deps.bzl", "nixpkgs_deps") @@ -140,15 +132,6 @@ register_mkosi( name = "mkosi_nix_toolchain", ) -# Python toolchain -load("//bazel/toolchains:python_deps.bzl", "python_deps") - -python_deps() - -load("@rules_python//python:repositories.bzl", "py_repositories") - -py_repositories() - nixpkgs_python_configure( fail_not_supported = False, python3_attribute_path = "python311", @@ -156,55 +139,11 @@ nixpkgs_python_configure( ) # Go toolchain -load("//bazel/toolchains:go_rules_deps.bzl", "go_deps") -go_deps() - -load("//bazel/toolchains:go_module_deps.bzl", "go_dependencies") - -# gazelle:repository_macro bazel/toolchains/go_module_deps.bzl%go_dependencies -go_dependencies() - -load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk", "go_register_toolchains", "go_rules_dependencies") - -go_download_sdk( - name = "go_sdk", - patches = ["//3rdparty/bazel/org_golang:go_tls_max_handshake_size.patch"], - version = "1.22.3", -) - -go_rules_dependencies() - -go_register_toolchains() - -load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") - -gazelle_dependencies(go_repository_default_config = "//:WORKSPACE.bazel") - -# gazelle:repo bazel_gazelle - -# proto toolchain -load("//bazel/toolchains:proto_deps.bzl", "proto_deps") - -proto_deps() - -load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") - -rules_proto_dependencies() - -rules_proto_toolchains() - -# Buildifier -load("//bazel/toolchains:buildifier_deps.bzl", "buildifier_deps") - -buildifier_deps() +# gazelle:repo gazelle # C / C++ toolchains -load("//bazel/toolchains:hermetic_cc_deps.bzl", "hermetic_cc_deps") - -hermetic_cc_deps() - load("@hermetic_cc_toolchain//toolchain:defs.bzl", zig_toolchains = "toolchains") # If needed, we can specify a specific version of the Zig toolchain to use. @@ -226,6 +165,7 @@ zig_toolchains() nixpkgs_cc_configure( name = "nixpkgs_cc_toolchain", + cc_std = "c++14", # TODO(malt3): Use clang once cc-wrapper path reset bug is fixed upstream. # attribute_path = "clang_11", repository = "@nixpkgs", @@ -233,6 +173,7 @@ nixpkgs_cc_configure( nixpkgs_cc_configure( name = "nixpkgs_cc_aarch64_darwin_x86_64_linux", + cc_std = "c++14", cross_cpu = "k8", exec_constraints = [ "@platforms//os:osx", @@ -267,28 +208,6 @@ register_toolchains( "@zig_sdk//toolchain:windows_amd64", ) -# Packaging rules (tar) -load("//bazel/toolchains:pkg_deps.bzl", "pkg_deps") - -pkg_deps() - -load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies") - -rules_pkg_dependencies() - -# Aspect Bazel Lib -load("//bazel/toolchains:aspect_bazel_lib.bzl", "aspect_bazel_lib") - -aspect_bazel_lib() - -load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "aspect_bazel_lib_register_toolchains", "register_coreutils_toolchains", "register_yq_toolchains") - -aspect_bazel_lib_dependencies() - -aspect_bazel_lib_register_toolchains() - -register_coreutils_toolchains() - # OCI rules load("//bazel/toolchains:oci_deps.bzl", "oci_deps") @@ -298,19 +217,14 @@ load("@rules_oci//oci:dependencies.bzl", "rules_oci_dependencies") rules_oci_dependencies() -load("@rules_oci//oci:repositories.bzl", "LATEST_CRANE_VERSION", "oci_register_toolchains") +load("@rules_oci//oci:repositories.bzl", "oci_register_toolchains") -oci_register_toolchains( - name = "oci", - crane_version = LATEST_CRANE_VERSION, -) +oci_register_toolchains(name = "oci") load("//bazel/toolchains:container_images.bzl", "containter_image_deps") containter_image_deps() -register_yq_toolchains() - # Multirun load("//bazel/toolchains:multirun_deps.bzl", "multirun_deps") diff --git a/bazel/bazelrc/ci.bazelrc b/bazel/bazelrc/ci.bazelrc index 4bc188e3d..dbae2df5e 100644 --- a/bazel/bazelrc/ci.bazelrc +++ b/bazel/bazelrc/ci.bazelrc @@ -62,6 +62,10 @@ build --remote_local_fallback # Docs: https://bazel.build/reference/command-line-reference#flag--grpc_keepalive_time build --grpc_keepalive_time=30s +# Use fallbacks in case proxy.golang.org is not reachable. +# Docs: https://go.dev/ref/mod#goproxy-protocol +common '--repo_env=GOPROXY=https://proxy.golang.org|https://goproxy.io|direct' + ###################################### # Edgeless specific # diff --git a/bazel/ci/BUILD.bazel b/bazel/ci/BUILD.bazel index 44e1c89c2..838beacab 100644 --- a/bazel/ci/BUILD.bazel +++ b/bazel/ci/BUILD.bazel @@ -1,6 +1,7 @@ -load("@bazel_gazelle//:def.bzl", "gazelle") -load("@com_github_ash2k_bazel_tools//multirun:def.bzl", "command", "multirun") -load("@com_github_bazelbuild_buildtools//buildifier:def.bzl", "buildifier", "buildifier_test") +load("@buildifier_prebuilt//:rules.bzl", "buildifier", "buildifier_test") +load("@com_github_ash2k_bazel_tools//multirun:def.bzl", "multirun") +load("@gazelle//:def.bzl", "gazelle") +load("@io_bazel_rules_go//go/private/rules:go_bin_for_host.bzl", "go_bin_for_host") load("//bazel/ci:proto_targets.bzl", "proto_targets") load("//bazel/sh:def.bzl", "noop_warn", "repo_command", "sh_template") @@ -9,18 +10,6 @@ required_tags = [ "integration", ] -# TODO(malt3): Remove this once we have a better solution for -# gazelle not respecting the default go env. -command( - name = "cmd_gazelle_update_repos", - command = ":gazelle_update_repos", - environment = { - "GOPROXY": "https://proxy.golang.org,direct", - "GOSUMDB": "sum.golang.org", - "GOTOOLCHAIN": "local", - }, -) - gazelle( name = "gazelle_generate", build_tags = required_tags, @@ -33,18 +22,6 @@ gazelle( mode = "diff", ) -gazelle( - name = "gazelle_update_repos", - args = [ - "-from_file=go.work", - "-to_macro=bazel/toolchains/go_module_deps.bzl%go_dependencies", - "-build_file_proto_mode=disable_global", - "-build_file_generation=on", - "-prune", - ], - command = "update-repos", -) - buildifier_test( name = "buildifier_check", timeout = "short", @@ -54,7 +31,7 @@ buildifier_test( no_sandbox = True, tags = ["no-remote-exec"], verbose = True, - workspace = "//:WORKSPACE.bazel", + workspace = "//:WORKSPACE.bzlmod", ) buildifier( @@ -80,10 +57,10 @@ sh_template( sh_template( name = "go_mod_tidy", data = [ - "@go_sdk//:bin/go", + ":go_bin_for_host", ], substitutions = { - "@@GO@@": "$(rootpath @go_sdk//:bin/go)", + "@@GO@@": "$(rootpath :go_bin_for_host)", }, template = "go_tidy.sh.in", ) @@ -257,10 +234,10 @@ sh_template( name = "golangci_lint", data = [ ":com_github_golangci_golangci_lint", - "@go_sdk//:bin/go", + ":go_bin_for_host", ], substitutions = { - "@@GO@@": "$(rootpath @go_sdk//:bin/go)", + "@@GO@@": "$(rootpath :go_bin_for_host)", "@@GOLANGCI-LINT@@": "$(rootpath :com_github_golangci_golangci_lint)", }, template = "golangci_lint.sh.in", @@ -290,11 +267,11 @@ sh_template( sh_template( name = "golicenses_check", data = [ + ":go_bin_for_host", "@com_github_google_go_licenses//:go-licenses", - "@go_sdk//:bin/go", ], substitutions = { - "@@GO@@": "$(rootpath @go_sdk//:bin/go)", + "@@GO@@": "$(rootpath :go_bin_for_host)", "@@GO_LICENSES@@": "$(rootpath @com_github_google_go_licenses//:go-licenses)", }, template = "golicenses.sh.in", @@ -310,12 +287,14 @@ sh_template( sh_template( name = "govulncheck", data = [ - "@go_sdk//:bin/go", + ":go_bin_for_host", + "@jq_toolchains//:resolved_toolchain", "@org_golang_x_vuln//cmd/govulncheck", ], substitutions = { - "@@GO@@": "$(rootpath @go_sdk//:bin/go)", + "@@GO@@": "$(rootpath :go_bin_for_host)", "@@GOVULNCHECK@@": "$(rootpath @org_golang_x_vuln//cmd/govulncheck:govulncheck)", + "@@JQ@@": "$(rootpath @jq_toolchains//:resolved_toolchain)", }, template = "govulncheck.sh.in", ) @@ -345,15 +324,15 @@ sh_template( data = [ ":com_github_helm_helm", ":com_github_siderolabs_talos_hack_docgen", + ":go_bin_for_host", "//internal/attestation/measurements/measurement-generator", "//internal/versions/hash-generator", - "@go_sdk//:bin/go", "@org_golang_x_tools//cmd/stringer", "@yq_toolchains//:resolved_toolchain", ], substitutions = { "@@DOCGEN@@": "$(rootpath :com_github_siderolabs_talos_hack_docgen)", - "@@GO@@": "$(rootpath @go_sdk//:bin/go)", + "@@GO@@": "$(rootpath :go_bin_for_host)", "@@HASH_GENERATOR@@": "$(rootpath //internal/versions/hash-generator:hash-generator)", "@@HELM@@": "$(rootpath :com_github_helm_helm)", "@@MEASUREMENT_GENERATOR@@": "$(rootpath //internal/attestation/measurements/measurement-generator:measurement-generator)", @@ -499,14 +478,19 @@ sh_template( template = "unused_gh_actions.sh.in", ) +go_bin_for_host( + name = "go_bin_for_host", + visibility = ["//visibility:private"], +) + sh_template( name = "gocoverage_diff", data = [ + ":go_bin_for_host", "//hack/gocoverage", - "@go_sdk//:bin/go", ], substitutions = { - "@@GO@@": "$(rootpath @go_sdk//:bin/go)", + "@@GO@@": "$(rootpath :go_bin_for_host)", "@@GOCOVERAGE@@": "$(rootpath //hack/gocoverage:gocoverage)", }, template = "gocoverage_diff.sh.in", @@ -518,7 +502,6 @@ multirun( ":shfmt", ":gofumpt", ":go_mod_tidy", - ":cmd_gazelle_update_repos", ":gazelle_generate", ":buildifier_fix", ":terraform_fmt", @@ -560,16 +543,34 @@ multirun( ) multirun( - name = "generate", + name = "generate_files", commands = [ ":terraform_gen", "//3rdparty/bazel/com_github_medik8s_node_maintainance_operator:pull_files", ":go_generate", ":proto_generate", - ":cli_docgen", - ":terraform_docgen", - ":version_info_gen", ], jobs = 0, # execute concurrently visibility = ["//visibility:public"], ) + +multirun( + name = "generate_docs", + commands = [ + ":cli_docgen", + ":terraform_docgen", + ], + jobs = 0, # execute concurrently + visibility = ["//visibility:public"], +) + +multirun( + name = "generate", + commands = [ + ":generate_files", + ":generate_docs", + ":version_info_gen", + ], + jobs = 1, # execute sequentially + visibility = ["//visibility:public"], +) diff --git a/bazel/ci/govulncheck.sh.in b/bazel/ci/govulncheck.sh.in index 0ea07b10c..d3cda88be 100644 --- a/bazel/ci/govulncheck.sh.in +++ b/bazel/ci/govulncheck.sh.in @@ -15,6 +15,8 @@ go=$(realpath @@GO@@) stat "${go}" >> /dev/null govulncheck=$(realpath @@GOVULNCHECK@@) stat "${govulncheck}" >> /dev/null +jq=$(realpath @@JQ@@) +stat "${jq}" >> /dev/null cd "${BUILD_WORKSPACE_DIRECTORY}" @@ -24,19 +26,26 @@ submodules=$(${go} list -f '{{.Dir}}' -m) PATH=$(dirname "${go}"):${PATH} +check_module() { + # shellcheck disable=SC2016 # The $ sign in the single quoted string is correct. + CGO_ENABLED=0 ${govulncheck} -C "$1" -format json "./..." | + "${jq}" -sr ' + (map(select(.osv) | {"key": .osv.id, "value": .osv.summary}) | from_entries) as $osvs | + map(select( .finding and .finding.osv != "GO-2024-3166" ) | .finding | select( .trace[-1].module | startswith("github.com/edgelesssys/") )) | + group_by(.osv) | + map( {"osv": .[0].osv, "summary": $osvs[.[0].osv], "traces": [.[] | [.trace[] | .module]]} ) | + if length > 0 then halt_error(1) else .[] end' + +} + check() { err=0 - echo "Scanning Go vulnerability DB for knwon vulnerabilities in modules:" + echo "Scanning Go vulnerability DB for known vulnerabilities in modules:" for mod in ${submodules}; do echo " ${mod}" echo -n " " - CGO_ENABLED=0 ${govulncheck} -C "${mod}" "./..." | - tail -n 2 | # Providing some nice output... - tr '\n' ' ' | - sed s/" your code and"// && - printf "\n" || - err=$? + check_module "${mod}" done exit "${err}" diff --git a/bazel/mkosi/mkosi_image.bzl b/bazel/mkosi/mkosi_image.bzl index dbb3c9a8b..fb11a81c2 100644 --- a/bazel/mkosi/mkosi_image.bzl +++ b/bazel/mkosi/mkosi_image.bzl @@ -2,6 +2,9 @@ load("@bazel_skylib//lib:paths.bzl", "paths") +def _resource_set(_os, _num_inputs): + return {"cpu": 4, "memory": 4096} + def _mkosi_image_impl(ctx): args = ctx.actions.args() inputs = [] @@ -67,8 +70,6 @@ def _mkosi_image_impl(ctx): args.add("--kernel-command-line", ctx.attr.kernel_command_line) for key, value in ctx.attr.kernel_command_line_dict.items(): args.add("--kernel-command-line", "{}={}".format(key, value)) - if ctx.attr.autologin: - args.add("--autologin", "yes") info = ctx.toolchains["@constellation//bazel/mkosi:toolchain_type"].mkosi if not info.valid: @@ -99,6 +100,7 @@ def _mkosi_image_impl(ctx): execution_requirements = {"no-remote": "1", "no-sandbox": "1"}, progress_message = "Building mkosi image " + ctx.label.name, env = env, + resource_set = _resource_set, ) return DefaultInfo(files = depset(outputs), runfiles = ctx.runfiles(outputs)) @@ -106,7 +108,6 @@ mkosi_image = rule( implementation = _mkosi_image_impl, attrs = { "architecture": attr.string(), - "autologin": attr.bool(), "base_trees": attr.label_list(allow_files = True), "distribution": attr.string(), "env": attr.string_dict(), diff --git a/bazel/toolchains/0001-disable-Windows-support.patch b/bazel/toolchains/0001-disable-Windows-support.patch new file mode 100644 index 000000000..1cb9c8340 --- /dev/null +++ b/bazel/toolchains/0001-disable-Windows-support.patch @@ -0,0 +1,75 @@ +From d10473f4ac89c23dcd8ea02488b28a649f4a9735 Mon Sep 17 00:00:00 2001 +From: Markus Rudy +Date: Tue, 6 Aug 2024 11:33:29 +0200 +Subject: [PATCH] disable Windows support + +It's broken and we don't need it, see +https://github.com/bazel-contrib/rules_oci/issues/420. +--- + oci/private/image.bzl | 9 --------- + oci/private/util.bzl | 29 +---------------------------- + 2 files changed, 1 insertion(+), 37 deletions(-) + +diff --git a/oci/private/image.bzl b/oci/private/image.bzl +index e8a6ca5..434947c 100644 +--- a/oci/private/image.bzl ++++ b/oci/private/image.bzl +@@ -226,15 +226,6 @@ def _oci_image_impl(ctx): + + action_env = {} + +- # Windows: Don't convert arguments like --entrypoint=/some/bin to --entrypoint=C:/msys64/some/bin +- if ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]): +- # See https://www.msys2.org/wiki/Porting/: +- # > Setting MSYS2_ARG_CONV_EXCL=* prevents any path transformation. +- action_env["MSYS2_ARG_CONV_EXCL"] = "*" +- +- # This one is for Windows Git MSys +- action_env["MSYS_NO_PATHCONV"] = "1" +- + ctx.actions.run( + inputs = depset(inputs, transitive = transitive_inputs), + arguments = [args], +diff --git a/oci/private/util.bzl b/oci/private/util.bzl +index 7c2a2c2..479ca7d 100644 +--- a/oci/private/util.bzl ++++ b/oci/private/util.bzl +@@ -141,34 +141,7 @@ def _maybe_wrap_launcher_for_windows(ctx, bash_launcher): + - make sure the bash_launcher is in the inputs to the action + - @bazel_tools//tools/sh:toolchain_type should appear in the rules toolchains + """ +- if not ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]): +- return bash_launcher +- +- win_launcher = ctx.actions.declare_file("wrap_%s.bat" % ctx.label.name) +- ctx.actions.write( +- output = win_launcher, +- content = r"""@echo off +-SETLOCAL ENABLEEXTENSIONS +-SETLOCAL ENABLEDELAYEDEXPANSION +-for %%a in ("{bash_bin}") do set "bash_bin_dir=%%~dpa" +-set PATH=%bash_bin_dir%;%PATH% +-set "parent_dir=%~dp0" +-set "parent_dir=!parent_dir:\=/!" +-set args=%* +-rem Escape \ and * in args before passing it with double quote +-if defined args ( +- set args=!args:\=\\\\! +- set args=!args:"=\"! +-) +-"{bash_bin}" -c "%parent_dir%{launcher} !args!" +-""".format( +- bash_bin = ctx.toolchains["@bazel_tools//tools/sh:toolchain_type"].path, +- launcher = paths.relativize(bash_launcher.path, win_launcher.dirname), +- ), +- is_executable = True, +- ) +- +- return win_launcher ++ return bash_launcher + + def _file_exists(rctx, path): + result = rctx.execute(["stat", path]) +-- +2.46.0 + diff --git a/bazel/toolchains/BUILD.bazel b/bazel/toolchains/BUILD.bazel index 5849b1b8b..55a19db8a 100644 --- a/bazel/toolchains/BUILD.bazel +++ b/bazel/toolchains/BUILD.bazel @@ -1 +1 @@ -"""This folder contains toolchain dependencies for the project. They are loaded by `WORKSPACE.bazel`.""" +"""This folder contains toolchain dependencies for the project. They are loaded by `WORKSPACE.bzlmod`.""" diff --git a/bazel/toolchains/aspect_bazel_lib.bzl b/bazel/toolchains/aspect_bazel_lib.bzl deleted file mode 100644 index 74b538ade..000000000 --- a/bazel/toolchains/aspect_bazel_lib.bzl +++ /dev/null @@ -1,15 +0,0 @@ -"""aspect bazel library""" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def aspect_bazel_lib(): - http_archive( - name = "aspect_bazel_lib", - sha256 = "87ab4ec479ebeb00d286266aca2068caeef1bb0b1765e8f71c7b6cfee6af4226", - strip_prefix = "bazel-lib-2.7.3", - urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/87ab4ec479ebeb00d286266aca2068caeef1bb0b1765e8f71c7b6cfee6af4226", - "https://github.com/aspect-build/bazel-lib/releases/download/v2.7.3/bazel-lib-v2.7.3.tar.gz", - ], - type = "tar.gz", - ) diff --git a/bazel/toolchains/buildifier_deps.bzl b/bazel/toolchains/buildifier_deps.bzl deleted file mode 100644 index 97ffccd6a..000000000 --- a/bazel/toolchains/buildifier_deps.bzl +++ /dev/null @@ -1,15 +0,0 @@ -"""buildifier repository rules""" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def buildifier_deps(): - http_archive( - name = "com_github_bazelbuild_buildtools", - strip_prefix = "buildtools-7.1.1", - urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/60a9025072ae237f325d0e7b661e1685f34922c29883888c2d06f5789462b939", - "https://github.com/bazelbuild/buildtools/archive/refs/tags/v7.1.1.tar.gz", - ], - type = "tar.gz", - sha256 = "60a9025072ae237f325d0e7b661e1685f34922c29883888c2d06f5789462b939", - ) diff --git a/bazel/toolchains/cc_deps.bzl b/bazel/toolchains/cc_deps.bzl deleted file mode 100644 index cdda9821c..000000000 --- a/bazel/toolchains/cc_deps.bzl +++ /dev/null @@ -1,15 +0,0 @@ -"""bazel rules_cc""" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def rules_cc_deps(): - http_archive( - name = "rules_cc", - urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/2037875b9a4456dce4a79d112a8ae885bbc4aad968e6587dca6e64f3a0900cdf", - "https://github.com/bazelbuild/rules_cc/releases/download/0.0.9/rules_cc-0.0.9.tar.gz", - ], - sha256 = "2037875b9a4456dce4a79d112a8ae885bbc4aad968e6587dca6e64f3a0900cdf", - strip_prefix = "rules_cc-0.0.9", - type = "tar.gz", - ) diff --git a/bazel/toolchains/ci_deps.bzl b/bazel/toolchains/ci_deps.bzl index e5aeefc9e..9267154eb 100644 --- a/bazel/toolchains/ci_deps.bzl +++ b/bazel/toolchains/ci_deps.bzl @@ -97,83 +97,83 @@ def _actionlint_deps(): name = "com_github_rhysd_actionlint_linux_amd64", build_file_content = """exports_files(["actionlint"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/8aae9148f61952d11a97651852fdc7dffd2b762ed3cdd28b3c2232ae5f55d4db", - "https://github.com/rhysd/actionlint/releases/download/v1.7.0/actionlint_1.7.0_linux_amd64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/fc0a6886bbb9a23a39eeec4b176193cadb54ddbe77cdbb19b637933919545395", + "https://github.com/rhysd/actionlint/releases/download/v1.7.4/actionlint_1.7.4_linux_amd64.tar.gz", ], type = "tar.gz", - sha256 = "8aae9148f61952d11a97651852fdc7dffd2b762ed3cdd28b3c2232ae5f55d4db", + sha256 = "fc0a6886bbb9a23a39eeec4b176193cadb54ddbe77cdbb19b637933919545395", ) http_archive( name = "com_github_rhysd_actionlint_linux_arm64", build_file_content = """exports_files(["actionlint"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/8181452246e7e6310b988f83762fc982e03f27eeb53dd4ad33fa4a5f4276b383", - "https://github.com/rhysd/actionlint/releases/download/v1.7.0/actionlint_1.7.0_linux_arm64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/ede03682dc955381d057dde95bb85ce9ca418122209a8a313b617d4adec56416", + "https://github.com/rhysd/actionlint/releases/download/v1.7.4/actionlint_1.7.4_linux_arm64.tar.gz", ], type = "tar.gz", - sha256 = "8181452246e7e6310b988f83762fc982e03f27eeb53dd4ad33fa4a5f4276b383", + sha256 = "ede03682dc955381d057dde95bb85ce9ca418122209a8a313b617d4adec56416", ) http_archive( name = "com_github_rhysd_actionlint_darwin_amd64", build_file_content = """exports_files(["actionlint"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/138aff674f31bd218030d4b00b3024bf0c721b75a7ec8e90b743763f81e3128e", - "https://github.com/rhysd/actionlint/releases/download/v1.7.0/actionlint_1.7.0_darwin_amd64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/63a3ba90ee2325afad3ff2e64a4d80688c261e6c68be8e6ab91214637bf936b8", + "https://github.com/rhysd/actionlint/releases/download/v1.7.4/actionlint_1.7.4_darwin_amd64.tar.gz", ], type = "tar.gz", - sha256 = "138aff674f31bd218030d4b00b3024bf0c721b75a7ec8e90b743763f81e3128e", + sha256 = "63a3ba90ee2325afad3ff2e64a4d80688c261e6c68be8e6ab91214637bf936b8", ) http_archive( name = "com_github_rhysd_actionlint_darwin_arm64", build_file_content = """exports_files(["actionlint"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/806e73fbafe54b7324d9478798534c5195fb71ea171633d9035b3fca237addd3", - "https://github.com/rhysd/actionlint/releases/download/v1.7.0/actionlint_1.7.0_darwin_arm64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/cbd193bb490f598d77e179261d7b76dfebd049dddede5803ba21cbf6a469aeee", + "https://github.com/rhysd/actionlint/releases/download/v1.7.4/actionlint_1.7.4_darwin_arm64.tar.gz", ], type = "tar.gz", - sha256 = "806e73fbafe54b7324d9478798534c5195fb71ea171633d9035b3fca237addd3", + sha256 = "cbd193bb490f598d77e179261d7b76dfebd049dddede5803ba21cbf6a469aeee", ) def _gofumpt_deps(): http_file( name = "com_github_mvdan_gofumpt_linux_amd64", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/bdb57c353e2bbc43d2b097bb7289a6e65ef2526787f89316b4b452a9e5086be4", - "https://github.com/mvdan/gofumpt/releases/download/v0.6.0/gofumpt_v0.6.0_linux_amd64", + "https://cdn.confidential.cloud/constellation/cas/sha256/6ff459c1dcae3b0b00844c1a5a4a5b0f547237d8a4f3624aaea8d424aeef24c6", + "https://github.com/mvdan/gofumpt/releases/download/v0.7.0/gofumpt_v0.7.0_linux_amd64", ], executable = True, downloaded_file_path = "gofumpt", - sha256 = "bdb57c353e2bbc43d2b097bb7289a6e65ef2526787f89316b4b452a9e5086be4", + sha256 = "6ff459c1dcae3b0b00844c1a5a4a5b0f547237d8a4f3624aaea8d424aeef24c6", ) http_file( name = "com_github_mvdan_gofumpt_linux_arm64", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/10ff2643b7b4b9425bda7f0ca2d4e54d85b09024fbfd9c21dbfd55017b907965", - "https://github.com/mvdan/gofumpt/releases/download/v0.6.0/gofumpt_v0.6.0_linux_arm64", + "https://cdn.confidential.cloud/constellation/cas/sha256/00c18c88ef50437629626ba20d677f4648684cb280952814cdd887677d42cbd3", + "https://github.com/mvdan/gofumpt/releases/download/v0.7.0/gofumpt_v0.7.0_linux_arm64", ], executable = True, downloaded_file_path = "gofumpt", - sha256 = "10ff2643b7b4b9425bda7f0ca2d4e54d85b09024fbfd9c21dbfd55017b907965", + sha256 = "00c18c88ef50437629626ba20d677f4648684cb280952814cdd887677d42cbd3", ) http_file( name = "com_github_mvdan_gofumpt_darwin_amd64", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/59e6047b3fa2fb65b60cf7f8be9b77cf6b31b428a9a24042ce29e85140868036", - "https://github.com/mvdan/gofumpt/releases/download/v0.6.0/gofumpt_v0.6.0_darwin_amd64", + "https://cdn.confidential.cloud/constellation/cas/sha256/b7d05e092da45c5ec96344ab635b1d6547c3e27c840ba39bc76989934efd7ce3", + "https://github.com/mvdan/gofumpt/releases/download/v0.7.0/gofumpt_v0.7.0_darwin_amd64", ], executable = True, downloaded_file_path = "gofumpt", - sha256 = "59e6047b3fa2fb65b60cf7f8be9b77cf6b31b428a9a24042ce29e85140868036", + sha256 = "b7d05e092da45c5ec96344ab635b1d6547c3e27c840ba39bc76989934efd7ce3", ) http_file( name = "com_github_mvdan_gofumpt_darwin_arm64", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/725f7a922bf3f88bed6818a4553e80554cc5cdb67a72236a01707325aa2dbb7b", - "https://github.com/mvdan/gofumpt/releases/download/v0.6.0/gofumpt_v0.6.0_darwin_arm64", + "https://cdn.confidential.cloud/constellation/cas/sha256/08f23114760a090b090706d92b8c52b9875b9eb352d76c77aa354d6aa20b045a", + "https://github.com/mvdan/gofumpt/releases/download/v0.7.0/gofumpt_v0.7.0_darwin_arm64", ], executable = True, downloaded_file_path = "gofumpt", - sha256 = "725f7a922bf3f88bed6818a4553e80554cc5cdb67a72236a01707325aa2dbb7b", + sha256 = "08f23114760a090b090706d92b8c52b9875b9eb352d76c77aa354d6aa20b045a", ) def _tfsec_deps(): @@ -181,41 +181,41 @@ def _tfsec_deps(): name = "com_github_aquasecurity_tfsec_linux_amd64", build_file_content = """exports_files(["tfsec"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/8cbd8d64cbd1f25b38f33fa04db602466dade79e99c99dc9da053b5962d34014", - "https://github.com/aquasecurity/tfsec/releases/download/v1.28.6/tfsec_1.28.6_linux_amd64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/9d783fa225a570f034000136973afba86a1708c919a539b72b3ea954a198289c", + "https://github.com/aquasecurity/tfsec/releases/download/v1.28.11/tfsec_1.28.11_linux_amd64.tar.gz", ], type = "tar.gz", - sha256 = "8cbd8d64cbd1f25b38f33fa04db602466dade79e99c99dc9da053b5962d34014", + sha256 = "9d783fa225a570f034000136973afba86a1708c919a539b72b3ea954a198289c", ) http_archive( name = "com_github_aquasecurity_tfsec_linux_arm64", build_file_content = """exports_files(["tfsec"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/4bc7b0f0592be4fa384cff52af5b1cdd2066ba7a06001bea98690340851c0bce", - "https://github.com/aquasecurity/tfsec/releases/download/v1.28.6/tfsec_1.28.6_linux_arm64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/68b5c4f6b7c459dd890ecff94b0732e456ef45974894f58bbb90fbb4816f3e52", + "https://github.com/aquasecurity/tfsec/releases/download/v1.28.11/tfsec_1.28.11_linux_arm64.tar.gz", ], type = "tar.gz", - sha256 = "4bc7b0f0592be4fa384cff52af5b1cdd2066ba7a06001bea98690340851c0bce", + sha256 = "68b5c4f6b7c459dd890ecff94b0732e456ef45974894f58bbb90fbb4816f3e52", ) http_archive( name = "com_github_aquasecurity_tfsec_darwin_amd64", build_file_content = """exports_files(["tfsec"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/3b31e954819faa7d6151b999548cefb782f2f4dc64b355c8747e44d4b0b2faca", - "https://github.com/aquasecurity/tfsec/releases/download/v1.28.6/tfsec_1.28.6_darwin_amd64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/d377597f2fd4e6956bb7beb711d627b0e0204c421c17e2cd062213222c2f3001", + "https://github.com/aquasecurity/tfsec/releases/download/v1.28.11/tfsec_1.28.11_darwin_amd64.tar.gz", ], type = "tar.gz", - sha256 = "3b31e954819faa7d6151b999548cefb782f2f4dc64b355c8747e44d4b0b2faca", + sha256 = "d377597f2fd4e6956bb7beb711d627b0e0204c421c17e2cd062213222c2f3001", ) http_archive( name = "com_github_aquasecurity_tfsec_darwin_arm64", build_file_content = """exports_files(["tfsec"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/aa132b7e0e69e16f1c9320257841751e52c42d9791b7f900de72cf0b06ffe74c", - "https://github.com/aquasecurity/tfsec/releases/download/v1.28.6/tfsec_1.28.6_darwin_arm64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/14db6b40049226ebc779789196f99eb4977bb93c99fa51c8b72b603e6cdf44e7", + "https://github.com/aquasecurity/tfsec/releases/download/v1.28.11/tfsec_1.28.11_darwin_arm64.tar.gz", ], type = "tar.gz", - sha256 = "aa132b7e0e69e16f1c9320257841751e52c42d9791b7f900de72cf0b06ffe74c", + sha256 = "14db6b40049226ebc779789196f99eb4977bb93c99fa51c8b72b603e6cdf44e7", ) def _golangci_lint_deps(): @@ -223,45 +223,45 @@ def _golangci_lint_deps(): name = "com_github_golangci_golangci_lint_linux_amd64", build_file = "//bazel/toolchains:BUILD.golangci.bazel", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/2e7c1b2af70ecb7ce18da79a3951db7046dcb709566c018fb93c61e8733b2239", - "https://github.com/golangci/golangci-lint/releases/download/v1.58.1/golangci-lint-1.58.1-linux-amd64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/77cb0af99379d9a21d5dc8c38364d060e864a01bd2f3e30b5e8cc550c3a54111", + "https://github.com/golangci/golangci-lint/releases/download/v1.61.0/golangci-lint-1.61.0-linux-amd64.tar.gz", ], - strip_prefix = "golangci-lint-1.58.1-linux-amd64", + strip_prefix = "golangci-lint-1.61.0-linux-amd64", type = "tar.gz", - sha256 = "2e7c1b2af70ecb7ce18da79a3951db7046dcb709566c018fb93c61e8733b2239", + sha256 = "77cb0af99379d9a21d5dc8c38364d060e864a01bd2f3e30b5e8cc550c3a54111", ) http_archive( name = "com_github_golangci_golangci_lint_linux_arm64", build_file = "//bazel/toolchains:BUILD.golangci.bazel", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/e78f55156ef7f8bd4a746aa695c6bd299dc0aa71b91ec066680d2c59e443708b", - "https://github.com/golangci/golangci-lint/releases/download/v1.58.1/golangci-lint-1.58.1-linux-arm64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/af60ac05566d9351615cb31b4cc070185c25bf8cbd9b09c1873aa5ec6f3cc17e", + "https://github.com/golangci/golangci-lint/releases/download/v1.61.0/golangci-lint-1.61.0-linux-arm64.tar.gz", ], - strip_prefix = "golangci-lint-1.58.1-linux-arm64", + strip_prefix = "golangci-lint-1.61.0-linux-arm64", type = "tar.gz", - sha256 = "e78f55156ef7f8bd4a746aa695c6bd299dc0aa71b91ec066680d2c59e443708b", + sha256 = "af60ac05566d9351615cb31b4cc070185c25bf8cbd9b09c1873aa5ec6f3cc17e", ) http_archive( name = "com_github_golangci_golangci_lint_darwin_amd64", build_file = "//bazel/toolchains:BUILD.golangci.bazel", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/79f587134955808e245aa78a734bc28f6e03fc42efb3e91d2a705930909fe0c0", - "https://github.com/golangci/golangci-lint/releases/download/v1.58.1/golangci-lint-1.58.1-darwin-amd64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/5c280ef3284f80c54fd90d73dc39ca276953949da1db03eb9dd0fbf868cc6e55", + "https://github.com/golangci/golangci-lint/releases/download/v1.61.0/golangci-lint-1.61.0-darwin-amd64.tar.gz", ], - strip_prefix = "golangci-lint-1.58.1-darwin-amd64", + strip_prefix = "golangci-lint-1.61.0-darwin-amd64", type = "tar.gz", - sha256 = "79f587134955808e245aa78a734bc28f6e03fc42efb3e91d2a705930909fe0c0", + sha256 = "5c280ef3284f80c54fd90d73dc39ca276953949da1db03eb9dd0fbf868cc6e55", ) http_archive( name = "com_github_golangci_golangci_lint_darwin_arm64", build_file = "//bazel/toolchains:BUILD.golangci.bazel", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/bd59615a2fdf8e8ff544ba79e15c53f81a538bd68cccf52f4802b65e0216199d", - "https://github.com/golangci/golangci-lint/releases/download/v1.58.1/golangci-lint-1.58.1-darwin-arm64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/544334890701e4e04a6e574bc010bea8945205c08c44cced73745a6378012d36", + "https://github.com/golangci/golangci-lint/releases/download/v1.61.0/golangci-lint-1.61.0-darwin-arm64.tar.gz", ], - strip_prefix = "golangci-lint-1.58.1-darwin-arm64", + strip_prefix = "golangci-lint-1.61.0-darwin-arm64", type = "tar.gz", - sha256 = "bd59615a2fdf8e8ff544ba79e15c53f81a538bd68cccf52f4802b65e0216199d", + sha256 = "544334890701e4e04a6e574bc010bea8945205c08c44cced73745a6378012d36", ) def _buf_deps(): @@ -270,44 +270,44 @@ def _buf_deps(): strip_prefix = "buf/bin", build_file_content = """exports_files(["buf"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/8a94dce37ce72c89c82e6c4baf77797a2a4a2eef3b02a7f39b40ef7fb0f39f94", - "https://github.com/bufbuild/buf/releases/download/v1.31.0/buf-Linux-x86_64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/deebd48a6bf85b073d7c7800c17b330376487e86852d4905c76a205b6fd795d4", + "https://github.com/bufbuild/buf/releases/download/v1.45.0/buf-Linux-x86_64.tar.gz", ], type = "tar.gz", - sha256 = "8a94dce37ce72c89c82e6c4baf77797a2a4a2eef3b02a7f39b40ef7fb0f39f94", + sha256 = "deebd48a6bf85b073d7c7800c17b330376487e86852d4905c76a205b6fd795d4", ) http_archive( name = "com_github_bufbuild_buf_linux_arm64", strip_prefix = "buf/bin", build_file_content = """exports_files(["buf"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/ed435fe40a8b719354f746261cf9dbfcbfa4165fdb600e2f324ad8f6fe488dd2", - "https://github.com/bufbuild/buf/releases/download/v1.31.0/buf-Linux-aarch64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/2d3ebfed036881d0615e5b24288cf788791b45848f26e915e3efe7ee9c10735d", + "https://github.com/bufbuild/buf/releases/download/v1.45.0/buf-Linux-aarch64.tar.gz", ], type = "tar.gz", - sha256 = "ed435fe40a8b719354f746261cf9dbfcbfa4165fdb600e2f324ad8f6fe488dd2", + sha256 = "2d3ebfed036881d0615e5b24288cf788791b45848f26e915e3efe7ee9c10735d", ) http_archive( name = "com_github_bufbuild_buf_darwin_amd64", strip_prefix = "buf/bin", build_file_content = """exports_files(["buf"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/a88b4ccf6aee4f7d525917bf4636253faa7c13b8f45c4c732a7fea55441ef835", - "https://github.com/bufbuild/buf/releases/download/v1.31.0/buf-Darwin-x86_64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/7fef3c482ac440cc09c40864498ef1f44745fde82428ddf52edd2012d3a036a4", + "https://github.com/bufbuild/buf/releases/download/v1.45.0/buf-Darwin-x86_64.tar.gz", ], type = "tar.gz", - sha256 = "a88b4ccf6aee4f7d525917bf4636253faa7c13b8f45c4c732a7fea55441ef835", + sha256 = "7fef3c482ac440cc09c40864498ef1f44745fde82428ddf52edd2012d3a036a4", ) http_archive( name = "com_github_bufbuild_buf_darwin_arm64", strip_prefix = "buf/bin", build_file_content = """exports_files(["buf"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/7519df87d3f681d5348f00e96215543edc55c62d821527056b5d8201d8982f28", - "https://github.com/bufbuild/buf/releases/download/v1.31.0/buf-Darwin-arm64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/e5309c70c7bb4a06d799ab7c7601c0d647c704085593d5cd981db29f986e469b", + "https://github.com/bufbuild/buf/releases/download/v1.45.0/buf-Darwin-arm64.tar.gz", ], type = "tar.gz", - sha256 = "7519df87d3f681d5348f00e96215543edc55c62d821527056b5d8201d8982f28", + sha256 = "e5309c70c7bb4a06d799ab7c7601c0d647c704085593d5cd981db29f986e469b", ) def _talos_docgen_deps(): diff --git a/bazel/toolchains/container_images.bzl b/bazel/toolchains/container_images.bzl index 325d5c2da..cd82c6fae 100644 --- a/bazel/toolchains/container_images.bzl +++ b/bazel/toolchains/container_images.bzl @@ -7,7 +7,7 @@ load("@rules_oci//oci:pull.bzl", "oci_pull") def containter_image_deps(): oci_pull( name = "distroless_static", - digest = "sha256:41972110a1c1a5c0b6adb283e8aa092c43c31f7c5d79b8656fbffff2c3e61f05", + digest = "sha256:f4a57e8ffd7ba407bdd0eb315bb54ef1f21a2100a7f032e9102e4da34fe7c196", image = "gcr.io/distroless/static", platforms = [ "linux/amd64", @@ -16,6 +16,6 @@ def containter_image_deps(): ) oci_pull( name = "libvirtd_base", - digest = "sha256:b1a65581c445a1da618e33743578c4ea80e6a724659fbad9e6555a6a9f48b37a", + digest = "sha256:99dbf3cf69b3f97cb0158bde152c9bc7c2a96458cf462527ee80b75754f572a7", image = "ghcr.io/edgelesssys/constellation/libvirtd-base", ) diff --git a/bazel/toolchains/go_module_deps.bzl b/bazel/toolchains/go_module_deps.bzl deleted file mode 100644 index c85e8f6b5..000000000 --- a/bazel/toolchains/go_module_deps.bzl +++ /dev/null @@ -1,7237 +0,0 @@ -"""Go module dependencies for Bazel. - -Contains the equivalent of go.mod and go.sum files for Bazel. -""" - -load("@bazel_gazelle//:deps.bzl", "go_repository") - -def go_dependencies(): - """Declare Go module dependencies for Bazel.""" - go_repository( - name = "build_buf_gen_go_bufbuild_protovalidate_protocolbuffers_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go", - sum = "h1:tdpHgTbmbvEIARu+bixzmleMi14+3imnpoFXz+Qzjp4=", - version = "v1.31.0-20230802163732-1c33ebd9ecfa.1", - ) - go_repository( - name = "cat_dario_mergo", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "dario.cat/mergo", - sum = "h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=", - version = "v1.0.0", - ) - go_repository( - name = "cc_mvdan_editorconfig", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "mvdan.cc/editorconfig", - sum = "h1:8nmqQGVnHUtHuT+yvuA49lQK0y5il5IOr2PtCBkDI2M=", - version = "v0.2.1-0.20231228180347-1925077f8eb2", - ) - go_repository( - name = "cc_mvdan_unparam", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "mvdan.cc/unparam", - sum = "h1:VuJo4Mt0EVPychre4fNlDWDuE5AjXtPJpRUWqZDQhaI=", - version = "v0.0.0-20230312165513-e84e2d14e3b8", - ) - go_repository( - name = "co_honnef_go_tools", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "honnef.co/go/tools", - sum = "h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=", - version = "v0.0.1-2020.1.4", - ) - go_repository( - name = "com_github_adalogics_go_fuzz_headers", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/AdaLogics/go-fuzz-headers", - sum = "h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=", - version = "v0.0.0-20230811130428-ced1acdcaa24", - ) - go_repository( - name = "com_github_adamkorcz_go_118_fuzz_build", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/AdamKorcz/go-118-fuzz-build", - sum = "h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA=", - version = "v0.0.0-20230306123547-8075edf89bb0", - ) - go_repository( - name = "com_github_adamkorcz_go_fuzz_headers_1", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/AdamKorcz/go-fuzz-headers-1", - sum = "h1:zjqpY4C7H15HjRPEenkS4SAn3Jy2eRRjkjZbGR30TOg=", - version = "v0.0.0-20230919221257-8b5d3ce2d11d", - ) - go_repository( - name = "com_github_adrg_xdg", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/adrg/xdg", - sum = "h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=", - version = "v0.4.0", - ) - go_repository( - name = "com_github_agext_levenshtein", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/agext/levenshtein", - sum = "h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE=", - version = "v1.2.2", - ) - go_repository( - name = "com_github_agnivade_levenshtein", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/agnivade/levenshtein", - sum = "h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_akavel_rsrc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/akavel/rsrc", - sum = "h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw=", - version = "v0.10.2", - ) - go_repository( - name = "com_github_alcortesm_tgz", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/alcortesm/tgz", - sum = "h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=", - version = "v0.0.0-20161220082320-9c5fe88206d7", - ) - go_repository( - name = "com_github_alecthomas_kingpin_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/alecthomas/kingpin/v2", - sum = "h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=", - version = "v2.4.0", - ) - go_repository( - name = "com_github_alecthomas_template", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/alecthomas/template", - sum = "h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=", - version = "v0.0.0-20160405071501-a0175ee3bccc", - ) - go_repository( - name = "com_github_alecthomas_units", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/alecthomas/units", - sum = "h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=", - version = "v0.0.0-20211218093645-b94a6e3cc137", - ) - go_repository( - name = "com_github_alessio_shellescape", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/alessio/shellescape", - sum = "h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=", - version = "v1.4.1", - ) - go_repository( - name = "com_github_anatol_vmtest", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/anatol/vmtest", - sum = "h1:t4JGeY9oaF5LB4Rdx9e2wARRRPAYt8Ow4eCf5SwO3fA=", - version = "v0.0.0-20220413190228-7a42f1f6d7b8", - ) - go_repository( - name = "com_github_anmitsu_go_shlex", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/anmitsu/go-shlex", - sum = "h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=", - version = "v0.0.0-20161002113705-648efa622239", - ) - go_repository( - name = "com_github_antihax_optional", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/antihax/optional", - sum = "h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_antlr_antlr4_runtime_go_antlr_v4", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/antlr/antlr4/runtime/Go/antlr/v4", - sum = "h1:goHVqTbFX3AIo0tzGr14pgfAW2ZfPChKO21Z9MGf/gk=", - version = "v4.0.0-20230512164433-5d1fd1a340c9", - ) - go_repository( - name = "com_github_apparentlymart_go_textseg_v12", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/apparentlymart/go-textseg/v12", - sum = "h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0=", - version = "v12.0.0", - ) - go_repository( - name = "com_github_apparentlymart_go_textseg_v13", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/apparentlymart/go-textseg/v13", - sum = "h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=", - version = "v13.0.0", - ) - go_repository( - name = "com_github_apparentlymart_go_textseg_v15", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/apparentlymart/go-textseg/v15", - sum = "h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=", - version = "v15.0.0", - ) - go_repository( - name = "com_github_armon_circbuf", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/armon/circbuf", - sum = "h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=", - version = "v0.0.0-20150827004946-bbbad097214e", - ) - go_repository( - name = "com_github_armon_go_radix", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/armon/go-radix", - sum = "h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_armon_go_socks5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/armon/go-socks5", - sum = "h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=", - version = "v0.0.0-20160902184237-e75332964ef5", - ) - go_repository( - name = "com_github_asaskevich_govalidator", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/asaskevich/govalidator", - sum = "h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=", - version = "v0.0.0-20230301143203-a9d515a09cc2", - ) - go_repository( - name = "com_github_aws_aws_sdk_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go", - sum = "h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo=", - version = "v1.53.0", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2", - sum = "h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=", - version = "v1.26.1", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_aws_protocol_eventstream", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream", - sum = "h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to=", - version = "v1.6.2", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_config", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/config", - sum = "h1:WbKW8hOzrWoOA/+35S5okqO/2Ap8hkkFUzoW8Hzq24A=", - version = "v1.27.13", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_credentials", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/credentials", - sum = "h1:XDCJDzk/u5cN7Aple7D/MiAhx1Rjo/0nueJ0La8mRuE=", - version = "v1.17.13", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_feature_ec2_imds", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/feature/ec2/imds", - sum = "h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4=", - version = "v1.16.1", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_feature_s3_manager", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/feature/s3/manager", - sum = "h1:9b1Os1s11mF5qTIKLgSsyPG810di2+ySSLIIt9bwe9I=", - version = "v1.16.17", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_internal_configsources", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/internal/configsources", - sum = "h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=", - version = "v1.3.5", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_internal_endpoints_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/internal/endpoints/v2", - sum = "h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0=", - version = "v2.6.5", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_internal_ini", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/internal/ini", - sum = "h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=", - version = "v1.8.0", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_internal_v4a", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/internal/v4a", - sum = "h1:81KE7vaZzrl7yHBYHVEzYB8sypz11NMOZ40YlWvPxsU=", - version = "v1.3.5", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_autoscaling", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/autoscaling", - sum = "h1:IDoEdCkKRy7iPlRVSuDATGE57xUjrk5i1M9eWPYwr/Y=", - version = "v1.40.6", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_cloudfront", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/cloudfront", - sum = "h1://GRw/PrpnUyWBJh6KvUvR9AgkDBhclzaj3HKGxRoCw=", - version = "v1.36.1", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_ec2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/ec2", - sum = "h1:NbjXshriDs5bGeqKvrOF70L41X0aCMC60ImN2vkcQAc=", - version = "v1.161.1", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_elasticloadbalancingv2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2", - sum = "h1:P5kMcIzrz4Y7GIkvmkosgv/0cs1Crk/VLo5pBhrTWGI=", - version = "v1.30.6", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_internal_accept_encoding", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding", - sum = "h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs=", - version = "v1.11.2", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_internal_checksum", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/internal/checksum", - sum = "h1:ZMeFZ5yk+Ek+jNr1+uwCd2tG89t6oTS5yVWpa6yy2es=", - version = "v1.3.7", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_internal_presigned_url", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/internal/presigned-url", - sum = "h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo=", - version = "v1.11.7", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_internal_s3shared", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/internal/s3shared", - sum = "h1:f9RyWNtS8oH7cZlbn+/JNPpjUk5+5fLd5lM9M0i49Ys=", - version = "v1.17.5", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_kms", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/kms", - sum = "h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU=", - version = "v1.30.0", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_resourcegroupstaggingapi", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi", - sum = "h1:GR0vFRc5TpN36ppQJjd+gjRRC9vMAHN5C2W53oMWCJU=", - version = "v1.21.5", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_s3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/s3", - sum = "h1:rq2hglTQM3yHZvOPVMtNvLS5x6hijx7JvRDgKiTNDGQ=", - version = "v1.53.2", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_secretsmanager", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/secretsmanager", - sum = "h1:4cziOtpDwtgcb+wTYRzz8C+GoH1XySy0p7j4oBbqPQE=", - version = "v1.28.7", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_sso", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/sso", - sum = "h1:o5cTaeunSpfXiLTIBx5xo2enQmiChtu1IBbzXnfU9Hs=", - version = "v1.20.6", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_ssooidc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/ssooidc", - sum = "h1:Qe0r0lVURDDeBQJ4yP+BOrJkvkiCo/3FH/t+wY11dmw=", - version = "v1.24.0", - ) - go_repository( - name = "com_github_aws_aws_sdk_go_v2_service_sts", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/aws-sdk-go-v2/service/sts", - sum = "h1:et3Ta53gotFR4ERLXXHIHl/Uuk1qYpP5uU7cvNql8ns=", - version = "v1.28.7", - ) - go_repository( - name = "com_github_aws_smithy_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/aws/smithy-go", - sum = "h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=", - version = "v1.20.2", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go", - sum = "h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=", - version = "v68.0.0+incompatible", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_azcore", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/azcore", - sum = "h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=", - version = "v1.11.1", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_azidentity", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/azidentity", - sum = "h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU=", - version = "v1.5.2", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_internal", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/internal", - sum = "h1:sUFnFjzDUie80h24I7mrKtwCKgLY9L8h5Tp2x9+TWqk=", - version = "v1.6.0", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_keyvault_azkeys", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys", - sum = "h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM=", - version = "v0.10.0", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_keyvault_internal", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal", - sum = "h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw=", - version = "v0.7.1", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5", - sum = "h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4=", - version = "v5.7.0", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_resourcemanager_internal_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2", - sum = "h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do=", - version = "v2.0.0", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_resourcemanager_network_armnetwork_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5", - sum = "h1:QZY6o3E/KX0QhgQpvat4UxAsXuBIb4efrFtZcqCUTbs=", - version = "v5.1.1", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_resourcemanager_resources_armresources", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources", - sum = "h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_resourcemanager_storage_armstorage", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage", - sum = "h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70=", - version = "v1.5.0", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_security_keyvault_azkeys", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys", - sum = "h1:DRiANoJTiW6obBQe3SqZizkuV1PEgfiiGivmVocDy64=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_security_keyvault_azsecrets", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets", - sum = "h1:h4Zxgmi9oyZL2l8jeg1iRTqPloHktywWcu0nlJmo1tA=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_security_keyvault_internal", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal", - sum = "h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_azure_azure_sdk_for_go_sdk_storage_azblob", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob", - sum = "h1:YUUxeiOWgdAQE3pXt2H7QXzZs0q8UBjgRbl56qo8GYM=", - version = "v1.3.2", - ) - go_repository( - name = "com_github_azure_go_ansiterm", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/go-ansiterm", - sum = "h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=", - version = "v0.0.0-20210617225240-d185dfc1b5a1", - ) - go_repository( - name = "com_github_azure_go_autorest", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/go-autorest", - sum = "h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=", - version = "v14.2.0+incompatible", - ) - go_repository( - name = "com_github_azure_go_autorest_autorest", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/go-autorest/autorest", - sum = "h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw=", - version = "v0.11.29", - ) - go_repository( - name = "com_github_azure_go_autorest_autorest_adal", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/go-autorest/autorest/adal", - sum = "h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8=", - version = "v0.9.23", - ) - go_repository( - name = "com_github_azure_go_autorest_autorest_date", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/go-autorest/autorest/date", - sum = "h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=", - version = "v0.3.0", - ) - go_repository( - name = "com_github_azure_go_autorest_autorest_mocks", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/go-autorest/autorest/mocks", - sum = "h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=", - version = "v0.4.2", - ) - go_repository( - name = "com_github_azure_go_autorest_autorest_to", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/go-autorest/autorest/to", - sum = "h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=", - version = "v0.4.0", - ) - go_repository( - name = "com_github_azure_go_autorest_autorest_validation", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/go-autorest/autorest/validation", - sum = "h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=", - version = "v0.3.1", - ) - go_repository( - name = "com_github_azure_go_autorest_logger", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/go-autorest/logger", - sum = "h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=", - version = "v0.2.1", - ) - go_repository( - name = "com_github_azure_go_autorest_tracing", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Azure/go-autorest/tracing", - sum = "h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=", - version = "v0.6.0", - ) - go_repository( - name = "com_github_azuread_microsoft_authentication_library_for_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/AzureAD/microsoft-authentication-library-for-go", - sum = "h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=", - version = "v1.2.2", - ) - go_repository( - name = "com_github_bazelbuild_buildtools", - # keep - build_file_generation = "off", - # keep - build_file_proto_mode = "default", - importpath = "github.com/bazelbuild/buildtools", - sum = "h1:hqhMmuZiSNwCWVHqnpr4DZfIeZ2/aJF7fs207eg7HZo=", - version = "v0.0.0-20240422193413-1429e15ae755", - ) - go_repository( - name = "com_github_bazelbuild_rules_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/bazelbuild/rules_go", - sum = "h1:9s9FA2l8IAxCbwV97E1WLu5ai21muLNrjZRV0+agTRs=", - version = "v0.47.1", - ) - go_repository( - name = "com_github_beorn7_perks", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/beorn7/perks", - sum = "h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_bgentry_speakeasy", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/bgentry/speakeasy", - sum = "h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_blang_semver", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/blang/semver", - sum = "h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=", - version = "v3.5.1+incompatible", - ) - go_repository( - name = "com_github_blang_semver_v4", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/blang/semver/v4", - sum = "h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=", - version = "v4.0.0", - ) - go_repository( - name = "com_github_bshuster_repo_logrus_logstash_hook", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/bshuster-repo/logrus-logstash-hook", - sum = "h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_bufbuild_protocompile", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/bufbuild/protocompile", - sum = "h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY=", - version = "v0.6.0", - ) - go_repository( - name = "com_github_bufbuild_protovalidate_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/bufbuild/protovalidate-go", - sum = "h1:pJr07sYhliyfj/STAM7hU4J3FKpVeLVKvOBmOTN8j+s=", - version = "v0.2.1", - ) - go_repository( - name = "com_github_bugsnag_bugsnag_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/bugsnag/bugsnag-go", - sum = "h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng=", - version = "v0.0.0-20141110184014-b1d153021fcd", - ) - go_repository( - name = "com_github_bugsnag_osext", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/bugsnag/osext", - sum = "h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ=", - version = "v0.0.0-20130617224835-0dd3f918b21b", - ) - go_repository( - name = "com_github_bugsnag_panicwrap", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/bugsnag/panicwrap", - sum = "h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o=", - version = "v0.0.0-20151223152923-e2c28503fcd0", - ) - go_repository( - name = "com_github_burntsushi_toml", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/BurntSushi/toml", - sum = "h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=", - version = "v1.3.2", - ) - go_repository( - name = "com_github_burntsushi_xgb", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/BurntSushi/xgb", - sum = "h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=", - version = "v0.0.0-20160522181843-27f122750802", - ) - go_repository( - name = "com_github_bwesterb_go_ristretto", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/bwesterb/go-ristretto", - sum = "h1:1w53tCkGhCQ5djbat3+MH0BAQ5Kfgbt56UZQ/JMzngw=", - version = "v1.2.3", - ) - go_repository( - name = "com_github_cavaliercoder_badio", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cavaliercoder/badio", - sum = "h1:YYUjy5BRwO5zPtfk+aa2gw255FIIoi93zMmuy19o0bc=", - version = "v0.0.0-20160213150051-ce5280129e9e", - ) - go_repository( - name = "com_github_cavaliercoder_go_rpm", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cavaliercoder/go-rpm", - sum = "h1:jP7ki8Tzx9ThnFPLDhBYAhEpI2+jOURnHQNURgsMvnY=", - version = "v0.0.0-20200122174316-8cb9fd9c31a8", - ) - go_repository( - name = "com_github_cavaliergopher_cpio", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cavaliergopher/cpio", - sum = "h1:KQFSeKmZhv0cr+kawA3a0xTQCU4QxXF1vhU7P7av2KM=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_cenkalti_backoff_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cenkalti/backoff/v3", - sum = "h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=", - version = "v3.2.2", - ) - go_repository( - name = "com_github_cenkalti_backoff_v4", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cenkalti/backoff/v4", - sum = "h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=", - version = "v4.2.1", - ) - go_repository( - name = "com_github_census_instrumentation_opencensus_proto", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/census-instrumentation/opencensus-proto", - sum = "h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=", - version = "v0.4.1", - ) - go_repository( - name = "com_github_cespare_xxhash", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cespare/xxhash", - sum = "h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_cespare_xxhash_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cespare/xxhash/v2", - sum = "h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=", - version = "v2.2.0", - ) - go_repository( - name = "com_github_chai2010_gettext_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/chai2010/gettext-go", - sum = "h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=", - version = "v1.0.2", - ) - go_repository( - name = "com_github_checkpoint_restore_go_criu_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/checkpoint-restore/go-criu/v5", - sum = "h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8=", - version = "v5.3.0", - ) - go_repository( - name = "com_github_chromedp_cdproto", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/chromedp/cdproto", - sum = "h1:aPflPkRFkVwbW6dmcVqfgwp1i+UWGFH6VgR1Jim5Ygc=", - version = "v0.0.0-20230802225258-3cf4e6d46a89", - ) - go_repository( - name = "com_github_chromedp_chromedp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/chromedp/chromedp", - sum = "h1:dKtNz4kApb06KuSXoTQIyUC2TrA0fhGDwNZf3bcgfKw=", - version = "v0.9.2", - ) - go_repository( - name = "com_github_chromedp_sysutil", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/chromedp/sysutil", - sum = "h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_chzyer_logex", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/chzyer/logex", - sum = "h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=", - version = "v1.1.10", - ) - go_repository( - name = "com_github_chzyer_readline", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/chzyer/readline", - sum = "h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=", - version = "v1.5.1", - ) - go_repository( - name = "com_github_chzyer_test", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/chzyer/test", - sum = "h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=", - version = "v0.0.0-20180213035817-a1ea475d72b1", - ) - go_repository( - name = "com_github_cilium_ebpf", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cilium/ebpf", - sum = "h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4=", - version = "v0.9.1", - ) - go_repository( - name = "com_github_client9_misspell", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/client9/misspell", - sum = "h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=", - version = "v0.3.4", - ) - go_repository( - name = "com_github_cloudflare_circl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cloudflare/circl", - # keep - patches = [ - "//3rdparty/bazel/com_github_cloudflare_circl:math_fp448_BUILD_bazel.patch", - "//3rdparty/bazel/com_github_cloudflare_circl:math_fp25519_BUILD_bazel.patch", - "//3rdparty/bazel/com_github_cloudflare_circl:dh_x448_BUILD_bazel.patch", - "//3rdparty/bazel/com_github_cloudflare_circl:dh_x25519_BUILD_bazel.patch", - ], - sum = "h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=", - version = "v1.3.7", - ) - go_repository( - name = "com_github_cncf_udpa_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cncf/udpa/go", - sum = "h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=", - version = "v0.0.0-20220112060539-c52dc94e7fbe", - ) - go_repository( - name = "com_github_cncf_xds_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cncf/xds/go", - sum = "h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=", - version = "v0.0.0-20231128003011-0fa0005c9caa", - ) - go_repository( - name = "com_github_codahale_rfc6979", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/codahale/rfc6979", - sum = "h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=", - version = "v0.0.0-20141003034818-6a90f24967eb", - ) - go_repository( - name = "com_github_common_nighthawk_go_figure", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/common-nighthawk/go-figure", - sum = "h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ=", - version = "v0.0.0-20210622060536-734e95fb86be", - ) - go_repository( - name = "com_github_container_orchestrated_devices_container_device_interface", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/container-orchestrated-devices/container-device-interface", - sum = "h1:mz77uJoP8im/4Zins+mPqt677ZMaflhoGaYrRAl5jvA=", - version = "v0.6.1", - ) - go_repository( - name = "com_github_container_storage_interface_spec", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/container-storage-interface/spec", - sum = "h1:D0vhF3PLIZwlwZEf2eNbpujGCNwspwTYf2idJRJx4xI=", - version = "v1.8.0", - ) - go_repository( - name = "com_github_containerd_aufs", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/aufs", - sum = "h1:2oeJiwX5HstO7shSrPZjrohJZLzK36wvpdmzDRkL/LY=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_containerd_btrfs_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/btrfs/v2", - sum = "h1:FN4wsx7KQrYoLXN7uLP0vBV4oVWHOIKDRQ1G2Z0oL5M=", - version = "v2.0.0", - ) - go_repository( - name = "com_github_containerd_cgroups", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/cgroups", - sum = "h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_containerd_cgroups_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/cgroups/v3", - sum = "h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0=", - version = "v3.0.2", - ) - go_repository( - name = "com_github_containerd_console", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/console", - sum = "h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=", - version = "v1.0.3", - ) - go_repository( - name = "com_github_containerd_containerd", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/containerd", - sum = "h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0=", - version = "v1.7.12", - ) - go_repository( - name = "com_github_containerd_continuity", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/continuity", - sum = "h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=", - version = "v0.4.2", - ) - go_repository( - name = "com_github_containerd_fifo", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/fifo", - sum = "h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_containerd_go_cni", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/go-cni", - sum = "h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9rU=", - version = "v1.1.9", - ) - go_repository( - name = "com_github_containerd_go_runc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/go-runc", - sum = "h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_containerd_imgcrypt", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/imgcrypt", - sum = "h1:WSf9o9EQ0KGHiUx2ESFZ+PKf4nxK9BcvV/nJDX8RkB4=", - version = "v1.1.7", - ) - go_repository( - name = "com_github_containerd_log", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/log", - sum = "h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_containerd_nri", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/nri", - sum = "h1:PjgIBm0RtUiFyEO6JqPBQZRQicbsIz41Fz/5VSC0zgw=", - version = "v0.4.0", - ) - go_repository( - name = "com_github_containerd_stargz_snapshotter_estargz", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/stargz-snapshotter/estargz", - sum = "h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=", - version = "v0.14.3", - ) - go_repository( - name = "com_github_containerd_ttrpc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/ttrpc", - sum = "h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs=", - version = "v1.2.2", - ) - go_repository( - name = "com_github_containerd_typeurl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/typeurl", - sum = "h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY=", - version = "v1.0.2", - ) - go_repository( - name = "com_github_containerd_typeurl_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/typeurl/v2", - sum = "h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=", - version = "v2.1.1", - ) - go_repository( - name = "com_github_containerd_zfs", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containerd/zfs", - sum = "h1:n7OZ7jZumLIqNJqXrEc/paBM840mORnmGdJDmAmJZHM=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_containernetworking_cni", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containernetworking/cni", - sum = "h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ=", - version = "v1.1.2", - ) - go_repository( - name = "com_github_containernetworking_plugins", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containernetworking/plugins", - sum = "h1:SWgg3dQG1yzUo4d9iD8cwSVh1VqI+bP7mkPDoSfP9VU=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_containers_ocicrypt", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/containers/ocicrypt", - sum = "h1:uoG52u2e91RE4UqmBICZY8dNshgfvkdl3BW6jnxiFaI=", - version = "v1.1.6", - ) - go_repository( - name = "com_github_coredns_caddy", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/coredns/caddy", - sum = "h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_coredns_corefile_migration", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/coredns/corefile-migration", - sum = "h1:W/DCETrHDiFo0Wj03EyMkaQ9fwsmSgqTCQDHpceaSsE=", - version = "v1.0.21", - ) - go_repository( - name = "com_github_coreos_go_oidc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/coreos/go-oidc", - sum = "h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=", - version = "v2.2.1+incompatible", - ) - go_repository( - name = "com_github_coreos_go_oidc_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/coreos/go-oidc/v3", - sum = "h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo=", - version = "v3.9.0", - ) - go_repository( - name = "com_github_coreos_go_semver", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/coreos/go-semver", - sum = "h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=", - version = "v0.3.1", - ) - go_repository( - name = "com_github_coreos_go_systemd_v22", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/coreos/go-systemd/v22", - sum = "h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=", - version = "v22.5.0", - ) - go_repository( - name = "com_github_cosi_project_runtime", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cosi-project/runtime", - sum = "h1:9lJWw5cl3Lz1qP32bl2vxAsJs6LM8KdUGLCc9t/EGqw=", - version = "v0.4.1", - ) - go_repository( - name = "com_github_cpuguy83_go_md2man_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cpuguy83/go-md2man/v2", - sum = "h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=", - version = "v2.0.3", - ) - go_repository( - name = "com_github_creack_pty", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/creack/pty", - sum = "h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=", - version = "v1.1.21", - ) - go_repository( - name = "com_github_cyberphone_json_canonicalization", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cyberphone/json-canonicalization", - sum = "h1:vU+EP9ZuFUCYE0NYLwTSob+3LNEJATzNfP/DC7SWGWI=", - version = "v0.0.0-20220623050100-57a0ce2678a7", - ) - go_repository( - name = "com_github_cyphar_filepath_securejoin", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/cyphar/filepath-securejoin", - sum = "h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=", - version = "v0.2.4", - ) - go_repository( - name = "com_github_danieljoos_wincred", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/danieljoos/wincred", - sum = "h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_data_dog_go_sqlmock", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/DATA-DOG/go-sqlmock", - sum = "h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=", - version = "v1.5.2", - ) - go_repository( - name = "com_github_davecgh_go_spew", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/davecgh/go-spew", - sum = "h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=", - version = "v1.1.2-0.20180830191138-d8f796af33cc", - ) - go_repository( - name = "com_github_daviddengcn_go_colortext", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/daviddengcn/go-colortext", - sum = "h1:ANqDyC0ys6qCSvuEK7l3g5RaehL/Xck9EX8ATG8oKsE=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_decred_dcrd_dcrec_secp256k1_v4", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/decred/dcrd/dcrec/secp256k1/v4", - sum = "h1:1iy2qD6JEhHKKhUOA9IWs7mjco7lnw2qx8FsRI2wirE=", - version = "v4.0.0-20210816181553-5444fa50b93d", - ) - go_repository( - name = "com_github_denisenkom_go_mssqldb", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/denisenkom/go-mssqldb", - sum = "h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk=", - version = "v0.9.0", - ) - go_repository( - name = "com_github_dgryski_go_rendezvous", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/dgryski/go-rendezvous", - sum = "h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=", - version = "v0.0.0-20200823014737-9f7001d12a5f", - ) - go_repository( - name = "com_github_distribution_distribution_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/distribution/distribution/v3", - sum = "h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc=", - version = "v3.0.0-20221208165359-362910506bc2", - ) - go_repository( - name = "com_github_distribution_reference", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/distribution/reference", - sum = "h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=", - version = "v0.5.0", - ) - go_repository( - name = "com_github_dnaeon_go_vcr", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/dnaeon/go-vcr", - sum = "h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_docker_cli", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/docker/cli", - sum = "h1:mFpqnrS6Hsm3v1k7Wa/BO23oz0k121MTbTO1lpcGSkU=", - version = "v25.0.1+incompatible", - ) - go_repository( - name = "com_github_docker_distribution", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/docker/distribution", - sum = "h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=", - version = "v2.8.3+incompatible", - ) - go_repository( - name = "com_github_docker_docker", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/docker/docker", - sum = "h1:UVX5ZOrrfTGZZYEP+ZDq3Xn9PdHNXaSYMFPDumMqG2k=", - version = "v26.1.2+incompatible", - ) - go_repository( - name = "com_github_docker_docker_credential_helpers", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/docker/docker-credential-helpers", - sum = "h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=", - version = "v0.7.0", - ) - go_repository( - name = "com_github_docker_go_connections", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/docker/go-connections", - sum = "h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=", - version = "v0.5.0", - ) - go_repository( - name = "com_github_docker_go_events", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/docker/go-events", - sum = "h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=", - version = "v0.0.0-20190806004212-e31b211e4f1c", - ) - go_repository( - name = "com_github_docker_go_metrics", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/docker/go-metrics", - sum = "h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=", - version = "v0.0.1", - ) - go_repository( - name = "com_github_docker_go_units", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/docker/go-units", - sum = "h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=", - version = "v0.5.0", - ) - go_repository( - name = "com_github_docker_libtrust", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/docker/libtrust", - sum = "h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=", - version = "v0.0.0-20160708172513-aabc10ec26b7", - ) - go_repository( - name = "com_github_dustin_go_humanize", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/dustin/go-humanize", - sum = "h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_edgelesssys_go_azguestattestation", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/edgelesssys/go-azguestattestation", - sum = "h1:XcoMVhZve0RRkSxFDn9Bs/z4FpHqZ3eHgVNWNCNOkqc=", - version = "v0.0.0-20240513062303-05f8770a633d", - ) - go_repository( - name = "com_github_edgelesssys_go_tdx_qpl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/edgelesssys/go-tdx-qpl", - sum = "h1:TCGUmmH50cQBGXPJsn32APf93fmWQXcSMi7pMbDPtV0=", - version = "v0.0.0-20240123150912-dcad3c41ec5f", - ) - go_repository( - name = "com_github_eggsampler_acme_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/eggsampler/acme/v3", - sum = "h1:LHWnB3wShVshK1+umL6ObCjnc0MM+D7TE8JINjk8zGY=", - version = "v3.4.0", - ) - go_repository( - name = "com_github_emicklei_dot", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/emicklei/dot", - sum = "h1:ujpDlBkkwgWUY+qPId5IwapRW/xEoligRSYjioR6DFI=", - version = "v1.6.1", - ) - go_repository( - name = "com_github_emicklei_go_restful_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/emicklei/go-restful/v3", - sum = "h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=", - version = "v3.11.0", - ) - go_repository( - name = "com_github_emirpasic_gods", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/emirpasic/gods", - sum = "h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=", - version = "v1.18.1", - ) - go_repository( - name = "com_github_envoyproxy_go_control_plane", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/envoyproxy/go-control-plane", - sum = "h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=", - version = "v0.12.0", - ) - go_repository( - name = "com_github_envoyproxy_protoc_gen_validate", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/envoyproxy/protoc-gen-validate", - sum = "h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=", - version = "v1.0.4", - ) - go_repository( - name = "com_github_euank_go_kmsg_parser", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/euank/go-kmsg-parser", - sum = "h1:cHD53+PLQuuQyLZeriD1V/esuG4MuU0Pjs5y6iknohY=", - version = "v2.0.0+incompatible", - ) - go_repository( - name = "com_github_evanphx_json_patch", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/evanphx/json-patch", - sum = "h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=", - version = "v5.9.0+incompatible", - ) - go_repository( - name = "com_github_evanphx_json_patch_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/evanphx/json-patch/v5", - sum = "h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=", - version = "v5.9.0", - ) - go_repository( - name = "com_github_exponent_io_jsonpath", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/exponent-io/jsonpath", - sum = "h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=", - version = "v0.0.0-20151013193312-d6023ce2651d", - ) - go_repository( - name = "com_github_fatih_camelcase", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/fatih/camelcase", - sum = "h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_fatih_color", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/fatih/color", - sum = "h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=", - version = "v1.16.0", - ) - go_repository( - name = "com_github_felixge_httpsnoop", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/felixge/httpsnoop", - sum = "h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=", - version = "v1.0.4", - ) - go_repository( - name = "com_github_flynn_go_docopt", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/flynn/go-docopt", - sum = "h1:Ss/B3/5wWRh8+emnK0++g5zQzwDTi30W10pKxKc4JXI=", - version = "v0.0.0-20140912013429-f6dd2ebbb31e", - ) - go_repository( - name = "com_github_flynn_go_shlex", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/flynn/go-shlex", - sum = "h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=", - version = "v0.0.0-20150515145356-3f9db97f8568", - ) - go_repository( - name = "com_github_foxboron_go_uefi", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/foxboron/go-uefi", - sum = "h1:qGlg/7H49H30Eu7nkCBA7YxNmW30ephqBf7xIxlAGuQ=", - version = "v0.0.0-20240128152106-48be911532c2", - ) - go_repository( - name = "com_github_foxcpp_go_mockdns", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/foxcpp/go-mockdns", - sum = "h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_frankban_quicktest", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/frankban/quicktest", - sum = "h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=", - version = "v1.14.6", - ) - go_repository( - name = "com_github_fsnotify_fsnotify", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/fsnotify/fsnotify", - sum = "h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=", - version = "v1.7.0", - ) - go_repository( - name = "com_github_fullstorydev_grpcurl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/fullstorydev/grpcurl", - sum = "h1:JMvZXK8lHDGyLmTQ0ZdGDnVVGuwjbpaumf8p42z0d+c=", - version = "v1.8.9", - ) - go_repository( - name = "com_github_fvbommel_sortorder", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/fvbommel/sortorder", - sum = "h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_fxamacker_cbor_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/fxamacker/cbor/v2", - sum = "h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA=", - version = "v2.6.0", - ) - go_repository( - name = "com_github_gabriel_vasile_mimetype", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gabriel-vasile/mimetype", - sum = "h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=", - version = "v1.4.3", - ) - go_repository( - name = "com_github_gertd_go_pluralize", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gertd/go-pluralize", - sum = "h1:M3uASbVjMnTsPb0PNqg+E/24Vwigyo/tvyMTtAlLgiA=", - version = "v0.2.1", - ) - go_repository( - name = "com_github_ghodss_yaml", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ghodss/yaml", - sum = "h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_gliderlabs_ssh", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gliderlabs/ssh", - sum = "h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=", - version = "v0.2.2", - ) - go_repository( - name = "com_github_go_chi_chi", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-chi/chi", - sum = "h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=", - version = "v4.1.2+incompatible", - ) - go_repository( - name = "com_github_go_errors_errors", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-errors/errors", - sum = "h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=", - version = "v1.4.2", - ) - go_repository( - name = "com_github_go_git_gcfg", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-git/gcfg", - sum = "h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=", - version = "v1.5.1-0.20230307220236-3a3c6141e376", - ) - go_repository( - name = "com_github_go_git_go_billy_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-git/go-billy/v5", - sum = "h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=", - version = "v5.5.0", - ) - go_repository( - name = "com_github_go_git_go_git_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-git/go-git/v5", - sum = "h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=", - version = "v5.12.0", - ) - go_repository( - name = "com_github_go_gl_glfw", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-gl/glfw", - sum = "h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=", - version = "v0.0.0-20190409004039-e6da0acd62b1", - ) - go_repository( - name = "com_github_go_gl_glfw_v3_3_glfw", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-gl/glfw/v3.3/glfw", - sum = "h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I=", - version = "v0.0.0-20200222043503-6f7a984d4dc4", - ) - go_repository( - name = "com_github_go_gorp_gorp_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-gorp/gorp/v3", - sum = "h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs=", - version = "v3.1.0", - ) - go_repository( - name = "com_github_go_jose_go_jose_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-jose/go-jose/v3", - sum = "h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=", - version = "v3.0.3", - ) - go_repository( - name = "com_github_go_kit_kit", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-kit/kit", - sum = "h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=", - version = "v0.8.0", - ) - go_repository( - name = "com_github_go_kit_log", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-kit/log", - sum = "h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=", - version = "v0.2.1", - ) - go_repository( - name = "com_github_go_logfmt_logfmt", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-logfmt/logfmt", - sum = "h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=", - version = "v0.5.1", - ) - go_repository( - name = "com_github_go_logr_logr", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-logr/logr", - sum = "h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=", - version = "v1.4.1", - ) - go_repository( - name = "com_github_go_logr_stdr", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-logr/stdr", - sum = "h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=", - version = "v1.2.2", - ) - go_repository( - name = "com_github_go_logr_zapr", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-logr/zapr", - sum = "h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=", - version = "v1.3.0", - ) - go_repository( - name = "com_github_go_openapi_analysis", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-openapi/analysis", - sum = "h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=", - version = "v0.23.0", - ) - go_repository( - name = "com_github_go_openapi_errors", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-openapi/errors", - sum = "h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=", - version = "v0.22.0", - ) - go_repository( - name = "com_github_go_openapi_jsonpointer", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-openapi/jsonpointer", - sum = "h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=", - version = "v0.21.0", - ) - go_repository( - name = "com_github_go_openapi_jsonreference", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-openapi/jsonreference", - sum = "h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=", - version = "v0.21.0", - ) - go_repository( - name = "com_github_go_openapi_loads", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-openapi/loads", - sum = "h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=", - version = "v0.22.0", - ) - go_repository( - name = "com_github_go_openapi_runtime", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-openapi/runtime", - sum = "h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=", - version = "v0.28.0", - ) - go_repository( - name = "com_github_go_openapi_spec", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-openapi/spec", - sum = "h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=", - version = "v0.21.0", - ) - go_repository( - name = "com_github_go_openapi_strfmt", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-openapi/strfmt", - sum = "h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=", - version = "v0.23.0", - ) - go_repository( - name = "com_github_go_openapi_swag", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-openapi/swag", - sum = "h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=", - version = "v0.23.0", - ) - go_repository( - name = "com_github_go_openapi_validate", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-openapi/validate", - sum = "h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=", - version = "v0.24.0", - ) - go_repository( - name = "com_github_go_playground_assert_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-playground/assert/v2", - sum = "h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=", - version = "v2.2.0", - ) - go_repository( - name = "com_github_go_playground_locales", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-playground/locales", - sum = "h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=", - version = "v0.14.1", - ) - go_repository( - name = "com_github_go_playground_universal_translator", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-playground/universal-translator", - sum = "h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=", - version = "v0.18.1", - ) - go_repository( - name = "com_github_go_playground_validator_v10", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-playground/validator/v10", - sum = "h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=", - version = "v10.20.0", - ) - go_repository( - name = "com_github_go_redis_redismock_v9", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-redis/redismock/v9", - sum = "h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw=", - version = "v9.2.0", - ) - go_repository( - name = "com_github_go_rod_rod", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-rod/rod", - sum = "h1:h4pimzSOUnw7Eo41zdJA788XsawzHjJMyzCE3BrBww0=", - version = "v0.114.7", - ) - go_repository( - name = "com_github_go_sql_driver_mysql", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-sql-driver/mysql", - sum = "h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=", - version = "v1.8.1", - ) - go_repository( - name = "com_github_go_stack_stack", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-stack/stack", - sum = "h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=", - version = "v1.8.0", - ) - go_repository( - name = "com_github_go_task_slim_sprig", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-task/slim-sprig", - sum = "h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=", - version = "v0.0.0-20230315185526-52ccab3ef572", - ) - go_repository( - name = "com_github_go_task_slim_sprig_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-task/slim-sprig/v3", - sum = "h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=", - version = "v3.0.0", - ) - go_repository( - name = "com_github_go_test_deep", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/go-test/deep", - sum = "h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_gobuffalo_logger", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gobuffalo/logger", - sum = "h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU=", - version = "v1.0.6", - ) - go_repository( - name = "com_github_gobuffalo_packd", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gobuffalo/packd", - sum = "h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_gobuffalo_packr_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gobuffalo/packr/v2", - sum = "h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY=", - version = "v2.8.3", - ) - go_repository( - name = "com_github_gobwas_glob", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gobwas/glob", - sum = "h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=", - version = "v0.2.3", - ) - go_repository( - name = "com_github_gobwas_httphead", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gobwas/httphead", - sum = "h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_gobwas_pool", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gobwas/pool", - sum = "h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=", - version = "v0.2.1", - ) - go_repository( - name = "com_github_gobwas_ws", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gobwas/ws", - sum = "h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk=", - version = "v1.2.1", - ) - go_repository( - name = "com_github_goccy_go_json", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/goccy/go-json", - sum = "h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM=", - version = "v0.9.7", - ) - go_repository( - name = "com_github_godbus_dbus_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/godbus/dbus/v5", - sum = "h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=", - version = "v5.1.0", - ) - go_repository( - name = "com_github_godror_godror", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/godror/godror", - sum = "h1:uxGAD7UdnNGjX5gf4NnEIGw0JAPTIFiqAyRBZTPKwXs=", - version = "v0.24.2", - ) - go_repository( - name = "com_github_gofrs_flock", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gofrs/flock", - sum = "h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=", - version = "v0.8.1", - ) - go_repository( - name = "com_github_gogo_protobuf", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gogo/protobuf", - sum = "h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=", - version = "v1.3.2", - ) - go_repository( - name = "com_github_golang_glog", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/golang/glog", - sum = "h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_golang_groupcache", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/golang/groupcache", - sum = "h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=", - version = "v0.0.0-20210331224755-41bb18bfe9da", - ) - go_repository( - name = "com_github_golang_jwt_jwt", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/golang-jwt/jwt", - sum = "h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=", - version = "v3.2.1+incompatible", - ) - go_repository( - name = "com_github_golang_jwt_jwt_v4", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/golang-jwt/jwt/v4", - sum = "h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=", - version = "v4.5.0", - ) - go_repository( - name = "com_github_golang_jwt_jwt_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/golang-jwt/jwt/v5", - sum = "h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=", - version = "v5.2.1", - ) - go_repository( - name = "com_github_golang_mock", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/golang/mock", - sum = "h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=", - version = "v1.7.0-rc.1", - ) - go_repository( - name = "com_github_golang_protobuf", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/golang/protobuf", - sum = "h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=", - version = "v1.5.4", - ) - go_repository( - name = "com_github_golang_snappy", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/golang/snappy", - sum = "h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=", - version = "v0.0.4", - ) - go_repository( - name = "com_github_golang_sql_civil", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/golang-sql/civil", - sum = "h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=", - version = "v0.0.0-20190719163853-cb61b32ac6fe", - ) - go_repository( - name = "com_github_gomodule_redigo", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gomodule/redigo", - sum = "h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=", - version = "v1.8.2", - ) - go_repository( - name = "com_github_google_btree", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/btree", - sum = "h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=", - version = "v1.1.2", - ) - go_repository( - name = "com_github_google_cadvisor", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/cadvisor", - sum = "h1:1PYeiORXmcFYi609M4Qvq5IzcvcVaWgYxDt78uH8jYA=", - version = "v0.49.0", - ) - go_repository( - name = "com_github_google_cel_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/cel-go", - sum = "h1:j9m730pMZt1Fc4oKhCLUHfjj6527LuhYcYw0Rl8gqto=", - version = "v0.17.8", - ) - go_repository( - name = "com_github_google_certificate_transparency_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/certificate-transparency-go", - sum = "h1:LGYKkgZF7satzgTak9R4yzfJXEeYVAjV6/EAEJOf1to=", - version = "v1.1.8", - ) - go_repository( - name = "com_github_google_gnostic_models", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/gnostic-models", - sum = "h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=", - version = "v0.6.8", - ) - go_repository( - name = "com_github_google_go_attestation", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-attestation", - sum = "h1:jqtOrLk5MNdliTKjPbIPrAaRKJaKW+0LIU2n/brJYms=", - version = "v0.5.1", - ) - go_repository( - name = "com_github_google_go_cmdtest", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-cmdtest", - sum = "h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU=", - version = "v0.4.1-0.20220921163831-55ab3332a786", - ) - go_repository( - name = "com_github_google_go_cmp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-cmp", - sum = "h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=", - version = "v0.6.0", - ) - go_repository( - name = "com_github_google_go_configfs_tsm", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-configfs-tsm", - sum = "h1:YnJ9rXIOj5BYD7/0DNnzs8AOp7UcvjfTvt215EWcs98=", - version = "v0.2.2", - ) - go_repository( - name = "com_github_google_go_containerregistry", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-containerregistry", - sum = "h1:uIsMRBV7m/HDkDxE/nXMnv1q+lOOSPlQ/ywc5JbB8Ic=", - version = "v0.19.0", - ) - go_repository( - name = "com_github_google_go_licenses", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-licenses", - sum = "h1:MM+VCXf0slYkpWO0mECvdYDVCxZXIQNal5wqUIXEZ/A=", - version = "v1.6.0", - ) - go_repository( - name = "com_github_google_go_pkcs11", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-pkcs11", - sum = "h1:OF1IPgv+F4NmqmJ98KTjdN97Vs1JxDPB3vbmYzV2dpk=", - version = "v0.2.1-0.20230907215043-c6f79328ddf9", - ) - go_repository( - name = "com_github_google_go_replayers_httpreplay", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-replayers/httpreplay", - sum = "h1:H91sIMlt1NZzN7R+/ASswyouLJfW0WLW7fhyUFvDEkY=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_google_go_sev_guest", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-sev-guest", - sum = "h1:gnww4U8fHV5DCPz4gykr1s8SEX1fFNcxCBy+vvXN24k=", - version = "v0.11.1", - ) - go_repository( - name = "com_github_google_go_tdx_guest", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-tdx-guest", - sum = "h1:gl0KvjdsD4RrJzyLefDOvFOUH3NAJri/3qvaL5m83Iw=", - version = "v0.3.1", - ) - go_repository( - name = "com_github_google_go_tpm", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-tpm", - sum = "h1:gfGQAIxsEEAuYuFvjCGpDnTwisMJOz+rUfJMkk4yTmc=", - version = "v0.9.1-0.20240510201744-5c2f0887e003", - ) - go_repository( - name = "com_github_google_go_tpm_tools", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-tpm-tools", - # keep - patches = [ - "//3rdparty/bazel/com_github_google_go_tpm_tools:com_github_google_go_tpm_tools.patch", - "//3rdparty/bazel/com_github_google_go_tpm_tools:ms_tpm_20_ref.patch", - "//3rdparty/bazel/com_github_google_go_tpm_tools:include.patch", - ], - sum = "h1:oiQfAIkc6xTy9Fl5NKTeTJkBTlXdHsxAofmQyxBKY98=", - version = "v0.4.4", - ) - go_repository( - name = "com_github_google_go_tspi", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/go-tspi", - sum = "h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus=", - version = "v0.3.0", - ) - go_repository( - name = "com_github_google_gofuzz", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/gofuzz", - sum = "h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_google_goterm", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/goterm", - sum = "h1:CVuJwN34x4xM2aT4sIKhmeib40NeBPhRihNjQmpJsA4=", - version = "v0.0.0-20200907032337-555d40f16ae2", - ) - go_repository( - name = "com_github_google_keep_sorted", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/keep-sorted", - sum = "h1:UNJGKBtOg4m4rgTYCpkBh0WBI2UTLm+xNC1lZvfQpp0=", - version = "v0.4.0", - ) - go_repository( - name = "com_github_google_licenseclassifier", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/licenseclassifier", - sum = "h1:TJsAqW6zLRMDTyGmc9TPosfn9OyVlHs8Hrn3pY6ONSY=", - version = "v0.0.0-20210722185704-3043a050f148", - ) - go_repository( - name = "com_github_google_logger", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/logger", - sum = "h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_google_martian", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/martian", - sum = "h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=", - version = "v2.1.0+incompatible", - ) - go_repository( - name = "com_github_google_martian_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/martian/v3", - sum = "h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=", - version = "v3.3.2", - ) - go_repository( - name = "com_github_google_pprof", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/pprof", - sum = "h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=", - version = "v0.0.0-20240424215950-a892ee059fd6", - ) - go_repository( - name = "com_github_google_renameio", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/renameio", - sum = "h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_google_renameio_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/renameio/v2", - sum = "h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=", - version = "v2.0.0", - ) - go_repository( - name = "com_github_google_rpmpack", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/rpmpack", - sum = "h1:LoQuqlw6kHRwg25n3M0xtYrW+z2pTkR0ae1xx11hRw8=", - version = "v0.6.0", - ) - go_repository( - name = "com_github_google_s2a_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/s2a-go", - sum = "h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=", - version = "v0.1.7", - ) - go_repository( - name = "com_github_google_shlex", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/shlex", - sum = "h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=", - version = "v0.0.0-20191202100458-e7afc7fbc510", - ) - go_repository( - name = "com_github_google_trillian", - build_file_generation = "on", - build_file_name = "", # keep - build_file_proto_mode = "disable_global", - importpath = "github.com/google/trillian", - sum = "h1:jMBeDBIkINFvS2n6oV5maDqfRlxREAc6CW9QYWQ0qT4=", - version = "v1.6.0", - ) - go_repository( - name = "com_github_google_uuid", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/uuid", - sum = "h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=", - version = "v1.6.0", - ) - go_repository( - name = "com_github_google_wire", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/google/wire", - sum = "h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI=", - version = "v0.6.0", - ) - go_repository( - name = "com_github_googleapis_enterprise_certificate_proxy", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/googleapis/enterprise-certificate-proxy", - sum = "h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=", - version = "v0.3.2", - ) - go_repository( - name = "com_github_googleapis_gax_go_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/googleapis/gax-go/v2", - sum = "h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg=", - version = "v2.12.4", - ) - go_repository( - name = "com_github_googleapis_go_type_adapters", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/googleapis/go-type-adapters", - sum = "h1:9XdMn+d/G57qq1s8dNc5IesGCXHf6V2HZ2JwRxfA2tA=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_googleapis_google_cloud_go_testing", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/googleapis/google-cloud-go-testing", - sum = "h1:zC34cGQu69FG7qzJ3WiKW244WfhDC3xxYMeNOX2gtUQ=", - version = "v0.0.0-20210719221736-1c9a4c676720", - ) - go_repository( - name = "com_github_googlecloudplatform_k8s_cloud_provider", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/GoogleCloudPlatform/k8s-cloud-provider", - sum = "h1:Heo1J/ttaQFgGJSVnCZquy3e5eH5j1nqxBuomztB3P0=", - version = "v1.18.1-0.20220218231025-f11817397a1b", - ) - go_repository( - name = "com_github_gophercloud_gophercloud", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gophercloud/gophercloud", - sum = "h1:ls0O747DIq1D8SUHc7r2vI8BFbMLeLFuENaAIfEx7OM=", - version = "v1.11.0", - ) - go_repository( - name = "com_github_gophercloud_utils", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gophercloud/utils", - sum = "h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE=", - version = "v0.0.0-20231010081019-80377eca5d56", - ) - go_repository( - name = "com_github_gorilla_handlers", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gorilla/handlers", - sum = "h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=", - version = "v1.5.1", - ) - go_repository( - name = "com_github_gorilla_mux", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gorilla/mux", - sum = "h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=", - version = "v1.8.1", - ) - go_repository( - name = "com_github_gorilla_websocket", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gorilla/websocket", - sum = "h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=", - version = "v1.5.0", - ) - go_repository( - name = "com_github_gosuri_uitable", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gosuri/uitable", - sum = "h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=", - version = "v0.0.4", - ) - go_repository( - name = "com_github_gregjones_httpcache", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/gregjones/httpcache", - sum = "h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=", - version = "v0.0.0-20180305231024-9cad4c3443a7", - ) - go_repository( - name = "com_github_grpc_ecosystem_go_grpc_middleware", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/grpc-ecosystem/go-grpc-middleware", - sum = "h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=", - version = "v1.4.0", - ) - go_repository( - name = "com_github_grpc_ecosystem_go_grpc_middleware_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/grpc-ecosystem/go-grpc-middleware/v2", - sum = "h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=", - version = "v2.1.0", - ) - go_repository( - name = "com_github_grpc_ecosystem_go_grpc_prometheus", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/grpc-ecosystem/go-grpc-prometheus", - sum = "h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_grpc_ecosystem_grpc_gateway", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/grpc-ecosystem/grpc-gateway", - sum = "h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=", - version = "v1.16.0", - ) - go_repository( - name = "com_github_grpc_ecosystem_grpc_gateway_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/grpc-ecosystem/grpc-gateway/v2", - sum = "h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is=", - version = "v2.19.1", - ) - go_repository( - name = "com_github_hashicorp_cli", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/cli", - sum = "h1:CMOV+/LJfL1tXCOKrgAX0uRKnzjj/mpmqNXloRSy2K8=", - version = "v1.1.6", - ) - go_repository( - name = "com_github_hashicorp_errwrap", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/errwrap", - sum = "h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_hashicorp_go_checkpoint", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-checkpoint", - sum = "h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=", - version = "v0.5.0", - ) - go_repository( - name = "com_github_hashicorp_go_cleanhttp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-cleanhttp", - sum = "h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=", - version = "v0.5.2", - ) - go_repository( - name = "com_github_hashicorp_go_cty", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-cty", - sum = "h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI=", - version = "v1.4.1-0.20200414143053-d3edf31b6320", - ) - go_repository( - name = "com_github_hashicorp_go_hclog", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-hclog", - sum = "h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I=", - version = "v1.6.2", - ) - go_repository( - name = "com_github_hashicorp_go_kms_wrapping_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-kms-wrapping/v2", - sum = "h1:WZeXfD26QMWYC35at25KgE021SF9L3u9UMHK8fJAdV0=", - version = "v2.0.16", - ) - go_repository( - name = "com_github_hashicorp_go_kms_wrapping_wrappers_awskms_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2", - sum = "h1:qdxeZvDMRGZ3YSE4Oz0Pp7WUSUn5S6cWZguEOkEVL50=", - version = "v2.0.9", - ) - go_repository( - name = "com_github_hashicorp_go_kms_wrapping_wrappers_azurekeyvault_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2", - sum = "h1:/7SKkYIhA8cr3l8m1EKT6Q90bPoSVqqVBuQ6HgoMIkw=", - version = "v2.0.11", - ) - go_repository( - name = "com_github_hashicorp_go_kms_wrapping_wrappers_gcpckms_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2", - sum = "h1:PCqWzT/Hii0KL07JsBZ3lJbv/wx02IAHYlhWQq8rxRY=", - version = "v2.0.12", - ) - go_repository( - name = "com_github_hashicorp_go_multierror", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-multierror", - sum = "h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_hashicorp_go_plugin", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-plugin", - sum = "h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A=", - version = "v1.6.0", - ) - go_repository( - name = "com_github_hashicorp_go_retryablehttp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-retryablehttp", - sum = "h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=", - version = "v0.7.5", - ) - go_repository( - name = "com_github_hashicorp_go_rootcerts", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-rootcerts", - sum = "h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=", - version = "v1.0.2", - ) - go_repository( - name = "com_github_hashicorp_go_secure_stdlib_awsutil", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-secure-stdlib/awsutil", - sum = "h1:W9WN8p6moV1fjKLkeqEgkAMu5rauy9QeYDAmIaPuuiA=", - version = "v0.1.6", - ) - go_repository( - name = "com_github_hashicorp_go_secure_stdlib_parseutil", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-secure-stdlib/parseutil", - sum = "h1:UpiO20jno/eV1eVZcxqWnUohyKRe1g8FPV/xH1s/2qs=", - version = "v0.1.7", - ) - go_repository( - name = "com_github_hashicorp_go_secure_stdlib_strutil", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-secure-stdlib/strutil", - sum = "h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=", - version = "v0.1.2", - ) - go_repository( - name = "com_github_hashicorp_go_sockaddr", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-sockaddr", - sum = "h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=", - version = "v1.0.2", - ) - go_repository( - name = "com_github_hashicorp_go_uuid", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-uuid", - sum = "h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=", - version = "v1.0.3", - ) - go_repository( - name = "com_github_hashicorp_go_version", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/go-version", - sum = "h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=", - version = "v1.6.0", - ) - go_repository( - name = "com_github_hashicorp_golang_lru", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/golang-lru", - sum = "h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=", - version = "v0.5.4", - ) - go_repository( - name = "com_github_hashicorp_hc_install", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/hc-install", - sum = "h1:QLqlM56/+SIIGvGcfFiwMY3z5WGXT066suo/v9Km8e0=", - version = "v0.6.4", - ) - go_repository( - name = "com_github_hashicorp_hcl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/hcl", - sum = "h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_hashicorp_hcl_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/hcl/v2", - sum = "h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc=", - version = "v2.20.1", - ) - go_repository( - name = "com_github_hashicorp_logutils", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/logutils", - sum = "h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_hashicorp_terraform_exec", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/terraform-exec", - sum = "h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8JyYF3vpnuEo=", - version = "v0.20.0", - ) - go_repository( - name = "com_github_hashicorp_terraform_json", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/terraform-json", - sum = "h1:9NQxbLNqPbEMze+S6+YluEdXgJmhQykRyRNd+zTI05U=", - version = "v0.21.0", - ) - go_repository( - name = "com_github_hashicorp_terraform_plugin_framework", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/terraform-plugin-framework", - sum = "h1:P07qy8RKLcoBkCrY2RHJer5AEvJnDuXomBgou6fD8kI=", - version = "v1.8.0", - ) - go_repository( - name = "com_github_hashicorp_terraform_plugin_framework_validators", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/terraform-plugin-framework-validators", - sum = "h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc=", - version = "v0.12.0", - ) - go_repository( - name = "com_github_hashicorp_terraform_plugin_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/terraform-plugin-go", - sum = "h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co=", - version = "v0.23.0", - ) - go_repository( - name = "com_github_hashicorp_terraform_plugin_log", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/terraform-plugin-log", - sum = "h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=", - version = "v0.9.0", - ) - go_repository( - name = "com_github_hashicorp_terraform_plugin_sdk_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/terraform-plugin-sdk/v2", - sum = "h1:qHprzXy/As0rxedphECBEQAh3R4yp6pKksKHcqZx5G8=", - version = "v2.33.0", - ) - go_repository( - name = "com_github_hashicorp_terraform_plugin_testing", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/terraform-plugin-testing", - sum = "h1:I6aeCyZ30z4NiI3tzyDoO6fS7YxP5xSL1ceOon3gTe8=", - version = "v1.7.0", - ) - go_repository( - name = "com_github_hashicorp_terraform_registry_address", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/terraform-registry-address", - sum = "h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI=", - version = "v0.2.3", - ) - go_repository( - name = "com_github_hashicorp_terraform_svchost", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/terraform-svchost", - sum = "h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ=", - version = "v0.1.1", - ) - go_repository( - name = "com_github_hashicorp_vault_api", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/vault/api", - sum = "h1:7YkCTE5Ni90TcmYHDBExdt4WGJxhpzaHqR6uGbQb/rE=", - version = "v1.12.2", - ) - go_repository( - name = "com_github_hashicorp_yamux", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hashicorp/yamux", - sum = "h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=", - version = "v0.1.1", - ) - go_repository( - name = "com_github_hexops_gotextdiff", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hexops/gotextdiff", - sum = "h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=", - version = "v1.0.3", - ) - go_repository( - name = "com_github_howeyc_gopass", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/howeyc/gopass", - sum = "h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM=", - version = "v0.0.0-20210920133722-c8aef6fb66ef", - ) - go_repository( - name = "com_github_hpcloud_tail", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hpcloud/tail", - sum = "h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_huandu_xstrings", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/huandu/xstrings", - sum = "h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=", - version = "v1.4.0", - ) - go_repository( - name = "com_github_hugelgupf_vmtest", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/hugelgupf/vmtest", - sum = "h1:aa9+0fjwoGotyC8A3QjdITMAX89g/+qvDAhKPrK1NKE=", - version = "v0.0.0-20240110072021-f6f07acb7aa1", - ) - go_repository( - name = "com_github_ianlancetaylor_demangle", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ianlancetaylor/demangle", - sum = "h1:KwWnWVWCNtNq/ewIX7HIKnELmEx2nDP42yskD/pi7QE=", - version = "v0.0.0-20240312041847-bd984b5ce465", - ) - go_repository( - name = "com_github_imdario_mergo", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/imdario/mergo", - sum = "h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=", - version = "v0.3.15", - ) - go_repository( - name = "com_github_in_toto_in_toto_golang", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/in-toto/in-toto-golang", - sum = "h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=", - version = "v0.9.0", - ) - go_repository( - name = "com_github_inconshreveable_mousetrap", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/inconshreveable/mousetrap", - sum = "h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_insomniacslk_dhcp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/insomniacslk/dhcp", - sum = "h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA=", - version = "v0.0.0-20231206064809-8c70d406f6d2", - ) - go_repository( - name = "com_github_intel_goresctrl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/intel/goresctrl", - sum = "h1:K2D3GOzihV7xSBedGxONSlaw/un1LZgWsc9IfqipN4c=", - version = "v0.3.0", - ) - go_repository( - name = "com_github_ishidawataru_sctp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ishidawataru/sctp", - sum = "h1:i2fYnDurfLlJH8AyyMOnkLHnHeP8Ff/DDpuZA/D3bPo=", - version = "v0.0.0-20230406120618-7ff4192f6ff2", - ) - go_repository( - name = "com_github_jbenet_go_context", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jbenet/go-context", - sum = "h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=", - version = "v0.0.0-20150711004518-d14ea06fba99", - ) - go_repository( - name = "com_github_jedisct1_go_minisign", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jedisct1/go-minisign", - sum = "h1:ZGiXF8sz7PDk6RgkP+A/SFfUD0ZR/AgG6SpRNEDKZy8=", - version = "v0.0.0-20211028175153-1c139d1cc84b", - ) - go_repository( - name = "com_github_jeffashton_win_pdh", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/JeffAshton/win_pdh", - sum = "h1:UKkYhof1njT1/xq4SEg5z+VpTgjmNeHwPGRQl7takDI=", - version = "v0.0.0-20161109143554-76bb4ee9f0ab", - ) - go_repository( - name = "com_github_jellydator_ttlcache_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jellydator/ttlcache/v3", - sum = "h1:6lqVJ8X3ZaUwvzENqPAobDsXNExfUJd61u++uW8a3LE=", - version = "v3.2.0", - ) - go_repository( - name = "com_github_jessevdk_go_flags", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jessevdk/go-flags", - sum = "h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=", - version = "v1.4.0", - ) - go_repository( - name = "com_github_jhump_protoreflect", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jhump/protoreflect", - sum = "h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls=", - version = "v1.15.3", - ) - go_repository( - name = "com_github_jmespath_go_jmespath", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jmespath/go-jmespath", - sum = "h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=", - version = "v0.4.0", - ) - go_repository( - name = "com_github_jmespath_go_jmespath_internal_testify", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jmespath/go-jmespath/internal/testify", - sum = "h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=", - version = "v1.5.1", - ) - go_repository( - name = "com_github_jmhodges_clock", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jmhodges/clock", - sum = "h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_jmoiron_sqlx", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jmoiron/sqlx", - sum = "h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=", - version = "v1.3.5", - ) - go_repository( - name = "com_github_jonboulle_clockwork", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jonboulle/clockwork", - sum = "h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=", - version = "v0.4.0", - ) - go_repository( - name = "com_github_josephspurrier_goversioninfo", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/josephspurrier/goversioninfo", - sum = "h1:Puhl12NSHUSALHSuzYwPYQkqa2E1+7SrtAPJorKK0C8=", - version = "v1.4.0", - ) - go_repository( - name = "com_github_josharian_intern", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/josharian/intern", - sum = "h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_josharian_native", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/josharian/native", - sum = "h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_jpillora_backoff", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jpillora/backoff", - sum = "h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_jsimonetti_rtnetlink", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jsimonetti/rtnetlink", - sum = "h1:JfD4jthWBqZMEffc5RjgmlzpYttAVw1sdnmiNaPO3hE=", - version = "v1.4.1", - ) - go_repository( - name = "com_github_json_iterator_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/json-iterator/go", - sum = "h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=", - version = "v1.1.12", - ) - go_repository( - name = "com_github_jstemmer_go_junit_report", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/jstemmer/go-junit-report", - sum = "h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=", - version = "v0.9.1", - ) - go_repository( - name = "com_github_julienschmidt_httprouter", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/julienschmidt/httprouter", - sum = "h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=", - version = "v1.3.0", - ) - go_repository( - name = "com_github_k0kubun_go_ansi", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/k0kubun/go-ansi", - sum = "h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=", - version = "v0.0.0-20180517002512-3bf9e2903213", - ) - go_repository( - name = "com_github_karrick_godirwalk", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/karrick/godirwalk", - sum = "h1:b4kY7nqDdioR/6qnbHQyDvmA17u5G1cZ6J+CZXwSWoI=", - version = "v1.17.0", - ) - go_repository( - name = "com_github_katexochen_sh_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/katexochen/sh/v3", - sum = "h1:/BNMhF21b6Q4vcB6YyGtxcGGcdT3NCTiUBNBYcI3EmI=", - version = "v3.8.0", - ) - go_repository( - name = "com_github_kevinburke_ssh_config", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/kevinburke/ssh_config", - sum = "h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_kisielk_errcheck", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/kisielk/errcheck", - sum = "h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY=", - version = "v1.5.0", - ) - go_repository( - name = "com_github_kisielk_gotool", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/kisielk/gotool", - sum = "h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_klauspost_compress", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/klauspost/compress", - sum = "h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=", - version = "v1.17.4", - ) - go_repository( - name = "com_github_klauspost_cpuid_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/klauspost/cpuid/v2", - sum = "h1:g0I61F2K2DjRHz1cnxlkNSBIaePVoJIjjnHui8QHbiw=", - version = "v2.0.4", - ) - go_repository( - name = "com_github_klauspost_pgzip", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/klauspost/pgzip", - sum = "h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=", - version = "v1.2.6", - ) - go_repository( - name = "com_github_konsorten_go_windows_terminal_sequences", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/konsorten/go-windows-terminal-sequences", - sum = "h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_kr_fs", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/kr/fs", - sum = "h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_kr_logfmt", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/kr/logfmt", - sum = "h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=", - version = "v0.0.0-20140226030751-b84e30acd515", - ) - go_repository( - name = "com_github_kr_pretty", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/kr/pretty", - sum = "h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=", - version = "v0.3.1", - ) - go_repository( - name = "com_github_kr_pty", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/kr/pty", - sum = "h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=", - version = "v1.1.8", - ) - go_repository( - name = "com_github_kr_text", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/kr/text", - sum = "h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=", - version = "v0.2.0", - ) - go_repository( - name = "com_github_kylelemons_godebug", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/kylelemons/godebug", - sum = "h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_lann_builder", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/lann/builder", - sum = "h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=", - version = "v0.0.0-20180802200727-47ae307949d0", - ) - go_repository( - name = "com_github_lann_ps", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/lann/ps", - sum = "h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=", - version = "v0.0.0-20150810152359-62de8c46ede0", - ) - go_repository( - name = "com_github_leodido_go_urn", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/leodido/go-urn", - sum = "h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=", - version = "v1.4.0", - ) - go_repository( - name = "com_github_lestrrat_go_backoff_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/lestrrat-go/backoff/v2", - sum = "h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=", - version = "v2.0.8", - ) - go_repository( - name = "com_github_lestrrat_go_blackmagic", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/lestrrat-go/blackmagic", - sum = "h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_lestrrat_go_httpcc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/lestrrat-go/httpcc", - sum = "h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_lestrrat_go_iter", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/lestrrat-go/iter", - sum = "h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_lestrrat_go_jwx", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/lestrrat-go/jwx", - sum = "h1:tAx93jN2SdPvFn08fHNAhqFJazn5mBBOB8Zli0g0otA=", - version = "v1.2.25", - ) - go_repository( - name = "com_github_lestrrat_go_option", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/lestrrat-go/option", - sum = "h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_letsencrypt_borp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/letsencrypt/borp", - sum = "h1:xS2U6PQYRURk61YN4Y5xvyLbQVyAP/8fpE6hJZdwEWs=", - version = "v0.0.0-20230707160741-6cc6ce580243", - ) - go_repository( - name = "com_github_letsencrypt_boulder", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/letsencrypt/boulder", - sum = "h1:RLTpX495BXToqxpM90Ws4hXEo4Wfh81jr9DX1n/4WOo=", - version = "v0.0.0-20230907030200-6d76a0f91e1e", - ) - go_repository( - name = "com_github_letsencrypt_challtestsrv", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/letsencrypt/challtestsrv", - sum = "h1:Lzv4jM+wSgVMCeO5a/F/IzSanhClstFMnX6SfrAJXjI=", - version = "v1.2.1", - ) - go_repository( - name = "com_github_letsencrypt_pkcs11key_v4", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/letsencrypt/pkcs11key/v4", - sum = "h1:qLc/OznH7xMr5ARJgkZCCWk+EomQkiNTOoOF5LAgagc=", - version = "v4.0.0", - ) - go_repository( - name = "com_github_letsencrypt_validator_v10", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/letsencrypt/validator/v10", - sum = "h1:HGFsIltYMUiB5eoFSowFzSoXkocM2k9ctmJ57QMGjys=", - version = "v10.0.0-20230215210743-a0c7dfc17158", - ) - go_repository( - name = "com_github_lib_pq", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/lib/pq", - sum = "h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=", - version = "v1.10.9", - ) - go_repository( - name = "com_github_libopenstorage_openstorage", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/libopenstorage/openstorage", - sum = "h1:GLPam7/0mpdP8ZZtKjbfcXJBTIA/T1O6CBErVEFEyIM=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_liggitt_tabwriter", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/liggitt/tabwriter", - sum = "h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=", - version = "v0.0.0-20181228230101-89fcab3d43de", - ) - go_repository( - name = "com_github_linuxkit_virtsock", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/linuxkit/virtsock", - sum = "h1:jUp75lepDg0phMUJBCmvaeFDldD2N3S1lBuPwUTszio=", - version = "v0.0.0-20201010232012-f8cee7dfc7a3", - ) - go_repository( - name = "com_github_lithammer_dedent", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/lithammer/dedent", - sum = "h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_magiconair_properties", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/magiconair/properties", - sum = "h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=", - version = "v1.8.7", - ) - go_repository( - name = "com_github_mailru_easyjson", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mailru/easyjson", - sum = "h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=", - version = "v0.7.7", - ) - go_repository( - name = "com_github_makenowjust_heredoc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/MakeNowJust/heredoc", - sum = "h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_markbates_errx", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/markbates/errx", - sum = "h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_markbates_oncer", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/markbates/oncer", - sum = "h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_markbates_safe", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/markbates/safe", - sum = "h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_martinjungblut_go_cryptsetup", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/martinjungblut/go-cryptsetup", - patches = [ - "//3rdparty/bazel/com_github_martinjungblut_go_cryptsetup:com_github_martinjungblut_go_cryptsetup.patch", # keep - ], - replace = "github.com/daniel-weisse/go-cryptsetup", - sum = "h1:ToajP6trZoiqlZ3Z4uoG1P02/wtqSw1AcowOXOYjATk=", - version = "v0.0.0-20230705150314-d8c07bd1723c", - ) - go_repository( - name = "com_github_masterminds_goutils", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Masterminds/goutils", - sum = "h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_masterminds_semver_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Masterminds/semver/v3", - sum = "h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=", - version = "v3.2.1", - ) - go_repository( - name = "com_github_masterminds_sprig_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Masterminds/sprig/v3", - sum = "h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=", - version = "v3.2.3", - ) - go_repository( - name = "com_github_masterminds_squirrel", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Masterminds/squirrel", - sum = "h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=", - version = "v1.5.4", - ) - go_repository( - name = "com_github_masterminds_vcs", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Masterminds/vcs", - sum = "h1:IIA2aBdXvfbIM+yl/eTnL4hb1XwdpvuQLglAix1gweE=", - version = "v1.13.3", - ) - go_repository( - name = "com_github_mattn_go_colorable", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mattn/go-colorable", - sum = "h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=", - version = "v0.1.13", - ) - go_repository( - name = "com_github_mattn_go_isatty", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mattn/go-isatty", - sum = "h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=", - version = "v0.0.20", - ) - go_repository( - name = "com_github_mattn_go_oci8", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mattn/go-oci8", - sum = "h1:aEUDxNAyDG0tv8CA3TArnDQNyc4EhnWlsfxRgDHABHM=", - version = "v0.1.1", - ) - go_repository( - name = "com_github_mattn_go_runewidth", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mattn/go-runewidth", - sum = "h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=", - version = "v0.0.13", - ) - go_repository( - name = "com_github_mattn_go_shellwords", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mattn/go-shellwords", - sum = "h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=", - version = "v1.0.12", - ) - go_repository( - name = "com_github_mattn_go_sqlite3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mattn/go-sqlite3", - sum = "h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=", - version = "v1.14.22", - ) - go_repository( - name = "com_github_matttproud_golang_protobuf_extensions", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/matttproud/golang_protobuf_extensions", - sum = "h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=", - version = "v1.0.4", - ) - go_repository( - name = "com_github_mdlayher_ethtool", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mdlayher/ethtool", - sum = "h1:XAWHsmKhyPOo42qq/yTPb0eFBGUKKTR1rE0dVrWVQ0Y=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_mdlayher_genetlink", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mdlayher/genetlink", - sum = "h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=", - version = "v1.3.2", - ) - go_repository( - name = "com_github_mdlayher_netlink", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mdlayher/netlink", - sum = "h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=", - version = "v1.7.2", - ) - go_repository( - name = "com_github_mdlayher_packet", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mdlayher/packet", - sum = "h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY=", - version = "v1.1.2", - ) - go_repository( - name = "com_github_mdlayher_socket", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mdlayher/socket", - sum = "h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=", - version = "v0.5.1", - ) - go_repository( - name = "com_github_microsoft_go_winio", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Microsoft/go-winio", - sum = "h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=", - version = "v0.6.1", - ) - go_repository( - name = "com_github_microsoft_hcsshim", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Microsoft/hcsshim", - sum = "h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=", - version = "v0.11.4", - ) - go_repository( - name = "com_github_miekg_dns", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/miekg/dns", - sum = "h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=", - version = "v1.1.55", - ) - go_repository( - name = "com_github_miekg_pkcs11", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/miekg/pkcs11", - sum = "h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_minio_sha256_simd", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/minio/sha256-simd", - sum = "h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_mistifyio_go_zfs", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mistifyio/go-zfs", - sum = "h1:aKW/4cBs+yK6gpqU3K/oIwk9Q/XICqd3zOX/UFuvqmk=", - version = "v2.1.2-0.20190413222219-f784269be439+incompatible", - ) - go_repository( - name = "com_github_mistifyio_go_zfs_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mistifyio/go-zfs/v3", - sum = "h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU=", - version = "v3.0.1", - ) - go_repository( - name = "com_github_mitchellh_cli", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mitchellh/cli", - sum = "h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng=", - version = "v1.1.5", - ) - go_repository( - name = "com_github_mitchellh_colorstring", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mitchellh/colorstring", - sum = "h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=", - version = "v0.0.0-20190213212951-d06e56a500db", - ) - go_repository( - name = "com_github_mitchellh_copystructure", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mitchellh/copystructure", - sum = "h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_mitchellh_go_homedir", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mitchellh/go-homedir", - sum = "h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_mitchellh_go_testing_interface", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mitchellh/go-testing-interface", - sum = "h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=", - version = "v1.14.1", - ) - go_repository( - name = "com_github_mitchellh_go_wordwrap", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mitchellh/go-wordwrap", - sum = "h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_mitchellh_mapstructure", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mitchellh/mapstructure", - sum = "h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=", - version = "v1.5.0", - ) - go_repository( - name = "com_github_mitchellh_reflectwalk", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mitchellh/reflectwalk", - sum = "h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=", - version = "v1.0.2", - ) - go_repository( - name = "com_github_moby_docker_image_spec", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/moby/docker-image-spec", - sum = "h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=", - version = "v1.3.1", - ) - go_repository( - name = "com_github_moby_ipvs", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/moby/ipvs", - sum = "h1:ONN4pGaZQgAx+1Scz5RvWV4Q7Gb+mvfRh3NsPS+1XQQ=", - version = "v1.1.0", - ) - go_repository( - name = "com_github_moby_locker", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/moby/locker", - sum = "h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=", - version = "v1.0.1", - ) - go_repository( - name = "com_github_moby_spdystream", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/moby/spdystream", - sum = "h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=", - version = "v0.2.0", - ) - go_repository( - name = "com_github_moby_sys_mountinfo", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/moby/sys/mountinfo", - sum = "h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=", - version = "v0.6.2", - ) - go_repository( - name = "com_github_moby_sys_sequential", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/moby/sys/sequential", - sum = "h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=", - version = "v0.5.0", - ) - go_repository( - name = "com_github_moby_sys_signal", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/moby/sys/signal", - sum = "h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=", - version = "v0.7.0", - ) - go_repository( - name = "com_github_moby_sys_symlink", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/moby/sys/symlink", - sum = "h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZc=", - version = "v0.2.0", - ) - go_repository( - name = "com_github_moby_sys_user", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/moby/sys/user", - sum = "h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_moby_term", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/moby/term", - sum = "h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=", - version = "v0.5.0", - ) - go_repository( - name = "com_github_modern_go_concurrent", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/modern-go/concurrent", - sum = "h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=", - version = "v0.0.0-20180306012644-bacd9c7ef1dd", - ) - go_repository( - name = "com_github_modern_go_reflect2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/modern-go/reflect2", - sum = "h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=", - version = "v1.0.2", - ) - go_repository( - name = "com_github_modocache_gover", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/modocache/gover", - sum = "h1:8Q0qkMVC/MmWkpIdlvZgcv2o2jrlF6zqVOh7W5YHdMA=", - version = "v0.0.0-20171022184752-b58185e213c5", - ) - go_repository( - name = "com_github_mohae_deepcopy", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mohae/deepcopy", - sum = "h1:e+l77LJOEqXTIQihQJVkA6ZxPOUmfPM5e4H7rcpgtSk=", - version = "v0.0.0-20170603005431-491d3605edfb", - ) - go_repository( - name = "com_github_monochromegane_go_gitignore", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/monochromegane/go-gitignore", - sum = "h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=", - version = "v0.0.0-20200626010858-205db1a8cc00", - ) - go_repository( - name = "com_github_montanaflynn_stats", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/montanaflynn/stats", - sum = "h1:r3y12KyNxj/Sb/iOE46ws+3mS1+MZca1wlHQFPsY/JU=", - version = "v0.7.0", - ) - go_repository( - name = "com_github_morikuni_aec", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/morikuni/aec", - sum = "h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_mr_tron_base58", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mr-tron/base58", - sum = "h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_mrunalp_fileutils", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mrunalp/fileutils", - sum = "h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q=", - version = "v0.5.1", - ) - go_repository( - name = "com_github_munnerz_goautoneg", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/munnerz/goautoneg", - sum = "h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=", - version = "v0.0.0-20191010083416-a7dc8b61c822", - ) - go_repository( - name = "com_github_mwitkow_go_conntrack", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mwitkow/go-conntrack", - sum = "h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=", - version = "v0.0.0-20190716064945-2f068394615f", - ) - go_repository( - name = "com_github_mxk_go_flowrate", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/mxk/go-flowrate", - sum = "h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=", - version = "v0.0.0-20140419014527-cca7078d478f", - ) - go_repository( - name = "com_github_nelsam_hel_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/nelsam/hel/v2", - sum = "h1:Z3TAKd9JS3BoKi6fW+d1bKD2Mf0FzTqDUEAwLWzYPRQ=", - version = "v2.3.3", - ) - go_repository( - name = "com_github_netflix_go_expect", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Netflix/go-expect", - sum = "h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=", - version = "v0.0.0-20220104043353-73e0943537d2", - ) - go_repository( - name = "com_github_niemeyer_pretty", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/niemeyer/pretty", - sum = "h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=", - version = "v0.0.0-20200227124842-a10e7caefd8e", - ) - go_repository( - name = "com_github_nytimes_gziphandler", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/NYTimes/gziphandler", - sum = "h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_oklog_run", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/oklog/run", - sum = "h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_oklog_ulid", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/oklog/ulid", - sum = "h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=", - version = "v1.3.1", - ) - go_repository( - name = "com_github_olareg_olareg", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/olareg/olareg", - sum = "h1:1I7mTStFqh+DqPG9rRjEhEallPi2MQg2uACGImFGS1Q=", - version = "v0.0.0-20240323210534-20ec9e4f6dd4", - ) - go_repository( - name = "com_github_olekukonko_tablewriter", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/olekukonko/tablewriter", - sum = "h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=", - version = "v0.0.5", - ) - go_repository( - name = "com_github_oneofone_xxhash", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/OneOfOne/xxhash", - sum = "h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=", - version = "v1.2.8", - ) - go_repository( - name = "com_github_onsi_ginkgo_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/onsi/ginkgo/v2", - sum = "h1:oJcvKpIb7/8uLpDDtnQuf18xVnwKp8DTD7DQ6gTd/MU=", - version = "v2.17.3", - ) - go_repository( - name = "com_github_onsi_gomega", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/onsi/gomega", - sum = "h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=", - version = "v1.33.1", - ) - go_repository( - name = "com_github_open_policy_agent_opa", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/open-policy-agent/opa", - sum = "h1:qocVAKyjrqMjCqsU02S/gHyLr4AQQ9xMtuV1kKnnyhM=", - version = "v0.42.2", - ) - go_repository( - name = "com_github_opencontainers_go_digest", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/opencontainers/go-digest", - sum = "h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_opencontainers_image_spec", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/opencontainers/image-spec", - sum = "h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU=", - version = "v1.1.0-rc6", - ) - go_repository( - name = "com_github_opencontainers_runc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/opencontainers/runc", - sum = "h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss=", - version = "v1.1.12", - ) - go_repository( - name = "com_github_opencontainers_runtime_spec", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/opencontainers/runtime-spec", - sum = "h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_opencontainers_runtime_tools", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/opencontainers/runtime-tools", - sum = "h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0=", - version = "v0.9.1-0.20221107090550-2e043c6bd626", - ) - go_repository( - name = "com_github_opencontainers_selinux", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/opencontainers/selinux", - sum = "h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=", - version = "v1.11.0", - ) - go_repository( - name = "com_github_opentracing_opentracing_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/opentracing/opentracing-go", - sum = "h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_otiai10_copy", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/otiai10/copy", - sum = "h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ=", - version = "v1.6.0", - ) - go_repository( - name = "com_github_otiai10_curr", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/otiai10/curr", - sum = "h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_otiai10_mint", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/otiai10/mint", - sum = "h1:VYWnrP5fXmz1MXvjuUvcBrXSjGE6xjON+axB/UrpO3E=", - version = "v1.3.2", - ) - go_repository( - name = "com_github_pborman_uuid", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pborman/uuid", - sum = "h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=", - version = "v1.2.1", - ) - go_repository( - name = "com_github_pelletier_go_buffruneio", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pelletier/go-buffruneio", - sum = "h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA=", - version = "v0.2.0", - ) - go_repository( - name = "com_github_pelletier_go_toml", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pelletier/go-toml", - sum = "h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=", - version = "v1.9.5", - ) - go_repository( - name = "com_github_pelletier_go_toml_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pelletier/go-toml/v2", - sum = "h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=", - version = "v2.1.0", - ) - go_repository( - name = "com_github_peterbourgon_diskv", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/peterbourgon/diskv", - sum = "h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=", - version = "v2.0.1+incompatible", - ) - go_repository( - name = "com_github_phayes_freeport", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/phayes/freeport", - sum = "h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=", - version = "v0.0.0-20220201140144-74d24b5ae9f5", - ) - go_repository( - name = "com_github_philhofer_fwd", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/philhofer/fwd", - sum = "h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_pierrec_lz4_v4", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pierrec/lz4/v4", - sum = "h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=", - version = "v4.1.14", - ) - go_repository( - name = "com_github_pjbgf_sha1cd", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pjbgf/sha1cd", - sum = "h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=", - version = "v0.3.0", - ) - go_repository( - name = "com_github_pkg_browser", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pkg/browser", - sum = "h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=", - version = "v0.0.0-20240102092130-5ac0b6a4141c", - ) - go_repository( - name = "com_github_pkg_diff", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pkg/diff", - sum = "h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=", - version = "v0.0.0-20210226163009-20ebb0f2a09e", - ) - go_repository( - name = "com_github_pkg_errors", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pkg/errors", - sum = "h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=", - version = "v0.9.1", - ) - go_repository( - name = "com_github_pkg_sftp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pkg/sftp", - sum = "h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=", - version = "v1.13.6", - ) - go_repository( - name = "com_github_planetscale_vtprotobuf", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/planetscale/vtprotobuf", - sum = "h1:nBeETjudeJ5ZgBHUz1fVHvbqUKnYOXNhsIEabROxmNA=", - version = "v0.6.0", - ) - go_repository( - name = "com_github_pmezard_go_difflib", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pmezard/go-difflib", - sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_posener_complete", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/posener/complete", - sum = "h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=", - version = "v1.2.3", - ) - go_repository( - name = "com_github_poy_onpar", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/poy/onpar", - sum = "h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY=", - version = "v1.1.2", - ) - go_repository( - name = "com_github_pquerna_cachecontrol", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/pquerna/cachecontrol", - sum = "h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_prometheus_client_golang", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/prometheus/client_golang", - sum = "h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=", - version = "v1.19.0", - ) - go_repository( - name = "com_github_prometheus_client_model", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/prometheus/client_model", - sum = "h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=", - version = "v0.5.0", - ) - go_repository( - name = "com_github_prometheus_common", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/prometheus/common", - sum = "h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=", - version = "v0.48.0", - ) - go_repository( - name = "com_github_prometheus_procfs", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/prometheus/procfs", - sum = "h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=", - version = "v0.12.0", - ) - go_repository( - name = "com_github_prometheus_prometheus", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/prometheus/prometheus", - sum = "h1:jWcnuQHz1o1Wu3MZ6nMJDuTI0kU5yJp9pkxh8XEkNvI=", - version = "v0.47.2", - ) - go_repository( - name = "com_github_protonmail_go_crypto", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ProtonMail/go-crypto", - sum = "h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg=", - version = "v1.1.0-alpha.2", - ) - go_repository( - name = "com_github_protonmail_go_mime", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ProtonMail/go-mime", - sum = "h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k=", - version = "v0.0.0-20230322103455-7d82a3887f2f", - ) - go_repository( - name = "com_github_protonmail_gopenpgp_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ProtonMail/gopenpgp/v2", - sum = "h1:STOY3vgES59gNgoOt2w0nyHBjKViB/qSg7NjbQWPJkA=", - version = "v2.7.5", - ) - go_repository( - name = "com_github_rcrowley_go_metrics", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/rcrowley/go-metrics", - sum = "h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=", - version = "v0.0.0-20200313005456-10cdbea86bc0", - ) - go_repository( - name = "com_github_redis_go_redis_v9", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/redis/go-redis/v9", - sum = "h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=", - version = "v9.5.1", - ) - go_repository( - name = "com_github_regclient_regclient", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/regclient/regclient", - sum = "h1:P+8L9fdOTCo6S6O0/vE/C47csVY5UW5CMEzVwENVbWA=", - version = "v0.6.0", - ) - go_repository( - name = "com_github_rivo_uniseg", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/rivo/uniseg", - sum = "h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=", - version = "v0.4.7", - ) - go_repository( - name = "com_github_robfig_cron_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/robfig/cron/v3", - sum = "h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=", - version = "v3.0.1", - ) - go_repository( - name = "com_github_rogpeppe_fastuuid", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/rogpeppe/fastuuid", - sum = "h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_rogpeppe_go_internal", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/rogpeppe/go-internal", - sum = "h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=", - version = "v1.12.0", - ) - go_repository( - name = "com_github_rs_cors", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/rs/cors", - sum = "h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo=", - version = "v1.10.1", - ) - go_repository( - name = "com_github_rs_xid", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/rs/xid", - sum = "h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=", - version = "v1.5.0", - ) - go_repository( - name = "com_github_rs_zerolog", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/rs/zerolog", - sum = "h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=", - version = "v1.31.0", - ) - go_repository( - name = "com_github_rubenv_sql_migrate", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/rubenv/sql-migrate", - sum = "h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0=", - version = "v1.5.2", - ) - go_repository( - name = "com_github_russross_blackfriday", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/russross/blackfriday", - sum = "h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=", - version = "v1.6.0", - ) - go_repository( - name = "com_github_russross_blackfriday_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/russross/blackfriday/v2", - sum = "h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=", - version = "v2.1.0", - ) - go_repository( - name = "com_github_ryanuber_go_glob", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ryanuber/go-glob", - sum = "h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_sagikazarmark_locafero", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sagikazarmark/locafero", - sum = "h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=", - version = "v0.4.0", - ) - go_repository( - name = "com_github_sagikazarmark_slog_shim", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sagikazarmark/slog-shim", - sum = "h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_samber_lo", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/samber/lo", - sum = "h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=", - version = "v1.38.1", - ) - go_repository( - name = "com_github_samber_slog_multi", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/samber/slog-multi", - sum = "h1:6BVH9uHGAsiGkbbtQgAOQJMpKgV8unMrHhhJaw+X1EQ=", - version = "v1.0.2", - ) - go_repository( - name = "com_github_santhosh_tekuri_jsonschema_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/santhosh-tekuri/jsonschema/v5", - sum = "h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=", - version = "v5.3.1", - ) - go_repository( - name = "com_github_sassoftware_relic", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sassoftware/relic", - sum = "h1:Pwyh1F3I0r4clFJXkSI8bOyJINGqpgjJU3DYAZeI05A=", - version = "v7.2.1+incompatible", - ) - go_repository( - name = "com_github_sassoftware_relic_v7", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sassoftware/relic/v7", - sum = "h1:rS44Lbv9G9eXsukknS4mSjIAuuX+lMq/FnStgmZlUv4=", - version = "v7.6.2", - ) - go_repository( - name = "com_github_schollz_progressbar_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/schollz/progressbar/v3", - sum = "h1:EducH6uNLIWsr560zSV1KrTeUb/wZGAHqyMFIEa99ks=", - version = "v3.14.2", - ) - go_repository( - name = "com_github_sebdah_goldie", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sebdah/goldie", - sum = "h1:9GNhIat69MSlz/ndaBg48vl9dF5fI+NBB6kfOxgfkMc=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_seccomp_libseccomp_golang", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/seccomp/libseccomp-golang", - sum = "h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY=", - version = "v0.10.0", - ) - go_repository( - name = "com_github_secure_systems_lab_go_securesystemslib", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/secure-systems-lab/go-securesystemslib", - sum = "h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA=", - version = "v0.8.0", - ) - go_repository( - name = "com_github_segmentio_ksuid", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/segmentio/ksuid", - sum = "h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=", - version = "v1.0.4", - ) - go_repository( - name = "com_github_sergi_go_diff", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sergi/go-diff", - sum = "h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=", - version = "v1.3.2-0.20230802210424-5b0b94c5c0d3", - ) - go_repository( - name = "com_github_shibumi_go_pathspec", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/shibumi/go-pathspec", - sum = "h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=", - version = "v1.3.0", - ) - go_repository( - name = "com_github_shopify_logrus_bugsnag", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Shopify/logrus-bugsnag", - sum = "h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=", - version = "v0.0.0-20171204204709-577dee27f20d", - ) - go_repository( - name = "com_github_shopspring_decimal", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/shopspring/decimal", - sum = "h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=", - version = "v1.3.1", - ) - go_repository( - name = "com_github_siderolabs_crypto", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/siderolabs/crypto", - sum = "h1:Q6EDBMR2Ub2oAZW5Xl8lrKB27bM3Sn8Gkfw3rngco5U=", - version = "v0.4.4", - ) - go_repository( - name = "com_github_siderolabs_gen", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/siderolabs/gen", - sum = "h1:VNpbmDLhkXp7qcSEkKk1Ee7vU2afs3xvHrWLGR2UuiY=", - version = "v0.4.8", - ) - go_repository( - name = "com_github_siderolabs_go_api_signature", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/siderolabs/go-api-signature", - sum = "h1:blqrZF1GM7TWgq7mY7CsR+yQ93u6az0Kf0mfsw+hvf0=", - version = "v0.3.2", - ) - go_repository( - name = "com_github_siderolabs_go_blockdevice", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/siderolabs/go-blockdevice", - sum = "h1:2bk4WpEEflGxjrNwp57ye24Pr+cYgAiAeNMWiQOuWbQ=", - version = "v0.4.7", - ) - go_repository( - name = "com_github_siderolabs_go_pointer", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/siderolabs/go-pointer", - sum = "h1:6TshPKep2doDQJAAtHUuHWXbca8ZfyRySjSBT/4GsMU=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_siderolabs_net", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/siderolabs/net", - sum = "h1:1bOgVay/ijPkJz4qct98nHsiB/ysLQU0KLoBC4qLm7I=", - version = "v0.4.0", - ) - go_repository( - name = "com_github_siderolabs_protoenc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/siderolabs/protoenc", - sum = "h1:BqxEmeWQeMpNP3R6WrPqDatX8sM/r4t97OP8mFmg6GA=", - version = "v0.2.1", - ) - go_repository( - name = "com_github_siderolabs_talos_pkg_machinery", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/siderolabs/talos/pkg/machinery", - sum = "h1:sVFQ0lNE6+kOomSZA8iuktzG1A4zSW9KTsB2TLaTPsU=", - version = "v1.7.1", - ) - go_repository( - name = "com_github_sigstore_protobuf_specs", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sigstore/protobuf-specs", - sum = "h1:E49qS++llp4psM+3NNVEb+C4AD422bT9VkOQIPrNLpA=", - version = "v0.3.0", - ) - go_repository( - name = "com_github_sigstore_rekor", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sigstore/rekor", - sum = "h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8=", - version = "v1.3.6", - ) - go_repository( - name = "com_github_sigstore_sigstore", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sigstore/sigstore", - sum = "h1:G7LVXqL+ekgYtYdksBks9B38dPoIsbscjQJX/MGWkA4=", - version = "v1.8.3", - ) - go_repository( - name = "com_github_sigstore_sigstore_pkg_signature_kms_aws", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sigstore/sigstore/pkg/signature/kms/aws", - sum = "h1:LTfPadUAo+PDRUbbdqbeSl2OuoFQwUFTnJ4stu+nwWw=", - version = "v1.8.3", - ) - go_repository( - name = "com_github_sigstore_sigstore_pkg_signature_kms_azure", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sigstore/sigstore/pkg/signature/kms/azure", - sum = "h1:xgbPRCr2npmmsuVVteJqi/ERw9+I13Wou7kq0Yk4D8g=", - version = "v1.8.3", - ) - go_repository( - name = "com_github_sigstore_sigstore_pkg_signature_kms_gcp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sigstore/sigstore/pkg/signature/kms/gcp", - sum = "h1:vDl2fqPT0h3D/k6NZPlqnKFd1tz3335wm39qjvpZNJc=", - version = "v1.8.3", - ) - go_repository( - name = "com_github_sigstore_sigstore_pkg_signature_kms_hashivault", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sigstore/sigstore/pkg/signature/kms/hashivault", - sum = "h1:h9G8j+Ds21zqqulDbA/R/ft64oQQIyp8S7wJYABYSlg=", - version = "v1.8.3", - ) - go_repository( - name = "com_github_sirupsen_logrus", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sirupsen/logrus", - sum = "h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=", - version = "v1.9.3", - ) - go_repository( - name = "com_github_skeema_knownhosts", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/skeema/knownhosts", - sum = "h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=", - version = "v1.2.2", - ) - go_repository( - name = "com_github_skratchdot_open_golang", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/skratchdot/open-golang", - sum = "h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=", - version = "v0.0.0-20200116055534-eef842397966", - ) - go_repository( - name = "com_github_soheilhy_cmux", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/soheilhy/cmux", - sum = "h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=", - version = "v0.1.5", - ) - go_repository( - name = "com_github_sourcegraph_conc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/sourcegraph/conc", - sum = "h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=", - version = "v0.3.0", - ) - go_repository( - name = "com_github_spaolacci_murmur3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/spaolacci/murmur3", - sum = "h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=", - version = "v0.0.0-20180118202830-f09979ecbc72", - ) - go_repository( - name = "com_github_spf13_afero", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/spf13/afero", - sum = "h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=", - version = "v1.11.0", - ) - go_repository( - name = "com_github_spf13_cast", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/spf13/cast", - sum = "h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=", - version = "v1.6.0", - ) - go_repository( - name = "com_github_spf13_cobra", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/spf13/cobra", - sum = "h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=", - version = "v1.8.0", - ) - go_repository( - name = "com_github_spf13_pflag", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/spf13/pflag", - sum = "h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=", - version = "v1.0.5", - ) - go_repository( - name = "com_github_spf13_viper", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/spf13/viper", - sum = "h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=", - version = "v1.18.2", - ) - go_repository( - name = "com_github_src_d_gcfg", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/src-d/gcfg", - sum = "h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=", - version = "v1.4.0", - ) - go_repository( - name = "com_github_stefanberger_go_pkcs11uri", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/stefanberger/go-pkcs11uri", - sum = "h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I=", - version = "v0.0.0-20201008174630-78d3cae3a980", - ) - go_repository( - name = "com_github_stoewer_go_strcase", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/stoewer/go-strcase", - sum = "h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=", - version = "v1.3.0", - ) - go_repository( - name = "com_github_stretchr_objx", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/stretchr/objx", - sum = "h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=", - version = "v0.5.2", - ) - go_repository( - name = "com_github_stretchr_testify", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/stretchr/testify", - sum = "h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=", - version = "v1.9.0", - ) - go_repository( - name = "com_github_subosito_gotenv", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/subosito/gotenv", - sum = "h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=", - version = "v1.6.0", - ) - go_repository( - name = "com_github_syndtr_gocapability", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/syndtr/gocapability", - sum = "h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=", - version = "v0.0.0-20200815063812-42c35b437635", - ) - go_repository( - name = "com_github_syndtr_goleveldb", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/syndtr/goleveldb", - sum = "h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=", - version = "v1.0.1-0.20220721030215-126854af5e6d", - ) - go_repository( - name = "com_github_tchap_go_patricia_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/tchap/go-patricia/v2", - sum = "h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes=", - version = "v2.3.1", - ) - go_repository( - name = "com_github_theupdateframework_go_tuf", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/theupdateframework/go-tuf", - sum = "h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI=", - version = "v0.7.0", - ) - go_repository( - name = "com_github_tink_crypto_tink_go_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/tink-crypto/tink-go/v2", - sum = "h1:QXFBguwMwTIaU17EgZpEJWsUSc60b1BAGTzBIoMdmok=", - version = "v2.1.0", - ) - go_repository( - name = "com_github_tinylib_msgp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/tinylib/msgp", - sum = "h1:2gXmtWueD2HefZHQe1QOy9HVzmFrLOVvsXwXBQ0ayy0=", - version = "v1.1.5", - ) - go_repository( - name = "com_github_titanous_rocacheck", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/titanous/rocacheck", - sum = "h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0=", - version = "v0.0.0-20171023193734-afe73141d399", - ) - go_repository( - name = "com_github_tmc_grpc_websocket_proxy", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/tmc/grpc-websocket-proxy", - sum = "h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=", - version = "v0.0.0-20220101234140-673ab2c3ae75", - ) - go_repository( - name = "com_github_tomasen_realip", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/tomasen/realip", - sum = "h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc=", - version = "v0.0.0-20180522021738-f0c99a92ddce", - ) - go_repository( - name = "com_github_transparency_dev_merkle", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/transparency-dev/merkle", - sum = "h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4=", - version = "v0.0.2", - ) - go_repository( - name = "com_github_ttacon_chalk", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ttacon/chalk", - sum = "h1:OXcKh35JaYsGMRzpvFkLv/MEyPuL49CThT1pZ8aSml4=", - version = "v0.0.0-20160626202418-22c06c80ed31", - ) - go_repository( - name = "com_github_u_root_gobusybox_src", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/u-root/gobusybox/src", - sum = "h1:AQX6C886dZqnOrXtbP0U59melqbb1+YnCfRYRfr4M3M=", - version = "v0.0.0-20231224233253-2944a440b6b6", - ) - go_repository( - name = "com_github_u_root_u_root", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/u-root/u-root", - sum = "h1:1AIJqOtdEufYfGb3eRpdaqWONzBOpAwrg1fehbWg+Mg=", - version = "v0.11.1-0.20230807200058-f87ad7ccb594", - ) - go_repository( - name = "com_github_u_root_uio", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/u-root/uio", - sum = "h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg=", - version = "v0.0.0-20230305220412-3e8cd9d6bf63", - ) - go_repository( - name = "com_github_ulikunitz_xz", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ulikunitz/xz", - sum = "h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=", - version = "v0.5.11", - ) - go_repository( - name = "com_github_urfave_cli", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/urfave/cli", - sum = "h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk=", - version = "v1.22.14", - ) - go_repository( - name = "com_github_vbatts_tar_split", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/vbatts/tar-split", - sum = "h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck=", - version = "v0.11.3", - ) - go_repository( - name = "com_github_vektah_gqlparser_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/vektah/gqlparser/v2", - sum = "h1:C02NsyEsL4TXJB7ndonqTfuQOL4XPIu0aAWugdmTgmc=", - version = "v2.4.5", - ) - go_repository( - name = "com_github_veraison_go_cose", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/veraison/go-cose", - sum = "h1:Gj4x20D0YP79J2+cK3anjGEMwIkg2xX+TKVVGUXwNAc=", - version = "v1.2.1", - ) - go_repository( - name = "com_github_vincent_petithory_dataurl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/vincent-petithory/dataurl", - sum = "h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_vishvananda_netlink", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/vishvananda/netlink", - sum = "h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=", - version = "v1.2.1-beta.2", - ) - go_repository( - name = "com_github_vishvananda_netns", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/vishvananda/netns", - sum = "h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=", - version = "v0.0.4", - ) - go_repository( - name = "com_github_vmihailenco_msgpack", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/vmihailenco/msgpack", - sum = "h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=", - version = "v4.0.4+incompatible", - ) - go_repository( - name = "com_github_vmihailenco_msgpack_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/vmihailenco/msgpack/v5", - sum = "h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=", - version = "v5.4.1", - ) - go_repository( - name = "com_github_vmihailenco_tagparser_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/vmihailenco/tagparser/v2", - sum = "h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=", - version = "v2.0.0", - ) - go_repository( - name = "com_github_vtolstov_go_ioctl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/vtolstov/go-ioctl", - sum = "h1:X6ps8XHfpQjw8dUStzlMi2ybiKQ2Fmdw7UM+TinwvyM=", - version = "v0.0.0-20151206205506-6be9cced4810", - ) - go_repository( - name = "com_github_weppos_publicsuffix_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/weppos/publicsuffix-go", - sum = "h1:kNn7cjQYeNjKUflvFFCxFeyS7ENcDdfPmkhFpgd0G/A=", - version = "v0.30.1-0.20230620154423-38c92ad2d5c6", - ) - go_repository( - name = "com_github_workiva_go_datastructures", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/Workiva/go-datastructures", - sum = "h1:J6Y/52yX10Xc5JjXmGtWoSSxs3mZnGSaq37xZZh7Yig=", - version = "v1.0.53", - ) - go_repository( - name = "com_github_x448_float16", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/x448/float16", - sum = "h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=", - version = "v0.8.4", - ) - go_repository( - name = "com_github_xanzy_ssh_agent", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/xanzy/ssh-agent", - sum = "h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=", - version = "v0.3.3", - ) - go_repository( - name = "com_github_xdg_go_pbkdf2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/xdg-go/pbkdf2", - sum = "h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=", - version = "v1.0.0", - ) - go_repository( - name = "com_github_xdg_go_scram", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/xdg-go/scram", - sum = "h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=", - version = "v1.1.2", - ) - go_repository( - name = "com_github_xdg_go_stringprep", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/xdg-go/stringprep", - sum = "h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=", - version = "v1.0.4", - ) - go_repository( - name = "com_github_xeipuuv_gojsonpointer", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/xeipuuv/gojsonpointer", - sum = "h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=", - version = "v0.0.0-20190905194746-02993c407bfb", - ) - go_repository( - name = "com_github_xeipuuv_gojsonreference", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/xeipuuv/gojsonreference", - sum = "h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=", - version = "v0.0.0-20180127040603-bd5ef7bd5415", - ) - go_repository( - name = "com_github_xeipuuv_gojsonschema", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/xeipuuv/gojsonschema", - sum = "h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_xhit_go_str2duration_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/xhit/go-str2duration/v2", - sum = "h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=", - version = "v2.1.0", - ) - go_repository( - name = "com_github_xiang90_probing", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/xiang90/probing", - sum = "h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk=", - version = "v0.0.0-20221125231312-a49e3df8f510", - ) - go_repository( - name = "com_github_xlab_treeprint", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/xlab/treeprint", - sum = "h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=", - version = "v1.2.0", - ) - go_repository( - name = "com_github_yashtewari_glob_intersection", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/yashtewari/glob-intersection", - sum = "h1:6gJvMYQlTDOL3dMsPF6J0+26vwX9MB8/1q3uAdhmTrg=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_youmark_pkcs8", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/youmark/pkcs8", - sum = "h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=", - version = "v0.0.0-20181117223130-1be2e3e5546d", - ) - go_repository( - name = "com_github_ysmood_fetchup", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ysmood/fetchup", - sum = "h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ=", - version = "v0.2.3", - ) - go_repository( - name = "com_github_ysmood_goob", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ysmood/goob", - sum = "h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=", - version = "v0.4.0", - ) - go_repository( - name = "com_github_ysmood_got", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ysmood/got", - sum = "h1:IrV2uWLs45VXNvZqhJ6g2nIhY+pgIG1CUoOcqfXFl1s=", - version = "v0.34.1", - ) - go_repository( - name = "com_github_ysmood_gson", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ysmood/gson", - sum = "h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE=", - version = "v0.7.3", - ) - go_repository( - name = "com_github_ysmood_leakless", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/ysmood/leakless", - sum = "h1:BzLrVoiwxikpgEQR0Lk8NyBN5Cit2b1z+u0mgL4ZJak=", - version = "v0.8.0", - ) - go_repository( - name = "com_github_yuin_goldmark", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/yuin/goldmark", - sum = "h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=", - version = "v1.4.13", - ) - go_repository( - name = "com_github_yuin_gopher_lua", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/yuin/gopher-lua", - sum = "h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_yvasiyarov_go_metrics", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/yvasiyarov/go-metrics", - sum = "h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=", - version = "v0.0.0-20140926110328-57bccd1ccd43", - ) - go_repository( - name = "com_github_yvasiyarov_gorelic", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/yvasiyarov/gorelic", - sum = "h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE=", - version = "v0.0.0-20141212073537-a9bba5b9ab50", - ) - go_repository( - name = "com_github_yvasiyarov_newrelic_platform_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/yvasiyarov/newrelic_platform_go", - sum = "h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY=", - version = "v0.0.0-20140908184405-b21fdbd4370f", - ) - go_repository( - name = "com_github_zalando_go_keyring", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/zalando/go-keyring", - sum = "h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms=", - version = "v0.2.3", - ) - go_repository( - name = "com_github_zclconf_go_cty", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/zclconf/go-cty", - sum = "h1:1JXy1XroaGrzZuG6X9dt7HL6s9AwbY+l4UNL8o5B6ho=", - version = "v1.14.3", - ) - go_repository( - name = "com_github_zclconf_go_cty_debug", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/zclconf/go-cty-debug", - sum = "h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=", - version = "v0.0.0-20191215020915-b22d67c1ba0b", - ) - go_repository( - name = "com_github_zmap_zcrypto", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/zmap/zcrypto", - sum = "h1:DZH5n7L3L8RxKdSyJHZt7WePgwdhHnPhQFdQSJaHF+o=", - version = "v0.0.0-20230310154051-c8b263fd8300", - ) - go_repository( - name = "com_github_zmap_zlint_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "github.com/zmap/zlint/v3", - sum = "h1:Eh2B5t6VKgVH0DFmTwOqE50POvyDhUaU9T2mJOe1vfQ=", - version = "v3.5.0", - ) - go_repository( - name = "com_google_cloud_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go", - sum = "h1:ZaGT6LiG7dBzi6zNOvVZwacaXlmf3lRqnC4DQzqyRQw=", - version = "v0.112.2", - ) - go_repository( - name = "com_google_cloud_go_accessapproval", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/accessapproval", - sum = "h1:fMbP4cJX/926h+kwGtABmcG83PXsjkB+q7nSBzZpJoo=", - version = "v1.7.6", - ) - go_repository( - name = "com_google_cloud_go_accesscontextmanager", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/accesscontextmanager", - sum = "h1:NipmPd3BCzwa/mr40SK8pWRkbzv9Th5Azhi4dBYazlM=", - version = "v1.8.6", - ) - go_repository( - name = "com_google_cloud_go_aiplatform", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/aiplatform", - sum = "h1:bbFYY4JInclG10czRFUYj2rjD+obhh3Gi9zVlyoMgEc=", - version = "v1.66.0", - ) - go_repository( - name = "com_google_cloud_go_analytics", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/analytics", - sum = "h1:UH/PWBcPxHKolWxaS3hO+aj+wDTuq7XKvdtpqR3lyOI=", - version = "v0.23.1", - ) - go_repository( - name = "com_google_cloud_go_apigateway", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/apigateway", - sum = "h1:60GMRN1JFwq9MldvEVMdR3gDJ0vI0C/BwgkImG6bx/M=", - version = "v1.6.6", - ) - go_repository( - name = "com_google_cloud_go_apigeeconnect", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/apigeeconnect", - sum = "h1:ObsKNGtdu0ckkCSUpCN5fVAVg+DmzFg89JlqsW4OAWk=", - version = "v1.6.6", - ) - go_repository( - name = "com_google_cloud_go_apigeeregistry", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/apigeeregistry", - sum = "h1:l8VFHdNMC+9Q4EHKye2eOZBu5IwddXF6ufAXI7D+PB8=", - version = "v0.8.4", - ) - go_repository( - name = "com_google_cloud_go_appengine", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/appengine", - sum = "h1:cM+Lj0A0nCtujM9lqRId5L8hz7bHRfu3q3KdKtpn+38=", - version = "v1.8.6", - ) - go_repository( - name = "com_google_cloud_go_area120", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/area120", - sum = "h1:7QJ4ZzqLOwh0pHD3UAa+VwiyWmDI7bdmkYKVkte8/wg=", - version = "v0.8.6", - ) - go_repository( - name = "com_google_cloud_go_artifactregistry", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/artifactregistry", - sum = "h1:icIyRzJ1Ag6EOafuDuFFJ/AdStcOFRVfSGURn27/7Pk=", - version = "v1.14.8", - ) - go_repository( - name = "com_google_cloud_go_asset", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/asset", - sum = "h1:+NpxL5L53VY91EoJTHeGGXSWEUllf2hhXpCyTnSrd3Q=", - version = "v1.18.1", - ) - go_repository( - name = "com_google_cloud_go_assuredworkloads", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/assuredworkloads", - sum = "h1:3NlUes0xLN2kcSU24qQADFYsOaetCPg0HSA302AyV5s=", - version = "v1.11.6", - ) - go_repository( - name = "com_google_cloud_go_auth", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/auth", - sum = "h1:Z7YNIhlWRtrnKlZke7z3GMqzvuYzdc2z98F9D1NV5Hg=", - version = "v0.4.1", - ) - go_repository( - name = "com_google_cloud_go_auth_oauth2adapt", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/auth/oauth2adapt", - sum = "h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4=", - version = "v0.2.2", - ) - go_repository( - name = "com_google_cloud_go_automl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/automl", - sum = "h1:NHBO5cjo2IgwaJ5qlez/iA35XI1db87PPlOB0Kjt5RM=", - version = "v1.13.6", - ) - go_repository( - name = "com_google_cloud_go_baremetalsolution", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/baremetalsolution", - sum = "h1:jCR4rnVsG6ocK6ngFr2Z6ugKZfTENmMZkiV6Ma2tEeE=", - version = "v1.2.5", - ) - go_repository( - name = "com_google_cloud_go_batch", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/batch", - sum = "h1:b9fVZDxxp4LWMhXV7uAhyMGmPuzlzPrsZ0uh+RM92h8=", - version = "v1.8.3", - ) - go_repository( - name = "com_google_cloud_go_beyondcorp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/beyondcorp", - sum = "h1:fnil8viEdcAJJiwiJPCT2fl3Grx3XFwXxTq7n9g/8QM=", - version = "v1.0.5", - ) - go_repository( - name = "com_google_cloud_go_bigquery", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/bigquery", - sum = "h1:kA96WfgvCbkqfLnr7xI5uEfJ4h4FrnkdEb0yty0KSZo=", - version = "v1.60.0", - ) - go_repository( - name = "com_google_cloud_go_billing", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/billing", - sum = "h1:XcYB8aKj97d4/0kh+LQgrxPxOo/0jgPNp5Q1nyzCyvs=", - version = "v1.18.4", - ) - go_repository( - name = "com_google_cloud_go_binaryauthorization", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/binaryauthorization", - sum = "h1:XiAdW5HAWtk9WEjEA5MXYiRJ28Tjp1xGPPAMRFI5bnc=", - version = "v1.8.2", - ) - go_repository( - name = "com_google_cloud_go_certificatemanager", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/certificatemanager", - sum = "h1:oc15T+leZ2Wm5oocvGTbDXwonka0chpJTEiHIVsBiEA=", - version = "v1.8.0", - ) - go_repository( - name = "com_google_cloud_go_channel", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/channel", - sum = "h1:rBnTls9G5nC/jOrb9V/tZFHFXt6kBMNlIQKg6DjAlRM=", - version = "v1.17.6", - ) - go_repository( - name = "com_google_cloud_go_cloudbuild", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/cloudbuild", - sum = "h1:66hY1gXV2cdn4gquy5TieaJwaZmRzrQ5cK++pVgnCkQ=", - version = "v1.16.0", - ) - go_repository( - name = "com_google_cloud_go_clouddms", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/clouddms", - sum = "h1:t1nc49kRzEU2vrDxQQIEc5rZ4Hr187YrdOZPMAgMwMI=", - version = "v1.7.5", - ) - go_repository( - name = "com_google_cloud_go_cloudtasks", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/cloudtasks", - sum = "h1:Ev+poxwb7pudBhiF0ObwAWT7Dh9BZAcsvAfFTWg0MPc=", - version = "v1.12.7", - ) - go_repository( - name = "com_google_cloud_go_compute", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/compute", - sum = "h1:uHf0NN2nvxl1Gh4QO83yRCOdMK4zivtMS5gv0dEX0hg=", - version = "v1.26.0", - ) - go_repository( - name = "com_google_cloud_go_compute_metadata", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/compute/metadata", - sum = "h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=", - version = "v0.3.0", - ) - go_repository( - name = "com_google_cloud_go_contactcenterinsights", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/contactcenterinsights", - sum = "h1:sCDKUmDj9Tfd6Qj7x4XbwC43oYzEBwSDLC1tReQWS/Y=", - version = "v1.13.1", - ) - go_repository( - name = "com_google_cloud_go_container", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/container", - sum = "h1:y5gmgrMMhTrLnQQdMCw0t/Yis9Ps7jvAG4JYcRWxR8g=", - version = "v1.35.0", - ) - go_repository( - name = "com_google_cloud_go_containeranalysis", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/containeranalysis", - sum = "h1:yzohQ0HDoZq2TtCJkbUBsJs9RIR5WbKZlHrD7ilp2yg=", - version = "v0.11.5", - ) - go_repository( - name = "com_google_cloud_go_datacatalog", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/datacatalog", - sum = "h1:BGDsEjqpAo0Ka+b9yDLXnE5k+jU3lXGMh//NsEeDMIg=", - version = "v1.20.0", - ) - go_repository( - name = "com_google_cloud_go_dataflow", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/dataflow", - sum = "h1:GuZJgkOL64cYySwYEYqQkggdxwoZTk8cvekQW0t3KRM=", - version = "v0.9.6", - ) - go_repository( - name = "com_google_cloud_go_dataform", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/dataform", - sum = "h1:0EzWf+c2R5V/ujZBb22H/EL5wpzD/bDFYPA2f3czB1g=", - version = "v0.9.3", - ) - go_repository( - name = "com_google_cloud_go_datafusion", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/datafusion", - sum = "h1:zSmMj/qZ0Yk+q/v5Wg40FTJ0WYPCtanYYekRt7cSKJ0=", - version = "v1.7.6", - ) - go_repository( - name = "com_google_cloud_go_datalabeling", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/datalabeling", - sum = "h1:2zz44bPbDMHsPanQ89SybqhHDQBH1EZk8icGotyrvSU=", - version = "v0.8.6", - ) - go_repository( - name = "com_google_cloud_go_dataplex", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/dataplex", - sum = "h1:Ob8NPT1UcB4kDaDx7/UdsRfZ8xUvUggZshXUlGWDahk=", - version = "v1.15.0", - ) - go_repository( - name = "com_google_cloud_go_dataproc_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/dataproc/v2", - sum = "h1:+cM8p/R6FdTuQYlriJOSUCvAZfMDgBKf0/ph9bMIjaY=", - version = "v2.4.1", - ) - go_repository( - name = "com_google_cloud_go_dataqna", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/dataqna", - sum = "h1:FI/1q7VnANchQR9ug+nzujfiusLMfC3BHT7/fHi+BVU=", - version = "v0.8.6", - ) - go_repository( - name = "com_google_cloud_go_datastore", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/datastore", - sum = "h1:0P9WcsQeTWjuD1H14JIY7XQscIPQ4Laje8ti96IC5vg=", - version = "v1.15.0", - ) - go_repository( - name = "com_google_cloud_go_datastream", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/datastream", - sum = "h1:nHdOKbFmKJ4tPjGtNNIO0//G7QAht6eHTUnREWPn2yI=", - version = "v1.10.5", - ) - go_repository( - name = "com_google_cloud_go_deploy", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/deploy", - sum = "h1:UxcxzjwxGPkT7RBdMmoc5a7QxHQVdpZllD6el2VC3JA=", - version = "v1.17.2", - ) - go_repository( - name = "com_google_cloud_go_dialogflow", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/dialogflow", - sum = "h1:B8Y5j4/QsDirX136OoPm62kG3y5gd8rzBpHSR/FW9vI=", - version = "v1.52.0", - ) - go_repository( - name = "com_google_cloud_go_dlp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/dlp", - sum = "h1:dTsEN6r1BoplUACz7teOmE6lRG1swREiwXkfkY7bi6c=", - version = "v1.12.1", - ) - go_repository( - name = "com_google_cloud_go_documentai", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/documentai", - sum = "h1:UdDy7nDTwr+mN1KiJqsj5AabauoW9SkgH9eY8BuFXJE=", - version = "v1.26.1", - ) - go_repository( - name = "com_google_cloud_go_domains", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/domains", - sum = "h1:NHqZk4XzHFlmXM3LMGwDVET4NKr60W2jaNCRGYod5Ic=", - version = "v0.9.6", - ) - go_repository( - name = "com_google_cloud_go_edgecontainer", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/edgecontainer", - sum = "h1:a++vBi1J00NP1ifVP5mV/3j1/EJKWPj0h6NfUPLfuCQ=", - version = "v1.2.0", - ) - go_repository( - name = "com_google_cloud_go_errorreporting", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/errorreporting", - sum = "h1:kj1XEWMu8P0qlLhm3FwcaFsUvXChV/OraZwA70trRR0=", - version = "v0.3.0", - ) - go_repository( - name = "com_google_cloud_go_essentialcontacts", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/essentialcontacts", - sum = "h1:FDdJGJEXK4RxvT6gdRBqGaCQVpi96RRB7MTyRHUcb20=", - version = "v1.6.7", - ) - go_repository( - name = "com_google_cloud_go_eventarc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/eventarc", - sum = "h1:JMUiLYzxkxr7BqnCPkyJ6Ycgrs6YQlZT44H0rHg7jQY=", - version = "v1.13.5", - ) - go_repository( - name = "com_google_cloud_go_filestore", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/filestore", - sum = "h1:BpaB7bxICPUTntAV+yVUK9bxAUOv7uHRSEibSKMBJVA=", - version = "v1.8.2", - ) - go_repository( - name = "com_google_cloud_go_firestore", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/firestore", - sum = "h1:/k8ppuWOtNuDHt2tsRV42yI21uaGnKDEQnRFeBpbFF8=", - version = "v1.15.0", - ) - go_repository( - name = "com_google_cloud_go_functions", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/functions", - sum = "h1:0kcko/2AKwm4USnWcGs/W/k++PAYPA3dYaQw1y5Xg3M=", - version = "v1.16.1", - ) - go_repository( - name = "com_google_cloud_go_gkebackup", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/gkebackup", - sum = "h1:SATJwsF8PjErP7GwHE+xK8gJ7f7hULuqtazV19ylPgg=", - version = "v1.4.0", - ) - go_repository( - name = "com_google_cloud_go_gkeconnect", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/gkeconnect", - sum = "h1:7X9P6lGkOF/nJRYZBQBG2XPhunqWbNMacy9AXN7qUcU=", - version = "v0.8.6", - ) - go_repository( - name = "com_google_cloud_go_gkehub", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/gkehub", - sum = "h1:kKreFf+097KfW+Tz/SqZKeXs/eFOjs1NDrsVjRPI18o=", - version = "v0.14.6", - ) - go_repository( - name = "com_google_cloud_go_gkemulticloud", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/gkemulticloud", - sum = "h1:CFBoDcQi9zLOkzM6xqmRzljZhF4A6A47QaQ0WtNd+DA=", - version = "v1.1.2", - ) - go_repository( - name = "com_google_cloud_go_gsuiteaddons", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/gsuiteaddons", - sum = "h1:q3x2NE0je/tSVL66MAht5YVbGGHjTV9BxFD2lyDQ0dU=", - version = "v1.6.6", - ) - go_repository( - name = "com_google_cloud_go_iam", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/iam", - sum = "h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0=", - version = "v1.1.8", - ) - go_repository( - name = "com_google_cloud_go_iap", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/iap", - sum = "h1:FrLAtgXzWPwe8rNp7AD+2Lgg4LqyhgXvEdiGK+jtd9g=", - version = "v1.9.5", - ) - go_repository( - name = "com_google_cloud_go_ids", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/ids", - sum = "h1:tNc3NpIp2LUmFJxP2CBlzYw0FTnd68r73mIzg8UlM3Q=", - version = "v1.4.6", - ) - go_repository( - name = "com_google_cloud_go_iot", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/iot", - sum = "h1:nRV/e1e3lEjsVoD5mW99JERwL8MKohyQyY63+lfBMA4=", - version = "v1.7.6", - ) - go_repository( - name = "com_google_cloud_go_kms", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/kms", - sum = "h1:1yZsRPhmargZOmY+fVAh8IKiR9HzCb0U1zsxb5g2nRY=", - version = "v1.16.0", - ) - go_repository( - name = "com_google_cloud_go_language", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/language", - sum = "h1:srkreCxnVa5+a5PXUri/K+VWxG50wGvz5+PEYjgaENQ=", - version = "v1.12.4", - ) - go_repository( - name = "com_google_cloud_go_lifesciences", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/lifesciences", - sum = "h1:8w3edjRiSN6GCxT0uJoXr6Zo2XNYD+6TxPZa7uIIOaU=", - version = "v0.9.6", - ) - go_repository( - name = "com_google_cloud_go_logging", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/logging", - sum = "h1:iEIOXFO9EmSiTjDmfpbRjOxECO7R8C7b8IXUGOj7xZw=", - version = "v1.9.0", - ) - go_repository( - name = "com_google_cloud_go_longrunning", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/longrunning", - sum = "h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU=", - version = "v0.5.7", - ) - go_repository( - name = "com_google_cloud_go_managedidentities", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/managedidentities", - sum = "h1:7+hGPQSojhnYNZCg3fG2mQIF7XMfvNpCpi2Zg5/Qx1g=", - version = "v1.6.6", - ) - go_repository( - name = "com_google_cloud_go_maps", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/maps", - sum = "h1:vcqmqk0wt1NRzQc84Qo6z8HYyol/znqbG7tAS5Qm91g=", - version = "v1.7.1", - ) - go_repository( - name = "com_google_cloud_go_mediatranslation", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/mediatranslation", - sum = "h1:EVW0wCQ7asoMjw8fm8oUe6pQWBaVQth/iquk7ysidy0=", - version = "v0.8.6", - ) - go_repository( - name = "com_google_cloud_go_memcache", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/memcache", - sum = "h1:rqDPCIUfVBvv7ojOGx5PRkPgWeWSKpOht2w6plaxklY=", - version = "v1.10.6", - ) - go_repository( - name = "com_google_cloud_go_metastore", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/metastore", - sum = "h1:K7gyYoqPvQgCc82tiB0CQkXOpg8AZxJtRGMVdN5B83U=", - version = "v1.13.5", - ) - go_repository( - name = "com_google_cloud_go_monitoring", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/monitoring", - sum = "h1:0yvFXK+xQd95VKo6thndjwnJMno7c7Xw1CwMByg0B+8=", - version = "v1.18.1", - ) - go_repository( - name = "com_google_cloud_go_networkconnectivity", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/networkconnectivity", - sum = "h1:t67aEKwmO+SXvQC5ncOjm3vTwnsbO/mTzlCWdK0nwqs=", - version = "v1.14.5", - ) - go_repository( - name = "com_google_cloud_go_networkmanagement", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/networkmanagement", - sum = "h1:uSoVcd78+uNSW34Q+BNumUvTxAtVaKHc8O9WUz091gg=", - version = "v1.13.0", - ) - go_repository( - name = "com_google_cloud_go_networksecurity", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/networksecurity", - sum = "h1:3ggPKshcFs1oRh5qI+Gq1s2CIU9BL99MKtYSBG4Z8s0=", - version = "v0.9.6", - ) - go_repository( - name = "com_google_cloud_go_notebooks", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/notebooks", - sum = "h1:A9jxIdxEccgL9iJLqvU4j5HT3/13YluoF2IbiV+hAN4=", - version = "v1.11.4", - ) - go_repository( - name = "com_google_cloud_go_optimization", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/optimization", - sum = "h1:T/j8xyIkmHGjU6kxeUjK3UTqiXlbvpZQ2A+F5vnH21Y=", - version = "v1.6.4", - ) - go_repository( - name = "com_google_cloud_go_orchestration", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/orchestration", - sum = "h1:i5iSxsu1Cx1itTQEEY/YvsAo1OO8gosGGXhnOjBjgJA=", - version = "v1.9.1", - ) - go_repository( - name = "com_google_cloud_go_orgpolicy", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/orgpolicy", - sum = "h1:x9GttuUZXXeKcJgHSGxYoPn2hOJhhuaN5YYJKfAfmLo=", - version = "v1.12.2", - ) - go_repository( - name = "com_google_cloud_go_osconfig", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/osconfig", - sum = "h1:wIOhgzklE0hHZsho02rRVXYBHSfsAwYZYIaxFaUBIjs=", - version = "v1.12.6", - ) - go_repository( - name = "com_google_cloud_go_oslogin", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/oslogin", - sum = "h1:v71OrrkKyqr5Mfnt345GqSOURzByv08qfrtvfhOVcnc=", - version = "v1.13.2", - ) - go_repository( - name = "com_google_cloud_go_phishingprotection", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/phishingprotection", - sum = "h1:DcAre1psFwJM/FBA/MkDj0H6uxZhACE5IW/xF9ssHDQ=", - version = "v0.8.6", - ) - go_repository( - name = "com_google_cloud_go_policytroubleshooter", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/policytroubleshooter", - sum = "h1:wxBRfNoMy7rnoEeaTOHIEHCUEdUIQIwQGUqfBWH6cyQ=", - version = "v1.10.4", - ) - go_repository( - name = "com_google_cloud_go_privatecatalog", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/privatecatalog", - sum = "h1:bcIABOUmpnzQip83OVv+Ju/NxXjUTRLUSP+FVLFG6kk=", - version = "v0.9.6", - ) - go_repository( - name = "com_google_cloud_go_profiler", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/profiler", - sum = "h1:ZeRDZbsOBDyRG0OiK0Op1/XWZ3xeLwJc9zjkzczUxyY=", - version = "v0.4.0", - ) - go_repository( - name = "com_google_cloud_go_pubsub", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/pubsub", - sum = "h1:0uEEfaB1VIJzabPpwpZf44zWAKAme3zwKKxHk7vJQxQ=", - version = "v1.37.0", - ) - go_repository( - name = "com_google_cloud_go_pubsublite", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/pubsublite", - sum = "h1:pX+idpWMIH30/K7c0epN6V703xpIcMXWRjKJsz0tYGY=", - version = "v1.8.1", - ) - go_repository( - name = "com_google_cloud_go_recaptchaenterprise_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/recaptchaenterprise/v2", - sum = "h1:nykUP2WD/914jui/IldiCOuoTn6T8ha1Ys6/N9sAqJY=", - version = "v2.12.0", - ) - go_repository( - name = "com_google_cloud_go_recommendationengine", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/recommendationengine", - sum = "h1:m0eQtYCToxMSbDKOnpJ2YGdQhyjOPffg4Y8lM2RWzao=", - version = "v0.8.6", - ) - go_repository( - name = "com_google_cloud_go_recommender", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/recommender", - sum = "h1:3M6lD39/GlOMYOikeF5wflSa4EP5pGFthoIASbyhIXE=", - version = "v1.12.2", - ) - go_repository( - name = "com_google_cloud_go_redis", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/redis", - sum = "h1:zlGxeAsiwcPU+Cta76ALduhdBAVhuYpEjv59V5L/ves=", - version = "v1.14.3", - ) - go_repository( - name = "com_google_cloud_go_resourcemanager", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/resourcemanager", - sum = "h1:VPfJFbWxrTYQzEXCDbJNpcvSB8eZhTSM0YHH146fIB8=", - version = "v1.9.6", - ) - go_repository( - name = "com_google_cloud_go_resourcesettings", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/resourcesettings", - sum = "h1:l/IbRDDmGJFlR4bRZGtfYvix1Pu0jAKGLr7wgUtixHQ=", - version = "v1.6.6", - ) - go_repository( - name = "com_google_cloud_go_retail", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/retail", - sum = "h1:AyVdElkdIU3JedWpX/qENbt8iUmKD+kiyj7ZpzguhTg=", - version = "v1.16.1", - ) - go_repository( - name = "com_google_cloud_go_run", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/run", - sum = "h1:xQND6EJn1LgouCLPSfykkzagyr4gq4FKiRexNxXixV0=", - version = "v1.3.6", - ) - go_repository( - name = "com_google_cloud_go_scheduler", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/scheduler", - sum = "h1:h1/VZk0XdkSh/jI7dDNp3V0Qi8yTkclOljDVPelXvAw=", - version = "v1.10.7", - ) - go_repository( - name = "com_google_cloud_go_secretmanager", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/secretmanager", - sum = "h1:nQ/Ca2Gzm/OEP8tr1hiFdHRi5wAnAmsm9qTjwkivyrQ=", - version = "v1.13.0", - ) - go_repository( - name = "com_google_cloud_go_security", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/security", - sum = "h1:LYMj7ISEEjVQ0ub6E6ygGhjVbNQTH5CawKZz0bbPMVE=", - version = "v1.15.6", - ) - go_repository( - name = "com_google_cloud_go_securitycenter", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/securitycenter", - sum = "h1:NpEJeFbm3ad3ibpbpIBKXJS7eQq1cZhtt9nrDTMO/QQ=", - version = "v1.28.0", - ) - go_repository( - name = "com_google_cloud_go_servicedirectory", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/servicedirectory", - sum = "h1:gkzx9Cd+OTOD+zY4u5vtbdvOx7vrvHYdeDiNdC6vKyw=", - version = "v1.11.5", - ) - go_repository( - name = "com_google_cloud_go_shell", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/shell", - sum = "h1:/oJf9sboa2FfHWCmHXy+XfTRnZy8lC7O5zFyfE1EA6s=", - version = "v1.7.6", - ) - go_repository( - name = "com_google_cloud_go_spanner", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/spanner", - sum = "h1:O9kf49dfaDRzPpKJNChHUJ+Bao02WPedZb8ZPyi02lI=", - version = "v1.60.0", - ) - go_repository( - name = "com_google_cloud_go_speech", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/speech", - sum = "h1:xo/cmhBtqoqqNg/5I8m0ECXPiqYg2fS2ioOccH+qbKE=", - version = "v1.22.1", - ) - go_repository( - name = "com_google_cloud_go_storage", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/storage", - sum = "h1:VEpDQV5CJxFmJ6ueWNsKxcr1QAYOXEgxDa+sBbJahPw=", - version = "v1.40.0", - ) - go_repository( - name = "com_google_cloud_go_storagetransfer", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/storagetransfer", - sum = "h1:BawJo/u0P21cdxc2gB878qIFDC80COq2i0qWZeNevSw=", - version = "v1.10.5", - ) - go_repository( - name = "com_google_cloud_go_talent", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/talent", - sum = "h1:4xgDFfOcgcSY0dUzaSc2tQCSRoLDEJ5CfbW5jfcgNJk=", - version = "v1.6.7", - ) - go_repository( - name = "com_google_cloud_go_texttospeech", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/texttospeech", - sum = "h1:gLEyDoJeFGdoX7jSKbf+nJy7CTgjsSbCZXwzzkXgH9w=", - version = "v1.7.6", - ) - go_repository( - name = "com_google_cloud_go_tpu", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/tpu", - sum = "h1:Cb1txkZYbKlGIZ4tQr9EjEB9snAOU6qyjvNezGXDunI=", - version = "v1.6.6", - ) - go_repository( - name = "com_google_cloud_go_trace", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/trace", - sum = "h1:XF0Ejdw0NpRfAvuZUeQe3ClAG4R/9w5JYICo7l2weaw=", - version = "v1.10.6", - ) - go_repository( - name = "com_google_cloud_go_translate", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/translate", - sum = "h1:SXOtKYnT7ZkeMtPwujaBOBt5Ph4kf6LIuMpAgu/WON0=", - version = "v1.10.2", - ) - go_repository( - name = "com_google_cloud_go_video", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/video", - sum = "h1:y4jgUqDiWMfX+beJnlrnloBQxEIa9v+KrlkD2QJVpeE=", - version = "v1.20.5", - ) - go_repository( - name = "com_google_cloud_go_videointelligence", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/videointelligence", - sum = "h1:P0Sa8+5KOEAVk/fazUNjVPzRCijCheZWJ8wL8xBn9Uk=", - version = "v1.11.6", - ) - go_repository( - name = "com_google_cloud_go_vision_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/vision/v2", - sum = "h1:kvR1sHcuPYat1wI3BYY7CEX2xLAcUHPYL6dOzV2Xf4Q=", - version = "v2.8.1", - ) - go_repository( - name = "com_google_cloud_go_vmmigration", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/vmmigration", - sum = "h1:sbaWK76csqtk0TGPGCiJqZi7tfrU0LnrhUjZHI5YVdc=", - version = "v1.7.6", - ) - go_repository( - name = "com_google_cloud_go_vmwareengine", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/vmwareengine", - sum = "h1:Mf8abigBstvjfSGq9twhtbMTCONL0Cjds+tGbc2pV0M=", - version = "v1.1.2", - ) - go_repository( - name = "com_google_cloud_go_vpcaccess", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/vpcaccess", - sum = "h1:wbMTRdZ9P5+3D6oQWWqB/YxDCFR5m5OJ+b+hHwaBBQQ=", - version = "v1.7.6", - ) - go_repository( - name = "com_google_cloud_go_webrisk", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/webrisk", - sum = "h1:rVhi2WOHcZF72X7spXVTFTmRGeFN4NFeW7/Ku7kgeug=", - version = "v1.9.6", - ) - go_repository( - name = "com_google_cloud_go_websecurityscanner", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/websecurityscanner", - sum = "h1:YAwNB/HjKOVAy9D7W8Bkv8OQ9G2lqIqFOuJbyH5Xo4Q=", - version = "v1.6.6", - ) - go_repository( - name = "com_google_cloud_go_workflows", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "cloud.google.com/go/workflows", - sum = "h1:hH511zmS93oE6j64m/eiGWnfgqailh/S8+f3MVNLcE8=", - version = "v1.12.5", - ) - go_repository( - name = "com_shuralyov_dmitri_gpu_mtl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "dmitri.shuralyov.com/gpu/mtl", - sum = "h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=", - version = "v0.0.0-20190408044501-666a987793e9", - ) - go_repository( - name = "com_sslmate_software_src_go_pkcs12", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "software.sslmate.com/src/go-pkcs12", - sum = "h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k=", - version = "v0.4.0", - ) - go_repository( - name = "dev_gocloud", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gocloud.dev", - sum = "h1:XF1rN6R0qZI/9DYjN16Uy0durAmSlf58DHOcb28GPro=", - version = "v0.37.0", - ) - go_repository( - name = "in_gopkg_alecthomas_kingpin_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/alecthomas/kingpin.v2", - sum = "h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=", - version = "v2.2.6", - ) - go_repository( - name = "in_gopkg_check_v1", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/check.v1", - sum = "h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=", - version = "v1.0.0-20201130134442-10cb98267c6c", - ) - go_repository( - name = "in_gopkg_cheggaaa_pb_v1", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/cheggaaa/pb.v1", - sum = "h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk=", - version = "v1.0.28", - ) - go_repository( - name = "in_gopkg_errgo_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/errgo.v2", - sum = "h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=", - version = "v2.1.0", - ) - go_repository( - name = "in_gopkg_fsnotify_v1", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/fsnotify.v1", - sum = "h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=", - version = "v1.4.7", - ) - go_repository( - name = "in_gopkg_gcfg_v1", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/gcfg.v1", - sum = "h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs=", - version = "v1.2.3", - ) - go_repository( - name = "in_gopkg_go_jose_go_jose_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/go-jose/go-jose.v2", - sum = "h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs=", - version = "v2.6.3", - ) - go_repository( - name = "in_gopkg_inf_v0", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/inf.v0", - sum = "h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=", - version = "v0.9.1", - ) - go_repository( - name = "in_gopkg_ini_v1", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/ini.v1", - sum = "h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=", - version = "v1.67.0", - ) - go_repository( - name = "in_gopkg_natefinch_lumberjack_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/natefinch/lumberjack.v2", - sum = "h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=", - version = "v2.2.1", - ) - go_repository( - name = "in_gopkg_square_go_jose_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/square/go-jose.v2", - sum = "h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=", - version = "v2.6.0", - ) - go_repository( - name = "in_gopkg_src_d_go_billy_v4", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/src-d/go-billy.v4", - sum = "h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=", - version = "v4.3.2", - ) - go_repository( - name = "in_gopkg_src_d_go_git_fixtures_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/src-d/go-git-fixtures.v3", - sum = "h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg=", - version = "v3.5.0", - ) - go_repository( - name = "in_gopkg_src_d_go_git_v4", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/src-d/go-git.v4", - sum = "h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=", - version = "v4.13.1", - ) - go_repository( - name = "in_gopkg_tomb_v1", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/tomb.v1", - sum = "h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=", - version = "v1.0.0-20141024135613-dd632973f1e7", - ) - go_repository( - name = "in_gopkg_warnings_v0", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/warnings.v0", - sum = "h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=", - version = "v0.1.2", - ) - go_repository( - name = "in_gopkg_yaml_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/yaml.v2", - sum = "h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=", - version = "v2.4.0", - ) - go_repository( - name = "in_gopkg_yaml_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gopkg.in/yaml.v3", - sum = "h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=", - version = "v3.0.1", - ) - go_repository( - name = "io_etcd_go_bbolt", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/bbolt", - sum = "h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=", - version = "v1.3.8", - ) - go_repository( - name = "io_etcd_go_etcd_api_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/api/v3", - sum = "h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4=", - version = "v3.5.13", - ) - go_repository( - name = "io_etcd_go_etcd_client_pkg_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/client/pkg/v3", - sum = "h1:RVZSAnWWWiI5IrYAXjQorajncORbS0zI48LQlE2kQWg=", - version = "v3.5.13", - ) - go_repository( - name = "io_etcd_go_etcd_client_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/client/v2", - sum = "h1:0m4ovXYo1CHaA/Mp3X/Fak5sRNIWf01wk/X1/G3sGKI=", - version = "v2.305.12", - ) - go_repository( - name = "io_etcd_go_etcd_client_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/client/v3", - sum = "h1:o0fHTNJLeO0MyVbc7I3fsCf6nrOqn5d+diSarKnB2js=", - version = "v3.5.13", - ) - go_repository( - name = "io_etcd_go_etcd_etcdctl_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/etcdctl/v3", - sum = "h1:GSmhNeq9LGt/gKHbzOmuPLO946GG5ZBCs9h28o0nNkE=", - version = "v3.5.12", - ) - go_repository( - name = "io_etcd_go_etcd_etcdutl_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/etcdutl/v3", - sum = "h1:R3HLloeRcIOAvNtOTcMV9fshCbz9aZP2Xh4AP2+KnFU=", - version = "v3.5.12", - ) - go_repository( - name = "io_etcd_go_etcd_pkg_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/pkg/v3", - sum = "h1:OK2fZKI5hX/+BTK76gXSTyZMrbnARyX9S643GenNGb8=", - version = "v3.5.12", - ) - go_repository( - name = "io_etcd_go_etcd_raft_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/raft/v3", - sum = "h1:7r22RufdDsq2z3STjoR7Msz6fYH8tmbkdheGfwJNRmU=", - version = "v3.5.12", - ) - go_repository( - name = "io_etcd_go_etcd_server_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/server/v3", - sum = "h1:EtMjsbfyfkwZuA2JlKOiBfuGkFCekv5H178qjXypbG8=", - version = "v3.5.12", - ) - go_repository( - name = "io_etcd_go_etcd_tests_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/tests/v3", - sum = "h1:k1fG7+F87Z7zKp57EcjXu9XgOsW0sfp5USqfzmMTIwM=", - version = "v3.5.12", - ) - go_repository( - name = "io_etcd_go_etcd_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.etcd.io/etcd/v3", - sum = "h1:YMdAAKv9xGTeWvfcangHj0Yqbph9w43xwosKOKzWJxs=", - version = "v3.5.12", - ) - go_repository( - name = "io_filippo_edwards25519", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "filippo.io/edwards25519", - sum = "h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=", - version = "v1.1.0", - ) - go_repository( - name = "io_k8s_api", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/api", - sum = "h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_apiextensions_apiserver", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/apiextensions-apiserver", - sum = "h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_apimachinery", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/apimachinery", - sum = "h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_apiserver", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/apiserver", - sum = "h1:QCec+U72tMQ+9tR6A0sMBB5Vh6ImCEkoKkTDRABWq6M=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_cli_runtime", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/cli-runtime", - sum = "h1:q2kC3cex4rOBLfPOnMSzV2BIrrQlx97gxHJs21KxKS4=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_client_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/client-go", - sum = "h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_cloud_provider", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/cloud-provider", - replace = "k8s.io/cloud-provider", - sum = "h1:Qgk/jHsSKGRk/ltTlN6e7eaNuuamLROOzVBd0RPp94M=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_cluster_bootstrap", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/cluster-bootstrap", - sum = "h1:vaIjA1eMFpcLYz+p6NMj75aqiauDahFx9EkuTxc0GMI=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_code_generator", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/code-generator", - sum = "h1:3VUVqHvWFSVSm9kqL/G6kD4ZwNdHF6J/jPyo3Jgjy3k=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_component_base", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/component-base", - sum = "h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_component_helpers", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/component-helpers", - sum = "h1:Y8W70NGeitKxWwhsPo/vEQbQx5VqJV+3xfLpP3V1VxU=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_controller_manager", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/controller-manager", - replace = "k8s.io/controller-manager", - sum = "h1:kEv9sKLnjDkoSqeouWp2lZ8P33an5wrDJpOMqoyD7pc=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_cri_api", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/cri-api", - sum = "h1:hZqh3vH5JZdqeAyhD9nPXSbT6GDgrtPJkPiIzhWKVhk=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_csi_translation_lib", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/csi-translation-lib", - replace = "k8s.io/csi-translation-lib", - sum = "h1:we4X1yUlDikvm5Rv0dwMuPHNw6KwjwsQiAuOPWXha8M=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_dynamic_resource_allocation", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/dynamic-resource-allocation", - replace = "k8s.io/dynamic-resource-allocation", - sum = "h1:JQW5erdoOsvhst7DxMfEpnXhrfm9SmNTnvyaXdqTLAE=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_endpointslice", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/endpointslice", - replace = "k8s.io/endpointslice", - sum = "h1:HM+zsyqSALW7FzOVCWYsF+eFabiTGDrZpLEZZX2065U=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_gengo_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/gengo/v2", - sum = "h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo=", - version = "v2.0.0-20240228010128-51d4e06bde70", - ) - go_repository( - name = "io_k8s_klog_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/klog/v2", - sum = "h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=", - version = "v2.120.1", - ) - go_repository( - name = "io_k8s_kms", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/kms", - sum = "h1:ZlnD/ei5lpvUlPw6eLfVvH7d8i9qZ6HwUQgydNVks8g=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_kube_aggregator", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/kube-aggregator", - replace = "k8s.io/kube-aggregator", - sum = "h1:N4fmtePxOZ+bwiK1RhVEztOU+gkoVkvterHgpwAuiTw=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_kube_controller_manager", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/kube-controller-manager", - replace = "k8s.io/kube-controller-manager", - sum = "h1:25nmyTOdjOLM1QLe4nbu5jvlLSv1ZIPFDvmUUWvbuSw=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_kube_openapi", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/kube-openapi", - sum = "h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=", - version = "v0.0.0-20240228011516-70dd3763d340", - ) - go_repository( - name = "io_k8s_kube_proxy", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/kube-proxy", - replace = "k8s.io/kube-proxy", - sum = "h1:nZJdLzHTIJ2okftUMsBvEidtH57GAOMMPFKBcA0V+Bg=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_kube_scheduler", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/kube-scheduler", - replace = "k8s.io/kube-scheduler", - sum = "h1:n4v68EvxYhy7o5Q/LFPgqBEGi7lKoiAxwQ0gQyMoj9M=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_kubectl", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/kubectl", - sum = "h1:Oqi48gXjikDhrBF67AYuZRTcJV4lg2l42GmvsP7FmYI=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_kubelet", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/kubelet", - sum = "h1:/pqHVR2Rn8ExCpn211wL3pMtqRFpcBcJPl4+1INbIMk=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_kubernetes", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/kubernetes", - sum = "h1:u3Yw8rNlo2NDSGaDpoxoHXLPQnEu1tfqHATKOJe94HY=", - version = "v1.30.0", - ) - go_repository( - name = "io_k8s_legacy_cloud_providers", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/legacy-cloud-providers", - replace = "k8s.io/legacy-cloud-providers", - sum = "h1:fjGV9OhqseUTp3R8xOm2TBoAxyuRTOS6B2zFTSJ80RE=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_metrics", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/metrics", - sum = "h1:a6dWcNM+EEowMzMZ8trka6wZtSRIfEA/9oLjuhBksGc=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_mount_utils", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/mount-utils", - sum = "h1:EceYTNYVabfpdtIAHC4KgMzoZkm1B8ovZ1J666mYZQI=", - version = "v0.30.0", - ) - go_repository( - name = "io_k8s_pod_security_admission", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/pod-security-admission", - replace = "k8s.io/pod-security-admission", - sum = "h1:tY/ldtkbBCulMYVSWg6ZDLlgDYDWy6rLj8e/AgmwSj4=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_sample_apiserver", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/sample-apiserver", - replace = "k8s.io/sample-apiserver", - sum = "h1:bUEz09ehjQE/xpgMVkutbBfZhcLvg1BvCMLvJnbLZbc=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_sigs_apiserver_network_proxy_konnectivity_client", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "sigs.k8s.io/apiserver-network-proxy/konnectivity-client", - sum = "h1:/U5vjBbQn3RChhv7P11uhYvCSm5G2GaIi5AIGBS6r4c=", - version = "v0.29.0", - ) - go_repository( - name = "io_k8s_sigs_controller_runtime", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "sigs.k8s.io/controller-runtime", - sum = "h1:RqVW6Kpeaji67CY5nPEfRz6ZfFMk0lWQlNrLqlNpx+Q=", - version = "v0.18.2", - ) - go_repository( - name = "io_k8s_sigs_json", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "sigs.k8s.io/json", - sum = "h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=", - version = "v0.0.0-20221116044647-bc3834ca7abd", - ) - go_repository( - name = "io_k8s_sigs_knftables", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "sigs.k8s.io/knftables", - sum = "h1:VzKQoDMCGBOH8c85sGrWSXSPCS0XrIpEfOlcCLBXiC0=", - version = "v0.0.14", - ) - go_repository( - name = "io_k8s_sigs_kustomize_api", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "sigs.k8s.io/kustomize/api", - sum = "h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0=", - version = "v0.13.5-0.20230601165947-6ce0bf390ce3", - ) - go_repository( - name = "io_k8s_sigs_kustomize_kustomize_v5", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "sigs.k8s.io/kustomize/kustomize/v5", - sum = "h1:vq2TtoDcQomhy7OxXLUOzSbHMuMYq0Bjn93cDtJEdKw=", - version = "v5.0.4-0.20230601165947-6ce0bf390ce3", - ) - go_repository( - name = "io_k8s_sigs_kustomize_kyaml", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "sigs.k8s.io/kustomize/kyaml", - sum = "h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U=", - version = "v0.14.3-0.20230601165947-6ce0bf390ce3", - ) - go_repository( - name = "io_k8s_sigs_release_utils", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "sigs.k8s.io/release-utils", - sum = "h1:JKDOvhCk6zW8ipEOkpTGDH/mW3TI+XqtPp16aaQ79FU=", - version = "v0.7.7", - ) - go_repository( - name = "io_k8s_sigs_structured_merge_diff_v4", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "sigs.k8s.io/structured-merge-diff/v4", - sum = "h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=", - version = "v4.4.1", - ) - go_repository( - name = "io_k8s_sigs_yaml", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "sigs.k8s.io/yaml", - sum = "h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=", - version = "v1.4.0", - ) - go_repository( - name = "io_k8s_system_validators", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/system-validators", - sum = "h1:tq05tdO9zdJZnNF3SXrq6LE7Knc/KfJm5wk68467JDg=", - version = "v1.8.0", - ) - go_repository( - name = "io_k8s_utils", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "k8s.io/utils", - sum = "h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak=", - version = "v0.0.0-20240502163921-fe8a2dddb1d0", - ) - go_repository( - name = "io_opencensus_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opencensus.io", - sum = "h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=", - version = "v0.24.0", - ) - go_repository( - name = "io_opencensus_go_contrib_exporter_stackdriver", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "contrib.go.opencensus.io/exporter/stackdriver", - sum = "h1:zBakwHardp9Jcb8sQHcHpXy/0+JIb1M8KjigCJzx7+4=", - version = "v0.13.14", - ) - go_repository( - name = "io_opentelemetry_go_contrib_instrumentation_github_com_emicklei_go_restful_otelrestful", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful", - sum = "h1:Z6SbqeRZAl2OczfkFOqLx1BeYBDYehNjEnqluD7581Y=", - version = "v0.42.0", - ) - go_repository( - name = "io_opentelemetry_go_contrib_instrumentation_google_golang_org_grpc_otelgrpc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc", - sum = "h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg=", - version = "v0.49.0", - ) - go_repository( - name = "io_opentelemetry_go_contrib_instrumentation_net_http_otelhttp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp", - sum = "h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=", - version = "v0.49.0", - ) - go_repository( - name = "io_opentelemetry_go_otel", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/otel", - sum = "h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=", - version = "v1.24.0", - ) - go_repository( - name = "io_opentelemetry_go_otel_exporters_otlp_internal_retry", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/otel/exporters/otlp/internal/retry", - sum = "h1:ZSdnH1x5Gm/eUFNQquwSt4/LMCOqS6KPlI9qaTKx5Ho=", - version = "v1.15.0", - ) - go_repository( - name = "io_opentelemetry_go_otel_exporters_otlp_otlptrace", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/otel/exporters/otlp/otlptrace", - sum = "h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8=", - version = "v1.20.0", - ) - go_repository( - name = "io_opentelemetry_go_otel_exporters_otlp_otlptrace_otlptracegrpc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc", - sum = "h1:gvmNvqrPYovvyRmCSygkUDyL8lC5Tl845MLEwqpxhEU=", - version = "v1.20.0", - ) - go_repository( - name = "io_opentelemetry_go_otel_exporters_otlp_otlptrace_otlptracehttp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp", - sum = "h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=", - version = "v1.19.0", - ) - go_repository( - name = "io_opentelemetry_go_otel_metric", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/otel/metric", - sum = "h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=", - version = "v1.24.0", - ) - go_repository( - name = "io_opentelemetry_go_otel_sdk", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/otel/sdk", - sum = "h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=", - version = "v1.24.0", - ) - go_repository( - name = "io_opentelemetry_go_otel_trace", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/otel/trace", - sum = "h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=", - version = "v1.24.0", - ) - go_repository( - name = "io_opentelemetry_go_proto_otlp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.opentelemetry.io/proto/otlp", - sum = "h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=", - version = "v1.0.0", - ) - go_repository( - name = "io_rsc_binaryregexp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "rsc.io/binaryregexp", - sum = "h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=", - version = "v0.2.0", - ) - go_repository( - name = "io_rsc_quote_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "rsc.io/quote/v3", - sum = "h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=", - version = "v3.1.0", - ) - go_repository( - name = "io_rsc_sampler", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "rsc.io/sampler", - sum = "h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=", - version = "v1.3.0", - ) - go_repository( - name = "land_oras_oras_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "oras.land/oras-go", - sum = "h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo=", - version = "v1.2.5", - ) - go_repository( - name = "net_starlark_go", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.starlark.net", - sum = "h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=", - version = "v0.0.0-20230525235612-a134d8f9ddca", - ) - go_repository( - name = "org_bitbucket_bertimus9_systemstat", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "bitbucket.org/bertimus9/systemstat", - sum = "h1:n0aLnh2Jo4nBUBym9cE5PJDG8GT6g+4VuS2Ya2jYYpA=", - version = "v0.5.0", - ) - go_repository( - name = "org_bitbucket_creachadair_shell", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "bitbucket.org/creachadair/shell", - sum = "h1:3yM6JcAfaGWzjzcCamTblzSIWXm/YSs0PFGIzBm2HTo=", - version = "v0.0.8", - ) - go_repository( - name = "org_golang_google_api", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "google.golang.org/api", - sum = "h1:M2D87Yo0rGBPWpo1orwfCLehUUL6E7/TYe5gvMQWDh4=", - version = "v0.180.0", - ) - go_repository( - name = "org_golang_google_appengine", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "google.golang.org/appengine", - sum = "h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=", - version = "v1.6.8", - ) - go_repository( - name = "org_golang_google_genproto", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "google.golang.org/genproto", - sum = "h1:wu/KJm9KJwpfHWhkkZGohVC6KRrc1oJNr4jwtQMOQXw=", - version = "v0.0.0-20240401170217-c3f982113cda", - ) - go_repository( - name = "org_golang_google_genproto_googleapis_api", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "google.golang.org/genproto/googleapis/api", - sum = "h1:AH34z6WAGVNkllnKs5raNq3yRq93VnjBG6rpfub/jYk=", - version = "v0.0.0-20240506185236-b8a5c65736ae", - ) - go_repository( - name = "org_golang_google_genproto_googleapis_bytestream", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "google.golang.org/genproto/googleapis/bytestream", - sum = "h1:GtsRfMHDREQPg/snOM0QudeC54kX7UqodmmK4uELHLQ=", - version = "v0.0.0-20240429193739-8cf5692501f6", - ) - go_repository( - name = "org_golang_google_genproto_googleapis_rpc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "google.golang.org/genproto/googleapis/rpc", - sum = "h1:DujSIu+2tC9Ht0aPNA7jgj23Iq8Ewi5sgkQ++wdvonE=", - version = "v0.0.0-20240429193739-8cf5692501f6", - ) - go_repository( - name = "org_golang_google_grpc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "google.golang.org/grpc", - sum = "h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=", - version = "v1.63.2", - ) - go_repository( - name = "org_golang_google_grpc_cmd_protoc_gen_go_grpc", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "google.golang.org/grpc/cmd/protoc-gen-go-grpc", - sum = "h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA=", - version = "v1.3.0", - ) - go_repository( - name = "org_golang_google_protobuf", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "google.golang.org/protobuf", - sum = "h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=", - version = "v1.34.1", - ) - go_repository( - name = "org_golang_x_crypto", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/crypto", - sum = "h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=", - version = "v0.23.0", - ) - go_repository( - name = "org_golang_x_exp", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/exp", - sum = "h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=", - version = "v0.0.0-20240506185415-9bf2ced13842", - ) - go_repository( - name = "org_golang_x_image", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/image", - sum = "h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=", - version = "v0.0.0-20190802002840-cff245a6509b", - ) - go_repository( - name = "org_golang_x_lint", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/lint", - sum = "h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=", - version = "v0.0.0-20210508222113-6edffad5e616", - ) - go_repository( - name = "org_golang_x_mobile", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/mobile", - sum = "h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=", - version = "v0.0.0-20190719004257-d2bd2a29d028", - ) - go_repository( - name = "org_golang_x_mod", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/mod", - sum = "h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=", - version = "v0.17.0", - ) - go_repository( - name = "org_golang_x_net", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/net", - sum = "h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=", - version = "v0.25.0", - ) - go_repository( - name = "org_golang_x_oauth2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/oauth2", - sum = "h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=", - version = "v0.20.0", - ) - go_repository( - name = "org_golang_x_sync", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/sync", - sum = "h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=", - version = "v0.7.0", - ) - go_repository( - name = "org_golang_x_sys", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/sys", - sum = "h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=", - version = "v0.20.0", - ) - go_repository( - name = "org_golang_x_telemetry", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/telemetry", - sum = "h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY=", - version = "v0.0.0-20240228155512-f48c80bd79b2", - ) - go_repository( - name = "org_golang_x_term", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/term", - sum = "h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=", - version = "v0.20.0", - ) - go_repository( - name = "org_golang_x_text", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/text", - sum = "h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=", - version = "v0.15.0", - ) - go_repository( - name = "org_golang_x_time", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/time", - sum = "h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=", - version = "v0.5.0", - ) - go_repository( - name = "org_golang_x_tools", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/tools", - sum = "h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=", - version = "v0.21.0", - ) - go_repository( - name = "org_golang_x_vuln", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/vuln", - sum = "h1:ECEdI+aEtjpF90eqEcDL5Q11DWSZAw5PJQWlp0+gWqc=", - version = "v1.1.0", - ) - go_repository( - name = "org_golang_x_xerrors", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "golang.org/x/xerrors", - sum = "h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=", - version = "v0.0.0-20231012003039-104605ab7028", - ) - go_repository( - name = "org_libvirt_go_libvirt", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "libvirt.org/go/libvirt", - # keep - patches = [ - "//3rdparty/bazel/org_libvirt_go_libvirt:go_libvirt.patch", - ], - sum = "h1:LEoawzuggD6IL5R/XtnBE8wWJx49i7UZ1HcB7p9glwE=", - version = "v1.10003.0", - ) - go_repository( - name = "org_mongodb_go_mongo_driver", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.mongodb.org/mongo-driver", - sum = "h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=", - version = "v1.14.0", - ) - go_repository( - name = "org_mozilla_go_pkcs7", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.mozilla.org/pkcs7", - sum = "h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M=", - version = "v0.0.0-20200128120323-432b2356ecb1", - ) - go_repository( - name = "org_uber_go_atomic", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.uber.org/atomic", - sum = "h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=", - version = "v1.7.0", - ) - go_repository( - name = "org_uber_go_goleak", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.uber.org/goleak", - sum = "h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=", - version = "v1.3.0", - ) - go_repository( - name = "org_uber_go_multierr", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.uber.org/multierr", - sum = "h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=", - version = "v1.11.0", - ) - go_repository( - name = "org_uber_go_zap", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.uber.org/zap", - sum = "h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=", - version = "v1.27.0", - ) - go_repository( - name = "sh_elv_src", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "src.elv.sh", - sum = "h1:pjVeIo9Ba6K1Wy+rlwX91zT7A+xGEmxiNRBdN04gDTQ=", - version = "v0.16.0-rc1.0.20220116211855-fda62502ad7f", - ) - go_repository( - name = "sh_helm_helm", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "helm.sh/helm", - sum = "h1:cSe3FaQOpRWLDXvTObQNj0P7WI98IG5yloU6tQVls2k=", - version = "v2.17.0+incompatible", - ) - go_repository( - name = "sh_helm_helm_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "helm.sh/helm/v3", - sum = "h1:6FSpEfqyDalHq3kUr4gOMThhgY55kXUEjdQoyODYnrM=", - version = "v3.14.4", - ) - go_repository( - name = "sm_step_go_crypto", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "go.step.sm/crypto", - sum = "h1:t3p3uQ7raP2jp2ha9P6xkQF85TJZh+87xmjSLaib+jk=", - version = "v0.44.2", - ) - go_repository( - name = "tools_gotest_v3", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gotest.tools/v3", - sum = "h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=", - version = "v3.4.0", - ) - go_repository( - name = "xyz_gomodules_jsonpatch_v2", - build_file_generation = "on", - build_file_proto_mode = "disable_global", - importpath = "gomodules.xyz/jsonpatch/v2", - sum = "h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=", - version = "v2.4.0", - ) diff --git a/bazel/toolchains/go_rules_deps.bzl b/bazel/toolchains/go_rules_deps.bzl deleted file mode 100644 index fcc01d6ba..000000000 --- a/bazel/toolchains/go_rules_deps.bzl +++ /dev/null @@ -1,35 +0,0 @@ -"""Go toolchain dependencies for Bazel. - -Defines hermetic go toolchains and rules to build and test go code. -Gazelle is a build file generator for Bazel projects written in Go. -""" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def go_deps(): - http_archive( - name = "io_bazel_rules_go", - sha256 = "f74c98d6df55217a36859c74b460e774abc0410a47cc100d822be34d5f990f16", - urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.47.1/rules_go-v0.47.1.zip", - "https://cdn.confidential.cloud/constellation/cas/sha256/f74c98d6df55217a36859c74b460e774abc0410a47cc100d822be34d5f990f16", - "https://github.com/bazelbuild/rules_go/releases/download/v0.47.1/rules_go-v0.47.1.zip", - ], - remote_patches = { - # Move timeout handling back to bzltestutil - # remove after https://github.com/bazelbuild/rules_go/pull/3939 is merged - "https://github.com/bazelbuild/rules_go/commit/cc911bfec4f52d93d1c47cc92a3bc03ec8f9cb33.patch": "sha256-Z1jNoEagzSghHrf1SiLLMLGpFq/IBvOjZMxWaIk1O3M=", - }, - remote_patch_strip = 1, - type = "zip", - ) - http_archive( - name = "bazel_gazelle", - sha256 = "75df288c4b31c81eb50f51e2e14f4763cb7548daae126817247064637fd9ea62", - urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.36.0/bazel-gazelle-v0.36.0.tar.gz", - "https://cdn.confidential.cloud/constellation/cas/sha256/75df288c4b31c81eb50f51e2e14f4763cb7548daae126817247064637fd9ea62", - "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.36.0/bazel-gazelle-v0.36.0.tar.gz", - ], - type = "tar.gz", - ) diff --git a/bazel/toolchains/hermetic_cc_deps.bzl b/bazel/toolchains/hermetic_cc_deps.bzl deleted file mode 100644 index db229d47a..000000000 --- a/bazel/toolchains/hermetic_cc_deps.bzl +++ /dev/null @@ -1,16 +0,0 @@ -"""hermetic cc toolchain (bazel-zig-cc) build rules""" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def hermetic_cc_deps(): - """Loads the dependencies for hermetic_cc_toolchain.""" - - http_archive( - name = "hermetic_cc_toolchain", - urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/3bc6ec127622fdceb4129cb06b6f7ab098c4d539124dde96a6318e7c32a53f7a", - "https://github.com/uber/hermetic_cc_toolchain/releases/download/v3.0.1/hermetic_cc_toolchain-v3.0.1.tar.gz", - ], - type = "tar.gz", - sha256 = "3bc6ec127622fdceb4129cb06b6f7ab098c4d539124dde96a6318e7c32a53f7a", - ) diff --git a/bazel/toolchains/multirun_deps.bzl b/bazel/toolchains/multirun_deps.bzl index 0db8f32e9..ee1f3a584 100644 --- a/bazel/toolchains/multirun_deps.bzl +++ b/bazel/toolchains/multirun_deps.bzl @@ -5,11 +5,11 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") def multirun_deps(): http_archive( name = "com_github_ash2k_bazel_tools", - sha256 = "c5c2bb097ef427ab021f522828167c6d85c3e9077763629343282c51dbde03db", - strip_prefix = "bazel-tools-ad2d84beb4e577bda323c8517533b046ed34e6ad", + sha256 = "dc32a65c69c843f1ba2a328b79974163896e5b8ed283cd711abe12bf7cd12ffc", + strip_prefix = "bazel-tools-415483a9e13342a6603a710b0296f6d85b8d26bf", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/c5c2bb097ef427ab021f522828167c6d85c3e9077763629343282c51dbde03db", - "https://github.com/ash2k/bazel-tools/archive/ad2d84beb4e577bda323c8517533b046ed34e6ad.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/dc32a65c69c843f1ba2a328b79974163896e5b8ed283cd711abe12bf7cd12ffc", + "https://github.com/ash2k/bazel-tools/archive/415483a9e13342a6603a710b0296f6d85b8d26bf.tar.gz", ], type = "tar.gz", ) diff --git a/bazel/toolchains/nixpkgs_deps.bzl b/bazel/toolchains/nixpkgs_deps.bzl index d1df61706..c28c10cef 100644 --- a/bazel/toolchains/nixpkgs_deps.bzl +++ b/bazel/toolchains/nixpkgs_deps.bzl @@ -5,11 +5,11 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") def nixpkgs_deps(): http_archive( name = "io_tweag_rules_nixpkgs", - sha256 = "2a555348d7f8593fca2bf3fc6ce53c5d62929de81b6c292e23f16c557c0ae45a", - strip_prefix = "rules_nixpkgs-0.11.1", + sha256 = "1ce13c13a2f354fd37016d9fb333efeddcb308e89db9b3a8f45eafce57746f49", + strip_prefix = "rules_nixpkgs-668609f0b3627751651cb325166d0e95062be3f7", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/2a555348d7f8593fca2bf3fc6ce53c5d62929de81b6c292e23f16c557c0ae45a", - "https://github.com/tweag/rules_nixpkgs/releases/download/v0.11.1/rules_nixpkgs-0.11.1.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/1ce13c13a2f354fd37016d9fb333efeddcb308e89db9b3a8f45eafce57746f49", + "https://github.com/tweag/rules_nixpkgs/archive/668609f0b3627751651cb325166d0e95062be3f7.tar.gz", ], type = "tar.gz", ) diff --git a/bazel/toolchains/oci_deps.bzl b/bazel/toolchains/oci_deps.bzl index 22f5cb148..8cfbecf3b 100644 --- a/bazel/toolchains/oci_deps.bzl +++ b/bazel/toolchains/oci_deps.bzl @@ -7,11 +7,14 @@ def oci_deps(): # Remove this override once https://github.com/bazel-contrib/rules_oci/issues/420 is fixed. http_archive( name = "rules_oci", - strip_prefix = "rules_oci-c622bf79d269473d3d9bc33510e16cfd9a1142bc", + strip_prefix = "rules_oci-2.0.1", type = "tar.gz", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/dca0cfa2a8eb4ab79c231617964fc821f6d1a3bb9d996358975a5ceee5b8d25f", - "https://github.com/bazel-contrib/rules_oci/archive/c622bf79d269473d3d9bc33510e16cfd9a1142bc.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/acbf8f40e062f707f8754e914dcb0013803c6e5e3679d3e05b571a9f5c7e0b43", + "https://cdn.confidential.cloud/constellation/cas/sha256/f70f07f9d0d6c275d7ec7d3c7f236d9b552ba3205e8f37df9c1125031cf967cc", + "https://github.com/bazel-contrib/rules_oci/releases/download/v2.0.1/rules_oci-v2.0.1.tar.gz", ], - sha256 = "dca0cfa2a8eb4ab79c231617964fc821f6d1a3bb9d996358975a5ceee5b8d25f", + sha256 = "acbf8f40e062f707f8754e914dcb0013803c6e5e3679d3e05b571a9f5c7e0b43", + patches = ["//bazel/toolchains:0001-disable-Windows-support.patch"], + patch_args = ["-p1"], ) diff --git a/bazel/toolchains/pkg_deps.bzl b/bazel/toolchains/pkg_deps.bzl deleted file mode 100644 index 5a4928141..000000000 --- a/bazel/toolchains/pkg_deps.bzl +++ /dev/null @@ -1,15 +0,0 @@ -"""rules_pkg dependencies""" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def pkg_deps(): - http_archive( - name = "rules_pkg", - urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.10.1/rules_pkg-0.10.1.tar.gz", - "https://cdn.confidential.cloud/constellation/cas/sha256/d250924a2ecc5176808fc4c25d5cf5e9e79e6346d79d5ab1c493e289e722d1d0", - "https://github.com/bazelbuild/rules_pkg/releases/download/0.10.1/rules_pkg-0.10.1.tar.gz", - ], - sha256 = "d250924a2ecc5176808fc4c25d5cf5e9e79e6346d79d5ab1c493e289e722d1d0", - type = "tar.gz", - ) diff --git a/bazel/toolchains/proto_deps.bzl b/bazel/toolchains/proto_deps.bzl deleted file mode 100644 index 72b02ff09..000000000 --- a/bazel/toolchains/proto_deps.bzl +++ /dev/null @@ -1,15 +0,0 @@ -"""proto toolchain rules""" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def proto_deps(): - http_archive( - name = "rules_proto", - sha256 = "17fa03f509b0d1df05c70c174a266ab211d04b9969e41924fd07a81ea171f117", - strip_prefix = "rules_proto-cda0effe6b5af095a6886c67f90c760b83f08c48", - urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/17fa03f509b0d1df05c70c174a266ab211d04b9969e41924fd07a81ea171f117", - "https://github.com/bazelbuild/rules_proto/archive/cda0effe6b5af095a6886c67f90c760b83f08c48.tar.gz", - ], - type = "tar.gz", - ) diff --git a/bazel/toolchains/python_deps.bzl b/bazel/toolchains/python_deps.bzl deleted file mode 100644 index 329a0a6f6..000000000 --- a/bazel/toolchains/python_deps.bzl +++ /dev/null @@ -1,15 +0,0 @@ -"""python toolchain rules""" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def python_deps(): - http_archive( - name = "rules_python", - strip_prefix = "rules_python-0.31.0", - urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/c68bdc4fbec25de5b5493b8819cfc877c4ea299c0dcb15c244c5a00208cde311", - "https://github.com/bazelbuild/rules_python/releases/download/0.31.0/rules_python-0.31.0.tar.gz", - ], - type = "tar.gz", - sha256 = "c68bdc4fbec25de5b5493b8819cfc877c4ea299c0dcb15c244c5a00208cde311", - ) diff --git a/bazel/toolchains/skylib_deps.bzl b/bazel/toolchains/skylib_deps.bzl deleted file mode 100644 index 28829a504..000000000 --- a/bazel/toolchains/skylib_deps.bzl +++ /dev/null @@ -1,15 +0,0 @@ -"""bazel skylib""" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def skylib_deps(): - http_archive( - name = "bazel_skylib", - sha256 = "9f38886a40548c6e96c106b752f242130ee11aaa068a56ba7e56f4511f33e4f2", - urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.6.1/bazel-skylib-1.6.1.tar.gz", - "https://cdn.confidential.cloud/constellation/cas/sha256/9f38886a40548c6e96c106b752f242130ee11aaa068a56ba7e56f4511f33e4f2", - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.6.1/bazel-skylib-1.6.1.tar.gz", - ], - type = "tar.gz", - ) diff --git a/bootstrapper/cmd/bootstrapper/BUILD.bazel b/bootstrapper/cmd/bootstrapper/BUILD.bazel index 6a8c61c50..77896efe7 100644 --- a/bootstrapper/cmd/bootstrapper/BUILD.bazel +++ b/bootstrapper/cmd/bootstrapper/BUILD.bazel @@ -21,6 +21,7 @@ go_library( "//bootstrapper/internal/kubernetes/k8sapi", "//bootstrapper/internal/kubernetes/kubewaiter", "//bootstrapper/internal/nodelock", + "//bootstrapper/internal/reboot", "//internal/atls", "//internal/attestation/choose", "//internal/attestation/initialize", diff --git a/bootstrapper/cmd/bootstrapper/main.go b/bootstrapper/cmd/bootstrapper/main.go index ff99b231f..ebd5a82c5 100644 --- a/bootstrapper/cmd/bootstrapper/main.go +++ b/bootstrapper/cmd/bootstrapper/main.go @@ -43,16 +43,10 @@ const ( ) func main() { - gRPCDebug := flag.Bool("debug", false, "Enable gRPC debug logging") verbosity := flag.Int("v", 0, logger.CmdLineVerbosityDescription) flag.Parse() log := logger.NewJSONLogger(logger.VerbosityFromInt(*verbosity)).WithGroup("bootstrapper") - - if *gRPCDebug { - logger.ReplaceGRPCLogger(log.WithGroup("gRPC")) - } else { - logger.ReplaceGRPCLogger(slog.New(logger.NewLevelHandler(slog.LevelWarn, log.Handler())).WithGroup("gRPC")) - } + logger.ReplaceGRPCLogger(logger.GRPCLogger(log)) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -86,7 +80,7 @@ func main() { clusterInitJoiner = kubernetes.New( "aws", k8sapi.NewKubernetesUtil(), &k8sapi.KubdeadmConfiguration{}, kubectl.NewUninitialized(), - metadata, &kubewaiter.CloudKubeAPIWaiter{}, + metadata, &kubewaiter.CloudKubeAPIWaiter{}, log, ) openDevice = vtpm.OpenVTPM fs = afero.NewOsFs() @@ -102,7 +96,7 @@ func main() { metadataAPI = metadata clusterInitJoiner = kubernetes.New( "gcp", k8sapi.NewKubernetesUtil(), &k8sapi.KubdeadmConfiguration{}, kubectl.NewUninitialized(), - metadata, &kubewaiter.CloudKubeAPIWaiter{}, + metadata, &kubewaiter.CloudKubeAPIWaiter{}, log, ) openDevice = vtpm.OpenVTPM fs = afero.NewOsFs() @@ -122,7 +116,7 @@ func main() { metadataAPI = metadata clusterInitJoiner = kubernetes.New( "azure", k8sapi.NewKubernetesUtil(), &k8sapi.KubdeadmConfiguration{}, kubectl.NewUninitialized(), - metadata, &kubewaiter.CloudKubeAPIWaiter{}, + metadata, &kubewaiter.CloudKubeAPIWaiter{}, log, ) openDevice = vtpm.OpenVTPM @@ -132,7 +126,7 @@ func main() { metadata := qemucloud.New() clusterInitJoiner = kubernetes.New( "qemu", k8sapi.NewKubernetesUtil(), &k8sapi.KubdeadmConfiguration{}, kubectl.NewUninitialized(), - metadata, &kubewaiter.CloudKubeAPIWaiter{}, + metadata, &kubewaiter.CloudKubeAPIWaiter{}, log, ) metadataAPI = metadata @@ -155,7 +149,7 @@ func main() { } clusterInitJoiner = kubernetes.New( "openstack", k8sapi.NewKubernetesUtil(), &k8sapi.KubdeadmConfiguration{}, kubectl.NewUninitialized(), - metadata, &kubewaiter.CloudKubeAPIWaiter{}, + metadata, &kubewaiter.CloudKubeAPIWaiter{}, log, ) metadataAPI = metadata openDevice = vtpm.OpenVTPM diff --git a/bootstrapper/cmd/bootstrapper/run.go b/bootstrapper/cmd/bootstrapper/run.go index 95bd46b06..815d879ce 100644 --- a/bootstrapper/cmd/bootstrapper/run.go +++ b/bootstrapper/cmd/bootstrapper/run.go @@ -10,17 +10,15 @@ import ( "context" "fmt" "log/slog" - "log/syslog" "net" "sync" - "syscall" - "time" "github.com/edgelesssys/constellation/v2/bootstrapper/internal/clean" "github.com/edgelesssys/constellation/v2/bootstrapper/internal/diskencryption" "github.com/edgelesssys/constellation/v2/bootstrapper/internal/initserver" "github.com/edgelesssys/constellation/v2/bootstrapper/internal/joinclient" "github.com/edgelesssys/constellation/v2/bootstrapper/internal/nodelock" + "github.com/edgelesssys/constellation/v2/bootstrapper/internal/reboot" "github.com/edgelesssys/constellation/v2/internal/atls" "github.com/edgelesssys/constellation/v2/internal/attestation/initialize" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" @@ -46,13 +44,13 @@ func run(issuer atls.Issuer, openDevice vtpm.TPMOpenFunc, fileHandler file.Handl nodeBootstrapped, err := initialize.IsNodeBootstrapped(openDevice) if err != nil { log.With(slog.Any("error", err)).Error("Failed to check if node was previously bootstrapped") - reboot(fmt.Errorf("checking if node was previously bootstrapped: %w", err)) + reboot.Reboot(fmt.Errorf("checking if node was previously bootstrapped: %w", err)) } if nodeBootstrapped { if err := kube.StartKubelet(); err != nil { log.With(slog.Any("error", err)).Error("Failed to restart kubelet") - reboot(fmt.Errorf("restarting kubelet: %w", err)) + reboot.Reboot(fmt.Errorf("restarting kubelet: %w", err)) } return } @@ -61,7 +59,7 @@ func run(issuer atls.Issuer, openDevice vtpm.TPMOpenFunc, fileHandler file.Handl initServer, err := initserver.New(context.Background(), nodeLock, kube, issuer, disk, fileHandler, metadata, log) if err != nil { log.With(slog.Any("error", err)).Error("Failed to create init server") - reboot(fmt.Errorf("creating init server: %w", err)) + reboot.Reboot(fmt.Errorf("creating init server: %w", err)) } dialer := dialer.New(issuer, nil, &net.Dialer{}) @@ -79,7 +77,7 @@ func run(issuer atls.Issuer, openDevice vtpm.TPMOpenFunc, fileHandler file.Handl if err := joinClient.Start(cleaner); err != nil { log.With(slog.Any("error", err)).Error("Failed to join cluster") markDiskForReset(disk) - reboot(fmt.Errorf("joining cluster: %w", err)) + reboot.Reboot(fmt.Errorf("joining cluster: %w", err)) } }() @@ -89,7 +87,7 @@ func run(issuer atls.Issuer, openDevice vtpm.TPMOpenFunc, fileHandler file.Handl if err := initServer.Serve(bindIP, bindPort, cleaner); err != nil { log.With(slog.Any("error", err)).Error("Failed to serve init server") markDiskForReset(disk) - reboot(fmt.Errorf("serving init server: %w", err)) + reboot.Reboot(fmt.Errorf("serving init server: %w", err)) } }() wg.Wait() @@ -122,20 +120,6 @@ func markDiskForReset(disk *diskencryption.DiskEncryption) { _ = disk.MarkDiskForReset() } -// reboot writes an error message to the system log and reboots the system. -// We call this instead of os.Exit() since failures in the bootstrapper usually require a node reset. -func reboot(e error) { - syslogWriter, err := syslog.New(syslog.LOG_EMERG|syslog.LOG_KERN, "bootstrapper") - if err != nil { - _ = syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART) - } - _ = syslogWriter.Err(e.Error()) - _ = syslogWriter.Emerg("bootstrapper has encountered a non recoverable error. Rebooting...") - time.Sleep(time.Minute) // sleep to allow the message to be written to syslog and seen by the user - - _ = syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART) -} - type clusterInitJoiner interface { joinclient.ClusterJoiner initserver.ClusterInitializer diff --git a/bootstrapper/cmd/bootstrapper/test.go b/bootstrapper/cmd/bootstrapper/test.go index 05840de33..d0132ead8 100644 --- a/bootstrapper/cmd/bootstrapper/test.go +++ b/bootstrapper/cmd/bootstrapper/test.go @@ -8,7 +8,6 @@ package main import ( "context" - "log/slog" "github.com/edgelesssys/constellation/v2/internal/cloud/metadata" "github.com/edgelesssys/constellation/v2/internal/role" @@ -22,13 +21,13 @@ type clusterFake struct{} // InitCluster fakes bootstrapping a new cluster with the current node being the master, returning the arguments required to join the cluster. func (c *clusterFake) InitCluster( context.Context, string, string, - bool, components.Components, []string, string, *slog.Logger, + bool, components.Components, []string, string, ) ([]byte, error) { return []byte{}, nil } // JoinCluster will fake joining the current node to an existing cluster. -func (c *clusterFake) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, components.Components, *slog.Logger) error { +func (c *clusterFake) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, components.Components) error { return nil } diff --git a/bootstrapper/initproto/init.pb.go b/bootstrapper/initproto/init.pb.go index 05a6dc25a..324d2d2e2 100644 --- a/bootstrapper/initproto/init.pb.go +++ b/bootstrapper/initproto/init.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.1 -// protoc v4.22.1 +// protoc-gen-go v1.35.1 +// protoc v5.29.0--rc2 // source: bootstrapper/initproto/init.proto package initproto @@ -44,11 +44,9 @@ type InitRequest struct { func (x *InitRequest) Reset() { *x = InitRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_bootstrapper_initproto_init_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_bootstrapper_initproto_init_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *InitRequest) String() string { @@ -59,7 +57,7 @@ func (*InitRequest) ProtoMessage() {} func (x *InitRequest) ProtoReflect() protoreflect.Message { mi := &file_bootstrapper_initproto_init_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -159,11 +157,9 @@ type InitResponse struct { func (x *InitResponse) Reset() { *x = InitResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_bootstrapper_initproto_init_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_bootstrapper_initproto_init_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *InitResponse) String() string { @@ -174,7 +170,7 @@ func (*InitResponse) ProtoMessage() {} func (x *InitResponse) ProtoReflect() protoreflect.Message { mi := &file_bootstrapper_initproto_init_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -251,11 +247,9 @@ type InitSuccessResponse struct { func (x *InitSuccessResponse) Reset() { *x = InitSuccessResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_bootstrapper_initproto_init_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_bootstrapper_initproto_init_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *InitSuccessResponse) String() string { @@ -266,7 +260,7 @@ func (*InitSuccessResponse) ProtoMessage() {} func (x *InitSuccessResponse) ProtoReflect() protoreflect.Message { mi := &file_bootstrapper_initproto_init_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -312,11 +306,9 @@ type InitFailureResponse struct { func (x *InitFailureResponse) Reset() { *x = InitFailureResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_bootstrapper_initproto_init_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_bootstrapper_initproto_init_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *InitFailureResponse) String() string { @@ -327,7 +319,7 @@ func (*InitFailureResponse) ProtoMessage() {} func (x *InitFailureResponse) ProtoReflect() protoreflect.Message { mi := &file_bootstrapper_initproto_init_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -359,11 +351,9 @@ type LogResponseType struct { func (x *LogResponseType) Reset() { *x = LogResponseType{} - if protoimpl.UnsafeEnabled { - mi := &file_bootstrapper_initproto_init_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_bootstrapper_initproto_init_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *LogResponseType) String() string { @@ -374,7 +364,7 @@ func (*LogResponseType) ProtoMessage() {} func (x *LogResponseType) ProtoReflect() protoreflect.Message { mi := &file_bootstrapper_initproto_init_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -409,11 +399,9 @@ type KubernetesComponent struct { func (x *KubernetesComponent) Reset() { *x = KubernetesComponent{} - if protoimpl.UnsafeEnabled { - mi := &file_bootstrapper_initproto_init_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_bootstrapper_initproto_init_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *KubernetesComponent) String() string { @@ -424,7 +412,7 @@ func (*KubernetesComponent) ProtoMessage() {} func (x *KubernetesComponent) ProtoReflect() protoreflect.Message { mi := &file_bootstrapper_initproto_init_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -560,7 +548,7 @@ func file_bootstrapper_initproto_init_proto_rawDescGZIP() []byte { } var file_bootstrapper_initproto_init_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_bootstrapper_initproto_init_proto_goTypes = []interface{}{ +var file_bootstrapper_initproto_init_proto_goTypes = []any{ (*InitRequest)(nil), // 0: init.InitRequest (*InitResponse)(nil), // 1: init.InitResponse (*InitSuccessResponse)(nil), // 2: init.InitSuccessResponse @@ -588,81 +576,7 @@ func file_bootstrapper_initproto_init_proto_init() { if File_bootstrapper_initproto_init_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_bootstrapper_initproto_init_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InitRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_bootstrapper_initproto_init_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InitResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_bootstrapper_initproto_init_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InitSuccessResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_bootstrapper_initproto_init_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InitFailureResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_bootstrapper_initproto_init_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LogResponseType); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_bootstrapper_initproto_init_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KubernetesComponent); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_bootstrapper_initproto_init_proto_msgTypes[1].OneofWrappers = []interface{}{ + file_bootstrapper_initproto_init_proto_msgTypes[1].OneofWrappers = []any{ (*InitResponse_InitSuccess)(nil), (*InitResponse_InitFailure)(nil), (*InitResponse_Log)(nil), diff --git a/bootstrapper/internal/etcdio/BUILD.bazel b/bootstrapper/internal/etcdio/BUILD.bazel new file mode 100644 index 000000000..7f33bd901 --- /dev/null +++ b/bootstrapper/internal/etcdio/BUILD.bazel @@ -0,0 +1,21 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "etcdio", + srcs = [ + "etcdio.go", + "setioprio_cross.go", + "setioprio_linux.go", + ], + importpath = "github.com/edgelesssys/constellation/v2/bootstrapper/internal/etcdio", + visibility = ["//bootstrapper:__subpackages__"], + deps = select({ + "@io_bazel_rules_go//go/platform:android": [ + "@org_golang_x_sys//unix", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "@org_golang_x_sys//unix", + ], + "//conditions:default": [], + }), +) diff --git a/bootstrapper/internal/etcdio/etcdio.go b/bootstrapper/internal/etcdio/etcdio.go new file mode 100644 index 000000000..f9caf7dbb --- /dev/null +++ b/bootstrapper/internal/etcdio/etcdio.go @@ -0,0 +1,154 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +// The etcdio package provides utilities to manage etcd I/O. +package etcdio + +import ( + "context" + "errors" + "fmt" + "log/slog" + "os" + "path" + "strconv" + "time" +) + +var ( + // ErrNoEtcdProcess is returned when no etcd process is found on the node. + ErrNoEtcdProcess = errors.New("no etcd process found on node") + // ErrMultipleEtcdProcesses is returned when multiple etcd processes are found on the node. + ErrMultipleEtcdProcesses = errors.New("multiple etcd processes found on node") +) + +const ( + // Tells the syscall that a process' priority is going to be set. + // See https://elixir.bootlin.com/linux/v6.9.1/source/include/uapi/linux/ioprio.h#L54. + ioPrioWhoProcess = 1 + + // See https://elixir.bootlin.com/linux/v6.9.1/source/include/uapi/linux/ioprio.h#L11. + ioPrioClassShift = 13 + ioPrioNrClasses = 8 + ioPrioClassMask = ioPrioNrClasses - 1 + ioPrioPrioMask = (1 << ioPrioClassShift) - 1 + + targetClass = 1 // Realtime IO class for best scheduling prio + targetPrio = 0 // Highest priority within the class +) + +// Client is a client for managing etcd I/O. +type Client struct { + log *slog.Logger +} + +// NewClient creates a new etcd I/O management client. +func NewClient(log *slog.Logger) *Client { + return &Client{log: log} +} + +// PrioritizeIO tries to prioritize the I/O of the etcd process. +// Since it might be possible that the process just started (if this method is called +// right after the kubelet started), it retries to do its work each second +// until it succeeds or the timeout of 10 seconds is reached. +func (c *Client) PrioritizeIO() { + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + timeout, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + for { + c.log.Info("Prioritizing etcd I/O") + err := c.setIOPriority() + if err == nil { + // Success, return directly + return + } else if errors.Is(err, ErrNoEtcdProcess) { + c.log.Info("No etcd process found, retrying") + } else { + c.log.Warn("Prioritizing etcd I/O failed", "error", err) + return + } + + select { + case <-ticker.C: + case <-timeout.Done(): + c.log.Warn("Timed out waiting for etcd to start") + return + } + } +} + +// setIOPriority tries to find the etcd process on the node and prioritizes its I/O. +func (c *Client) setIOPriority() error { + // find etcd process(es) + pid, err := c.findEtcdProcess() + if err != nil { + return fmt.Errorf("finding etcd process: %w", err) + } + + // Highest realtime priority value for the etcd process, see https://elixir.bootlin.com/linux/v6.9.1/source/include/uapi/linux/ioprio.h + // for the calculation details. + prioVal := ((targetClass & ioPrioClassMask) << ioPrioClassShift) | (targetPrio & ioPrioPrioMask) + + // see https://man7.org/linux/man-pages/man2/ioprio_set.2.html + ret, _, errno := setioprio(ioPrioWhoProcess, uintptr(pid), uintptr(prioVal)) + if ret != 0 { + return fmt.Errorf("setting I/O priority for etcd: %w", errno) + } + + return nil +} + +// findEtcdProcess tries to find the etcd process on the node. +func (c *Client) findEtcdProcess() (int, error) { + procDir, err := os.Open("/proc") + if err != nil { + return 0, fmt.Errorf("opening /proc: %w", err) + } + defer procDir.Close() + + procEntries, err := procDir.Readdirnames(0) + if err != nil { + return 0, fmt.Errorf("reading /proc: %w", err) + } + + // find etcd process(es) + etcdPIDs := []int{} + for _, f := range procEntries { + // exclude non-pid dirs + if f[0] < '0' || f[0] > '9' { + continue + } + + exe, err := os.Readlink(fmt.Sprintf("/proc/%s/exe", f)) + if err != nil { + continue + } + + if path.Base(exe) != "etcd" { + continue + } + + pid, err := strconv.Atoi(f) + if err != nil { + continue + } + + // add the PID to the list of etcd PIDs + etcdPIDs = append(etcdPIDs, pid) + } + + if len(etcdPIDs) == 0 { + return 0, ErrNoEtcdProcess + } + + if len(etcdPIDs) > 1 { + return 0, ErrMultipleEtcdProcesses + } + + return etcdPIDs[0], nil +} diff --git a/bootstrapper/internal/etcdio/setioprio_cross.go b/bootstrapper/internal/etcdio/setioprio_cross.go new file mode 100644 index 000000000..6422f0c60 --- /dev/null +++ b/bootstrapper/internal/etcdio/setioprio_cross.go @@ -0,0 +1,17 @@ +//go:build !linux + +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package etcdio + +import ( + "syscall" +) + +func setioprio(_, _, _ uintptr) (uintptr, uintptr, syscall.Errno) { + panic("setioprio not implemented on non-Linux platforms") +} diff --git a/bootstrapper/internal/etcdio/setioprio_linux.go b/bootstrapper/internal/etcdio/setioprio_linux.go new file mode 100644 index 000000000..61d82248f --- /dev/null +++ b/bootstrapper/internal/etcdio/setioprio_linux.go @@ -0,0 +1,19 @@ +//go:build linux + +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package etcdio + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +func setioprio(ioPrioWhoProcess, pid, prioVal uintptr) (uintptr, uintptr, syscall.Errno) { + return unix.Syscall(unix.SYS_IOPRIO_SET, ioPrioWhoProcess, pid, prioVal) +} diff --git a/bootstrapper/internal/initserver/BUILD.bazel b/bootstrapper/internal/initserver/BUILD.bazel index b1d5e66ba..3ad04343c 100644 --- a/bootstrapper/internal/initserver/BUILD.bazel +++ b/bootstrapper/internal/initserver/BUILD.bazel @@ -21,7 +21,7 @@ go_library( "//internal/nodestate", "//internal/role", "//internal/versions/components", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//keepalive", "@org_golang_google_grpc//status", @@ -50,7 +50,7 @@ go_test( "@com_github_spf13_afero//:afero", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_x_crypto//bcrypt", "@org_uber_go_goleak//:goleak", ], diff --git a/bootstrapper/internal/initserver/initserver.go b/bootstrapper/internal/initserver/initserver.go index a38bdbc8d..a65a5f8b7 100644 --- a/bootstrapper/internal/initserver/initserver.go +++ b/bootstrapper/internal/initserver/initserver.go @@ -109,7 +109,7 @@ func New( grpcServer := grpc.NewServer( grpc.Creds(atlscredentials.New(issuer, nil)), grpc.KeepaliveParams(keepalive.ServerParameters{Time: 15 * time.Second}), - logger.GetServerUnaryInterceptor(log.WithGroup("gRPC")), + logger.GetServerUnaryInterceptor(logger.GRPCLogger(log)), ) initproto.RegisterAPIServer(grpcServer, server) @@ -234,7 +234,6 @@ func (s *Server) Init(req *initproto.InitRequest, stream initproto.API_InitServe req.KubernetesComponents, req.ApiserverCertSans, req.ServiceCidr, - s.log, ) if err != nil { if e := s.sendLogsWithMessage(stream, status.Errorf(codes.Internal, "initializing cluster: %s", err)); e != nil { @@ -357,7 +356,6 @@ type ClusterInitializer interface { kubernetesComponents components.Components, apiServerCertSANs []string, serviceCIDR string, - log *slog.Logger, ) ([]byte, error) } diff --git a/bootstrapper/internal/initserver/initserver_test.go b/bootstrapper/internal/initserver/initserver_test.go index 84d0316d7..0d9f25db4 100644 --- a/bootstrapper/internal/initserver/initserver_test.go +++ b/bootstrapper/internal/initserver/initserver_test.go @@ -11,7 +11,6 @@ import ( "context" "errors" "io" - "log/slog" "net" "strings" "sync" @@ -420,7 +419,7 @@ type stubClusterInitializer struct { func (i *stubClusterInitializer) InitCluster( context.Context, string, string, - bool, components.Components, []string, string, *slog.Logger, + bool, components.Components, []string, string, ) ([]byte, error) { return i.initClusterKubeconfig, i.initClusterErr } diff --git a/bootstrapper/internal/joinclient/BUILD.bazel b/bootstrapper/internal/joinclient/BUILD.bazel index 687ffd250..048df72ac 100644 --- a/bootstrapper/internal/joinclient/BUILD.bazel +++ b/bootstrapper/internal/joinclient/BUILD.bazel @@ -20,7 +20,7 @@ go_library( "@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm/v1beta3", "@io_k8s_kubernetes//cmd/kubeadm/app/constants", "@io_k8s_utils//clock", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", ], ) @@ -48,7 +48,7 @@ go_test( "@com_github_stretchr_testify//require", "@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm/v1beta3", "@io_k8s_utils//clock/testing", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_uber_go_goleak//:goleak", ], ) diff --git a/bootstrapper/internal/joinclient/joinclient.go b/bootstrapper/internal/joinclient/joinclient.go index 3e2944325..37c9e9b8f 100644 --- a/bootstrapper/internal/joinclient/joinclient.go +++ b/bootstrapper/internal/joinclient/joinclient.go @@ -173,13 +173,13 @@ func (c *JoinClient) tryJoinWithAvailableServices() (ticket *joinproto.IssueJoin endpoint, _, err := c.metadataAPI.GetLoadBalancerEndpoint(ctx) if err != nil { - return nil, nil, fmt.Errorf("failed to get load balancer endpoint: %w", err) + c.log.Warn("Failed to get load balancer endpoint", "err", err) } endpoints = append(endpoints, endpoint) ips, err := c.getControlPlaneIPs(ctx) if err != nil { - return nil, nil, fmt.Errorf("failed to get control plane IPs: %w", err) + c.log.Warn("Failed to get control plane IPs", "err", err) } endpoints = append(endpoints, ips...) @@ -209,7 +209,7 @@ func (c *JoinClient) requestJoinTicket(serviceEndpoint string) (ticket *joinprot return nil, nil, err } - conn, err := c.dialer.Dial(ctx, serviceEndpoint) + conn, err := c.dialer.Dial(serviceEndpoint) if err != nil { c.log.With(slog.String("endpoint", serviceEndpoint), slog.Any("error", err)).Error("Join service unreachable") return nil, nil, fmt.Errorf("dialing join service endpoint: %w", err) @@ -288,7 +288,7 @@ func (c *JoinClient) startNodeAndJoin(ticket *joinproto.IssueJoinTicketResponse, // We currently cannot recover from any failure in this function. Joining the k8s cluster // sometimes fails transiently, and we don't want to brick the node because of that. for i := range 3 { - err = c.joiner.JoinCluster(ctx, btd, c.role, ticket.KubernetesComponents, c.log) + err = c.joiner.JoinCluster(ctx, btd, c.role, ticket.KubernetesComponents) if err == nil { break } @@ -388,7 +388,7 @@ func (c *JoinClient) timeoutCtx() (context.Context, context.CancelFunc) { } type grpcDialer interface { - Dial(ctx context.Context, target string) (*grpc.ClientConn, error) + Dial(target string) (*grpc.ClientConn, error) } // ClusterJoiner has the ability to join a new node to an existing cluster. @@ -399,7 +399,6 @@ type ClusterJoiner interface { args *kubeadm.BootstrapTokenDiscovery, peerRole role.Role, k8sComponents components.Components, - log *slog.Logger, ) error } diff --git a/bootstrapper/internal/joinclient/joinclient_test.go b/bootstrapper/internal/joinclient/joinclient_test.go index a93ed4b3f..6a0b89f4b 100644 --- a/bootstrapper/internal/joinclient/joinclient_test.go +++ b/bootstrapper/internal/joinclient/joinclient_test.go @@ -8,7 +8,6 @@ package joinclient import ( "context" - "log/slog" "net" "strconv" "sync" @@ -350,7 +349,7 @@ type stubClusterJoiner struct { joinClusterErr error } -func (j *stubClusterJoiner) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, components.Components, *slog.Logger) error { +func (j *stubClusterJoiner) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, components.Components) error { j.joinClusterCalled++ if j.numBadCalls == 0 { return nil diff --git a/bootstrapper/internal/kubernetes/BUILD.bazel b/bootstrapper/internal/kubernetes/BUILD.bazel index d6ba14a49..935c3fefd 100644 --- a/bootstrapper/internal/kubernetes/BUILD.bazel +++ b/bootstrapper/internal/kubernetes/BUILD.bazel @@ -11,6 +11,7 @@ go_library( importpath = "github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes", visibility = ["//bootstrapper:__subpackages__"], deps = [ + "//bootstrapper/internal/etcdio", "//bootstrapper/internal/kubernetes/k8sapi", "//bootstrapper/internal/kubernetes/kubewaiter", "//internal/cloud/cloudprovider", diff --git a/bootstrapper/internal/kubernetes/k8sapi/k8sutil.go b/bootstrapper/internal/kubernetes/k8sapi/k8sutil.go index 53f681b49..d2ec6e78f 100644 --- a/bootstrapper/internal/kubernetes/k8sapi/k8sutil.go +++ b/bootstrapper/internal/kubernetes/k8sapi/k8sutil.go @@ -48,7 +48,6 @@ type Client interface { AddNodeSelectorsToDeployment(ctx context.Context, selectors map[string]string, name string, namespace string) error ListAllNamespaces(ctx context.Context) (*corev1.NamespaceList, error) AnnotateNode(ctx context.Context, nodeName, annotationKey, annotationValue string) error - EnforceCoreDNSSpread(ctx context.Context) error PatchFirstNodePodCIDR(ctx context.Context, firstNodePodCIDR string) error } @@ -137,6 +136,12 @@ func (k *KubernetesUtil) InitCluster( } // Create static pods directory for all nodes (the Kubelets on the worker nodes also expect the path to exist) + // If the node rebooted after the static pod directory was created, + // the existing directory needs to be removed before we can + // try to init the cluster again. + if err := os.RemoveAll("/etc/kubernetes/manifests"); err != nil { + return nil, fmt.Errorf("removing static pods directory: %w", err) + } log.Info("Creating static Pod directory /etc/kubernetes/manifests") if err := os.MkdirAll("/etc/kubernetes/manifests", os.ModePerm); err != nil { return nil, fmt.Errorf("creating static pods directory: %w", err) @@ -144,7 +149,7 @@ func (k *KubernetesUtil) InitCluster( // initialize the cluster log.Info("Initializing the cluster using kubeadm init") - skipPhases := "--skip-phases=preflight,certs" + skipPhases := "--skip-phases=preflight,certs,addon/coredns" if !conformanceMode { skipPhases += ",addon/kube-proxy" } @@ -200,6 +205,12 @@ func (k *KubernetesUtil) JoinCluster(ctx context.Context, joinConfig []byte, log } // Create static pods directory for all nodes (the Kubelets on the worker nodes also expect the path to exist) + // If the node rebooted after the static pod directory was created, for example + // if a failure during an upgrade occurred, the existing directory needs to be + // removed before we can try to join the cluster again. + if err := os.RemoveAll("/etc/kubernetes/manifests"); err != nil { + return fmt.Errorf("removing static pods directory: %w", err) + } log.Info("Creating static Pod directory /etc/kubernetes/manifests") if err := os.MkdirAll("/etc/kubernetes/manifests", os.ModePerm); err != nil { return fmt.Errorf("creating static pods directory: %w", err) diff --git a/bootstrapper/internal/kubernetes/kubernetes.go b/bootstrapper/internal/kubernetes/kubernetes.go index 5ef1f4637..13c387d23 100644 --- a/bootstrapper/internal/kubernetes/kubernetes.go +++ b/bootstrapper/internal/kubernetes/kubernetes.go @@ -16,6 +16,7 @@ import ( "strings" "time" + "github.com/edgelesssys/constellation/v2/bootstrapper/internal/etcdio" "github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes/k8sapi" "github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes/kubewaiter" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" @@ -40,37 +41,48 @@ type kubeAPIWaiter interface { Wait(ctx context.Context, kubernetesClient kubewaiter.KubernetesClient) error } +type etcdIOPrioritizer interface { + PrioritizeIO() +} + // KubeWrapper implements Cluster interface. type KubeWrapper struct { - cloudProvider string - clusterUtil clusterUtil - kubeAPIWaiter kubeAPIWaiter - configProvider configurationProvider - client k8sapi.Client - providerMetadata ProviderMetadata - getIPAddr func() (string, error) + cloudProvider string + clusterUtil clusterUtil + kubeAPIWaiter kubeAPIWaiter + configProvider configurationProvider + client k8sapi.Client + providerMetadata ProviderMetadata + etcdIOPrioritizer etcdIOPrioritizer + getIPAddr func() (string, error) + + log *slog.Logger } // New creates a new KubeWrapper with real values. func New(cloudProvider string, clusterUtil clusterUtil, configProvider configurationProvider, client k8sapi.Client, - providerMetadata ProviderMetadata, kubeAPIWaiter kubeAPIWaiter, + providerMetadata ProviderMetadata, kubeAPIWaiter kubeAPIWaiter, log *slog.Logger, ) *KubeWrapper { + etcdIOPrioritizer := etcdio.NewClient(log) + return &KubeWrapper{ - cloudProvider: cloudProvider, - clusterUtil: clusterUtil, - kubeAPIWaiter: kubeAPIWaiter, - configProvider: configProvider, - client: client, - providerMetadata: providerMetadata, - getIPAddr: getIPAddr, + cloudProvider: cloudProvider, + clusterUtil: clusterUtil, + kubeAPIWaiter: kubeAPIWaiter, + configProvider: configProvider, + client: client, + providerMetadata: providerMetadata, + getIPAddr: getIPAddr, + log: log, + etcdIOPrioritizer: etcdIOPrioritizer, } } // InitCluster initializes a new Kubernetes cluster and applies pod network provider. func (k *KubeWrapper) InitCluster( - ctx context.Context, versionString, clusterName string, conformanceMode bool, kubernetesComponents components.Components, apiServerCertSANs []string, serviceCIDR string, log *slog.Logger, + ctx context.Context, versionString, clusterName string, conformanceMode bool, kubernetesComponents components.Components, apiServerCertSANs []string, serviceCIDR string, ) ([]byte, error) { - log.With(slog.String("version", versionString)).Info("Installing Kubernetes components") + k.log.With(slog.String("version", versionString)).Info("Installing Kubernetes components") if err := k.clusterUtil.InstallComponents(ctx, kubernetesComponents); err != nil { return nil, err } @@ -78,7 +90,7 @@ func (k *KubeWrapper) InitCluster( var validIPs []net.IP // Step 1: retrieve cloud metadata for Kubernetes configuration - log.Info("Retrieving node metadata") + k.log.Info("Retrieving node metadata") instance, err := k.providerMetadata.Self(ctx) if err != nil { return nil, fmt.Errorf("retrieving own instance metadata: %w", err) @@ -106,7 +118,7 @@ func (k *KubeWrapper) InitCluster( certSANs := []string{nodeIP} certSANs = append(certSANs, apiServerCertSANs...) - log.With( + k.log.With( slog.String("nodeName", nodeName), slog.String("providerID", instance.ProviderID), slog.String("nodeIP", nodeIP), @@ -132,12 +144,16 @@ func (k *KubeWrapper) InitCluster( if err != nil { return nil, fmt.Errorf("encoding kubeadm init configuration as YAML: %w", err) } - log.Info("Initializing Kubernetes cluster") - kubeConfig, err := k.clusterUtil.InitCluster(ctx, initConfigYAML, nodeName, clusterName, validIPs, conformanceMode, log) + + k.log.Info("Initializing Kubernetes cluster") + kubeConfig, err := k.clusterUtil.InitCluster(ctx, initConfigYAML, nodeName, clusterName, validIPs, conformanceMode, k.log) if err != nil { return nil, fmt.Errorf("kubeadm init: %w", err) } + k.log.Info("Prioritizing etcd I/O") + k.etcdIOPrioritizer.PrioritizeIO() + err = k.client.Initialize(kubeConfig) if err != nil { return nil, fmt.Errorf("initializing kubectl client: %w", err) @@ -149,10 +165,6 @@ func (k *KubeWrapper) InitCluster( return nil, fmt.Errorf("waiting for Kubernetes API to be available: %w", err) } - if err := k.client.EnforceCoreDNSSpread(ctx); err != nil { - return nil, fmt.Errorf("configuring CoreDNS deployment: %w", err) - } - // Setup the K8s components ConfigMap. k8sComponentsConfigMap, err := k.setupK8sComponentsConfigMap(ctx, kubernetesComponents, versionString) if err != nil { @@ -177,22 +189,23 @@ func (k *KubeWrapper) InitCluster( return nil, fmt.Errorf("annotating node with Kubernetes components hash: %w", err) } - log.Info("Setting up internal-config ConfigMap") + k.log.Info("Setting up internal-config ConfigMap") if err := k.setupInternalConfigMap(ctx); err != nil { return nil, fmt.Errorf("failed to setup internal ConfigMap: %w", err) } + return kubeConfig, nil } // JoinCluster joins existing Kubernetes cluster. -func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTokenDiscovery, peerRole role.Role, k8sComponents components.Components, log *slog.Logger) error { - log.With("k8sComponents", k8sComponents).Info("Installing provided kubernetes components") +func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTokenDiscovery, peerRole role.Role, k8sComponents components.Components) error { + k.log.With("k8sComponents", k8sComponents).Info("Installing provided kubernetes components") if err := k.clusterUtil.InstallComponents(ctx, k8sComponents); err != nil { return fmt.Errorf("installing kubernetes components: %w", err) } // Step 1: retrieve cloud metadata for Kubernetes configuration - log.Info("Retrieving node metadata") + k.log.Info("Retrieving node metadata") instance, err := k.providerMetadata.Self(ctx) if err != nil { return fmt.Errorf("retrieving own instance metadata: %w", err) @@ -212,7 +225,7 @@ func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTo // override join endpoint to go over lb args.APIServerEndpoint = net.JoinHostPort(loadBalancerHost, loadBalancerPort) - log.With( + k.log.With( slog.String("nodeName", nodeName), slog.String("providerID", providerID), slog.String("nodeIP", nodeInternalIP), @@ -237,11 +250,18 @@ func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTo if err != nil { return fmt.Errorf("encoding kubeadm join configuration as YAML: %w", err) } - log.With(slog.String("apiServerEndpoint", args.APIServerEndpoint)).Info("Joining Kubernetes cluster") - if err := k.clusterUtil.JoinCluster(ctx, joinConfigYAML, log); err != nil { + + k.log.With(slog.String("apiServerEndpoint", args.APIServerEndpoint)).Info("Joining Kubernetes cluster") + if err := k.clusterUtil.JoinCluster(ctx, joinConfigYAML, k.log); err != nil { return fmt.Errorf("joining cluster: %v; %w ", string(joinConfigYAML), err) } + // If on control plane (and thus with etcd), try to prioritize etcd I/O. + if peerRole == role.ControlPlane { + k.log.Info("Prioritizing etcd I/O") + k.etcdIOPrioritizer.PrioritizeIO() + } + return nil } @@ -301,6 +321,8 @@ func (k *KubeWrapper) StartKubelet() error { return fmt.Errorf("starting kubelet: %w", err) } + k.etcdIOPrioritizer.PrioritizeIO() + return nil } diff --git a/bootstrapper/internal/kubernetes/kubernetes_test.go b/bootstrapper/internal/kubernetes/kubernetes_test.go index ccc3a107c..bef50253d 100644 --- a/bootstrapper/internal/kubernetes/kubernetes_test.go +++ b/bootstrapper/internal/kubernetes/kubernetes_test.go @@ -42,17 +42,19 @@ func TestInitCluster(t *testing.T) { aliasIPRange := "192.0.2.0/24" testCases := map[string]struct { - clusterUtil stubClusterUtil - kubectl stubKubectl - kubeAPIWaiter stubKubeAPIWaiter - providerMetadata ProviderMetadata - wantConfig k8sapi.KubeadmInitYAML - wantErr bool - k8sVersion versions.ValidK8sVersion + clusterUtil stubClusterUtil + kubectl stubKubectl + kubeAPIWaiter stubKubeAPIWaiter + providerMetadata ProviderMetadata + wantConfig k8sapi.KubeadmInitYAML + etcdIOPrioritizer stubEtcdIOPrioritizer + wantErr bool + k8sVersion versions.ValidK8sVersion }{ "kubeadm init works with metadata and loadbalancer": { - clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, - kubeAPIWaiter: stubKubeAPIWaiter{}, + clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + kubeAPIWaiter: stubKubeAPIWaiter{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, providerMetadata: &stubProviderMetadata{ selfResp: metadata.InstanceMetadata{ Name: nodeName, @@ -85,8 +87,9 @@ func TestInitCluster(t *testing.T) { k8sVersion: versions.Default, }, "kubeadm init fails when annotating itself": { - clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, - kubeAPIWaiter: stubKubeAPIWaiter{}, + clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + kubeAPIWaiter: stubKubeAPIWaiter{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, providerMetadata: &stubProviderMetadata{ selfResp: metadata.InstanceMetadata{ Name: nodeName, @@ -102,8 +105,9 @@ func TestInitCluster(t *testing.T) { k8sVersion: versions.Default, }, "kubeadm init fails when retrieving metadata self": { - clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, - kubeAPIWaiter: stubKubeAPIWaiter{}, + clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + kubeAPIWaiter: stubKubeAPIWaiter{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, providerMetadata: &stubProviderMetadata{ selfErr: assert.AnError, }, @@ -111,7 +115,8 @@ func TestInitCluster(t *testing.T) { k8sVersion: versions.Default, }, "kubeadm init fails when retrieving metadata loadbalancer ip": { - clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, providerMetadata: &stubProviderMetadata{ getLoadBalancerEndpointErr: assert.AnError, }, @@ -123,51 +128,58 @@ func TestInitCluster(t *testing.T) { initClusterErr: assert.AnError, kubeconfig: []byte("someKubeconfig"), }, - kubeAPIWaiter: stubKubeAPIWaiter{}, - providerMetadata: &stubProviderMetadata{}, - wantErr: true, - k8sVersion: versions.Default, + kubeAPIWaiter: stubKubeAPIWaiter{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, + providerMetadata: &stubProviderMetadata{}, + wantErr: true, + k8sVersion: versions.Default, }, "kubeadm init fails when deploying cilium": { - clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, - providerMetadata: &stubProviderMetadata{}, - wantErr: true, - k8sVersion: versions.Default, + clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, + providerMetadata: &stubProviderMetadata{}, + wantErr: true, + k8sVersion: versions.Default, }, "kubeadm init fails when setting up constellation-services chart": { - clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, - kubeAPIWaiter: stubKubeAPIWaiter{}, - providerMetadata: &stubProviderMetadata{}, - wantErr: true, - k8sVersion: versions.Default, + clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + kubeAPIWaiter: stubKubeAPIWaiter{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, + providerMetadata: &stubProviderMetadata{}, + wantErr: true, + k8sVersion: versions.Default, }, "kubeadm init fails when reading kubeconfig": { - clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, - kubeAPIWaiter: stubKubeAPIWaiter{}, - providerMetadata: &stubProviderMetadata{}, - wantErr: true, - k8sVersion: versions.Default, + clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + kubeAPIWaiter: stubKubeAPIWaiter{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, + providerMetadata: &stubProviderMetadata{}, + wantErr: true, + k8sVersion: versions.Default, }, "kubeadm init fails when setting up verification service": { - clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, - kubeAPIWaiter: stubKubeAPIWaiter{}, - providerMetadata: &stubProviderMetadata{}, - wantErr: true, - k8sVersion: versions.Default, + clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + kubeAPIWaiter: stubKubeAPIWaiter{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, + providerMetadata: &stubProviderMetadata{}, + wantErr: true, + k8sVersion: versions.Default, }, "kubeadm init fails when waiting for kubeAPI server": { - clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, - kubeAPIWaiter: stubKubeAPIWaiter{waitErr: assert.AnError}, - providerMetadata: &stubProviderMetadata{}, - k8sVersion: versions.Default, - wantErr: true, + clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + kubeAPIWaiter: stubKubeAPIWaiter{waitErr: assert.AnError}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, + providerMetadata: &stubProviderMetadata{}, + k8sVersion: versions.Default, + wantErr: true, }, "unsupported k8sVersion fails cluster creation": { - clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, - kubeAPIWaiter: stubKubeAPIWaiter{}, - providerMetadata: &stubProviderMetadata{}, - k8sVersion: "1.19", - wantErr: true, + clusterUtil: stubClusterUtil{kubeconfig: []byte("someKubeconfig")}, + kubeAPIWaiter: stubKubeAPIWaiter{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, + providerMetadata: &stubProviderMetadata{}, + k8sVersion: "1.19", + wantErr: true, }, } @@ -177,18 +189,20 @@ func TestInitCluster(t *testing.T) { require := require.New(t) kube := KubeWrapper{ - cloudProvider: "aws", // provide a valid cloud provider for cilium installation - clusterUtil: &tc.clusterUtil, - providerMetadata: tc.providerMetadata, - kubeAPIWaiter: &tc.kubeAPIWaiter, - configProvider: &stubConfigProvider{initConfig: k8sapi.KubeadmInitYAML{}}, - client: &tc.kubectl, - getIPAddr: func() (string, error) { return privateIP, nil }, + cloudProvider: "aws", // provide a valid cloud provider for cilium installation + clusterUtil: &tc.clusterUtil, + providerMetadata: tc.providerMetadata, + kubeAPIWaiter: &tc.kubeAPIWaiter, + configProvider: &stubConfigProvider{initConfig: k8sapi.KubeadmInitYAML{}}, + client: &tc.kubectl, + getIPAddr: func() (string, error) { return privateIP, nil }, + etcdIOPrioritizer: &tc.etcdIOPrioritizer, + log: logger.NewTest(t), } _, err := kube.InitCluster( context.Background(), string(tc.k8sVersion), "kubernetes", - false, nil, nil, "", logger.NewTest(t), + false, nil, nil, "", ) if tc.wantErr { @@ -224,15 +238,17 @@ func TestJoinCluster(t *testing.T) { } testCases := map[string]struct { - clusterUtil stubClusterUtil - providerMetadata ProviderMetadata - wantConfig kubeadm.JoinConfiguration - role role.Role - k8sComponents components.Components - wantErr bool + clusterUtil stubClusterUtil + providerMetadata ProviderMetadata + wantConfig kubeadm.JoinConfiguration + role role.Role + k8sComponents components.Components + etcdIOPrioritizer stubEtcdIOPrioritizer + wantErr bool }{ "kubeadm join worker works with metadata and remote Kubernetes Components": { - clusterUtil: stubClusterUtil{}, + clusterUtil: stubClusterUtil{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, providerMetadata: &stubProviderMetadata{ selfResp: metadata.InstanceMetadata{ ProviderID: "provider-id", @@ -253,7 +269,8 @@ func TestJoinCluster(t *testing.T) { }, }, "kubeadm join worker works with metadata and local Kubernetes components": { - clusterUtil: stubClusterUtil{}, + clusterUtil: stubClusterUtil{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, providerMetadata: &stubProviderMetadata{ selfResp: metadata.InstanceMetadata{ ProviderID: "provider-id", @@ -273,7 +290,8 @@ func TestJoinCluster(t *testing.T) { }, }, "kubeadm join worker works with metadata and cloud controller manager": { - clusterUtil: stubClusterUtil{}, + clusterUtil: stubClusterUtil{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, providerMetadata: &stubProviderMetadata{ selfResp: metadata.InstanceMetadata{ ProviderID: "provider-id", @@ -293,7 +311,8 @@ func TestJoinCluster(t *testing.T) { }, }, "kubeadm join control-plane node works with metadata": { - clusterUtil: stubClusterUtil{}, + clusterUtil: stubClusterUtil{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, providerMetadata: &stubProviderMetadata{ selfResp: metadata.InstanceMetadata{ ProviderID: "provider-id", @@ -320,7 +339,8 @@ func TestJoinCluster(t *testing.T) { }, }, "kubeadm join worker fails when installing remote Kubernetes components": { - clusterUtil: stubClusterUtil{installComponentsErr: errors.New("error")}, + clusterUtil: stubClusterUtil{installComponentsErr: errors.New("error")}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, providerMetadata: &stubProviderMetadata{ selfResp: metadata.InstanceMetadata{ ProviderID: "provider-id", @@ -333,7 +353,8 @@ func TestJoinCluster(t *testing.T) { wantErr: true, }, "kubeadm join worker fails when retrieving self metadata": { - clusterUtil: stubClusterUtil{}, + clusterUtil: stubClusterUtil{}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, providerMetadata: &stubProviderMetadata{ selfErr: assert.AnError, }, @@ -341,10 +362,11 @@ func TestJoinCluster(t *testing.T) { wantErr: true, }, "kubeadm join worker fails when applying the join config": { - clusterUtil: stubClusterUtil{joinClusterErr: assert.AnError}, - providerMetadata: &stubProviderMetadata{}, - role: role.Worker, - wantErr: true, + clusterUtil: stubClusterUtil{joinClusterErr: assert.AnError}, + etcdIOPrioritizer: stubEtcdIOPrioritizer{}, + providerMetadata: &stubProviderMetadata{}, + role: role.Worker, + wantErr: true, }, } @@ -354,13 +376,15 @@ func TestJoinCluster(t *testing.T) { require := require.New(t) kube := KubeWrapper{ - clusterUtil: &tc.clusterUtil, - providerMetadata: tc.providerMetadata, - configProvider: &stubConfigProvider{}, - getIPAddr: func() (string, error) { return privateIP, nil }, + clusterUtil: &tc.clusterUtil, + providerMetadata: tc.providerMetadata, + configProvider: &stubConfigProvider{}, + getIPAddr: func() (string, error) { return privateIP, nil }, + etcdIOPrioritizer: &tc.etcdIOPrioritizer, + log: logger.NewTest(t), } - err := kube.JoinCluster(context.Background(), joinCommand, tc.role, tc.k8sComponents, logger.NewTest(t)) + err := kube.JoinCluster(context.Background(), joinCommand, tc.role, tc.k8sComponents) if tc.wantErr { assert.Error(err) return @@ -545,3 +569,7 @@ type stubKubeAPIWaiter struct { func (s *stubKubeAPIWaiter) Wait(_ context.Context, _ kubewaiter.KubernetesClient) error { return s.waitErr } + +type stubEtcdIOPrioritizer struct{} + +func (s *stubEtcdIOPrioritizer) PrioritizeIO() {} diff --git a/bootstrapper/internal/reboot/BUILD.bazel b/bootstrapper/internal/reboot/BUILD.bazel new file mode 100644 index 000000000..ce71293b3 --- /dev/null +++ b/bootstrapper/internal/reboot/BUILD.bazel @@ -0,0 +1,11 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "reboot", + srcs = [ + "reboot_cross.go", + "reboot_linux.go", + ], + importpath = "github.com/edgelesssys/constellation/v2/bootstrapper/internal/reboot", + visibility = ["//bootstrapper:__subpackages__"], +) diff --git a/bootstrapper/internal/reboot/reboot_cross.go b/bootstrapper/internal/reboot/reboot_cross.go new file mode 100644 index 000000000..708749461 --- /dev/null +++ b/bootstrapper/internal/reboot/reboot_cross.go @@ -0,0 +1,14 @@ +//go:build !linux + +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package reboot + +// Reboot is not implemented on non-Linux platforms. +func Reboot(_ error) { + panic("reboot not implemented on non-Linux platforms") +} diff --git a/bootstrapper/internal/reboot/reboot_linux.go b/bootstrapper/internal/reboot/reboot_linux.go new file mode 100644 index 000000000..c39d1cce9 --- /dev/null +++ b/bootstrapper/internal/reboot/reboot_linux.go @@ -0,0 +1,29 @@ +//go:build linux + +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package reboot + +import ( + "log/syslog" + "syscall" + "time" +) + +// Reboot writes an error message to the system log and reboots the system. +// We call this instead of os.Exit() since failures in the bootstrapper usually require a node reset. +func Reboot(e error) { + syslogWriter, err := syslog.New(syslog.LOG_EMERG|syslog.LOG_KERN, "bootstrapper") + if err != nil { + _ = syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART) + } + _ = syslogWriter.Err(e.Error()) + _ = syslogWriter.Emerg("bootstrapper has encountered a non recoverable error. Rebooting...") + time.Sleep(time.Minute) // sleep to allow the message to be written to syslog and seen by the user + + _ = syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART) +} diff --git a/cli/internal/cloudcmd/iam.go b/cli/internal/cloudcmd/iam.go index e5902c842..e73f2854d 100644 --- a/cli/internal/cloudcmd/iam.go +++ b/cli/internal/cloudcmd/iam.go @@ -95,6 +95,7 @@ type GCPIAMConfig struct { // AzureIAMConfig holds the necessary values for Azure IAM configuration. type AzureIAMConfig struct { + SubscriptionID string Location string ServicePrincipal string ResourceGroup string @@ -167,6 +168,7 @@ func (c *IAMCreator) createAzure(ctx context.Context, cl tfIAMClient, opts *IAMC defer rollbackOnError(c.out, &retErr, &rollbackerTerraform{client: cl}, opts.TFLogLevel) vars := terraform.AzureIAMVariables{ + SubscriptionID: opts.Azure.SubscriptionID, Location: opts.Azure.Location, ResourceGroup: opts.Azure.ResourceGroup, ServicePrincipal: opts.Azure.ServicePrincipal, diff --git a/cli/internal/cloudcmd/tfvars.go b/cli/internal/cloudcmd/tfvars.go index 50df8dbcc..aab752aca 100644 --- a/cli/internal/cloudcmd/tfvars.go +++ b/cli/internal/cloudcmd/tfvars.go @@ -147,6 +147,7 @@ func azureTerraformVars(conf *config.Config, imageRef string) (*terraform.AzureC } } vars := &terraform.AzureClusterVariables{ + SubscriptionID: conf.Provider.Azure.SubscriptionID, Name: conf.Name, NodeGroups: nodeGroups, Location: conf.Provider.Azure.Location, @@ -191,6 +192,7 @@ func azureTerraformVars(conf *config.Config, imageRef string) (*terraform.AzureC func azureTerraformIAMVars(conf *config.Config, oldVars terraform.AzureIAMVariables) *terraform.AzureIAMVariables { return &terraform.AzureIAMVariables{ + SubscriptionID: conf.Provider.Azure.SubscriptionID, Location: conf.Provider.Azure.Location, ServicePrincipal: oldVars.ServicePrincipal, ResourceGroup: conf.Provider.Azure.ResourceGroup, diff --git a/cli/internal/cmd/BUILD.bazel b/cli/internal/cmd/BUILD.bazel index 8c300b62a..828a63d5b 100644 --- a/cli/internal/cmd/BUILD.bazel +++ b/cli/internal/cmd/BUILD.bazel @@ -109,8 +109,13 @@ go_library( "@io_k8s_client_go//tools/clientcmd", "@io_k8s_client_go//tools/clientcmd/api/latest", "@io_k8s_sigs_yaml//:yaml", - "@org_golang_google_grpc//:go_default_library", "@org_golang_x_mod//semver", + "@org_golang_google_grpc//:grpc", + "@com_github_google_go_tdx_guest//abi", + "@com_github_google_go_tdx_guest//proto/tdx", + "//internal/attestation/azure/tdx", + "@com_github_google_go_sev_guest//proto/sevsnp", + "@com_github_google_go_tpm_tools//proto/attest", ] + select({ "@io_bazel_rules_go//go/platform:android_amd64": [ "@org_golang_x_sys//unix", @@ -193,7 +198,7 @@ go_test( "@io_k8s_apimachinery//pkg/runtime/schema", "@io_k8s_client_go//tools/clientcmd", "@io_k8s_client_go//tools/clientcmd/api", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//status", "@org_golang_x_mod//semver", diff --git a/cli/internal/cmd/apply.go b/cli/internal/cmd/apply.go index 2db2f318c..d4390db21 100644 --- a/cli/internal/cmd/apply.go +++ b/cli/internal/cmd/apply.go @@ -211,10 +211,6 @@ func (f *applyFlags) parse(flags *pflag.FlagSet) error { // runApply sets up the apply command and runs it. func runApply(cmd *cobra.Command, _ []string) error { - log, err := newCLILogger(cmd) - if err != nil { - return fmt.Errorf("creating logger: %w", err) - } spinner, err := newSpinnerOrStderr(cmd) if err != nil { return err @@ -227,7 +223,7 @@ func runApply(cmd *cobra.Command, _ []string) error { } fileHandler := file.NewHandler(afero.NewOsFs()) - logger, err := newDebugFileLogger(cmd, fileHandler) + debugLogger, err := newDebugFileLogger(cmd, fileHandler) if err != nil { return err } @@ -250,15 +246,15 @@ func runApply(cmd *cobra.Command, _ []string) error { ) } - applier := constellation.NewApplier(log, spinner, constellation.ApplyContextCLI, newDialer) + applier := constellation.NewApplier(debugLogger, spinner, constellation.ApplyContextCLI, newDialer) apply := &applyCmd{ fileHandler: fileHandler, flags: flags, - log: logger, - wLog: &warnLogger{cmd: cmd, log: log}, + log: debugLogger, + wLog: &warnLogger{cmd: cmd, log: debugLogger}, spinner: spinner, - merger: &kubeconfigMerger{log: log}, + merger: &kubeconfigMerger{log: debugLogger}, newInfraApplier: newInfraApplier, imageFetcher: imagefetcher.New(), applier: applier, @@ -422,9 +418,15 @@ func (a *applyCmd) apply( // Apply Helm Charts if !a.flags.skipPhases.contains(skipHelmPhase) { + if err := a.applier.AnnotateCoreDNSResources(cmd.Context()); err != nil { + return fmt.Errorf("annotating CoreDNS: %w", err) + } if err := a.runHelmApply(cmd, conf, stateFile, upgradeDir); err != nil { return err } + if err := a.applier.CleanupCoreDNSResources(cmd.Context()); err != nil { + return fmt.Errorf("cleaning up CoreDNS: %w", err) + } } // Upgrade node image @@ -820,6 +822,7 @@ func (wl warnLogger) Info(msg string, args ...any) { // Warn prints a formatted warning from the validator. func (wl warnLogger) Warn(msg string, args ...any) { wl.cmd.PrintErrf("Warning: %s %s\n", msg, fmt.Sprint(args...)) + wl.log.Debug(msg, args...) } type warnLog interface { @@ -843,6 +846,8 @@ type applier interface { // methods required to install/upgrade Helm charts + AnnotateCoreDNSResources(context.Context) error + CleanupCoreDNSResources(context.Context) error PrepareHelmCharts( flags helm.Options, state *state.State, serviceAccURI string, masterSecret uri.MasterSecret, ) (helm.Applier, bool, error) diff --git a/cli/internal/cmd/apply_test.go b/cli/internal/cmd/apply_test.go index 064e1f42b..17c03f33f 100644 --- a/cli/internal/cmd/apply_test.go +++ b/cli/internal/cmd/apply_test.go @@ -553,6 +553,8 @@ func (s *stubConstellApplier) Init(context.Context, atls.Validator, *state.State } type helmApplier interface { + AnnotateCoreDNSResources(context.Context) error + CleanupCoreDNSResources(ctx context.Context) error PrepareHelmCharts( flags helm.Options, stateFile *state.State, serviceAccURI string, masterSecret uri.MasterSecret, ) ( diff --git a/cli/internal/cmd/applyhelm.go b/cli/internal/cmd/applyhelm.go index bd629d348..9b6ba7d69 100644 --- a/cli/internal/cmd/applyhelm.go +++ b/cli/internal/cmd/applyhelm.go @@ -42,6 +42,7 @@ func (a *applyCmd) runHelmApply(cmd *cobra.Command, conf *config.Config, stateFi HelmWaitMode: a.flags.helmWaitMode, ApplyTimeout: a.flags.helmTimeout, AllowDestructive: helm.DenyDestructive, + ServiceCIDR: conf.ServiceCIDR, } if conf.Provider.OpenStack != nil { var deployYawolLoadBalancer bool diff --git a/cli/internal/cmd/configfetchmeasurements_test.go b/cli/internal/cmd/configfetchmeasurements_test.go index 9cebbb7da..12fd761ae 100644 --- a/cli/internal/cmd/configfetchmeasurements_test.go +++ b/cli/internal/cmd/configfetchmeasurements_test.go @@ -204,18 +204,8 @@ func (f stubVerifyFetcher) FetchAndVerifyMeasurements(_ context.Context, _ strin type stubAttestationFetcher struct{} -func (f stubAttestationFetcher) FetchSEVSNPVersionList(_ context.Context, _ attestationconfigapi.SEVSNPVersionList) (attestationconfigapi.SEVSNPVersionList, error) { - return attestationconfigapi.SEVSNPVersionList{}, nil -} - -func (f stubAttestationFetcher) FetchSEVSNPVersion(_ context.Context, _ attestationconfigapi.SEVSNPVersionAPI) (attestationconfigapi.SEVSNPVersionAPI, error) { - return attestationconfigapi.SEVSNPVersionAPI{ - SEVSNPVersion: testCfg, - }, nil -} - -func (f stubAttestationFetcher) FetchSEVSNPVersionLatest(_ context.Context, _ variant.Variant) (attestationconfigapi.SEVSNPVersionAPI, error) { - return attestationconfigapi.SEVSNPVersionAPI{ +func (f stubAttestationFetcher) FetchLatestVersion(_ context.Context, _ variant.Variant) (attestationconfigapi.Entry, error) { + return attestationconfigapi.Entry{ SEVSNPVersion: testCfg, }, nil } diff --git a/cli/internal/cmd/iamcreateazure.go b/cli/internal/cmd/iamcreateazure.go index d80bcb654..26e6ed82a 100644 --- a/cli/internal/cmd/iamcreateazure.go +++ b/cli/internal/cmd/iamcreateazure.go @@ -6,7 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only package cmd import ( + "errors" "fmt" + "os" "github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" @@ -26,6 +28,7 @@ func newIAMCreateAzureCmd() *cobra.Command { RunE: runIAMCreateAzure, } + cmd.Flags().String("subscriptionID", "", "subscription ID of the Azure account. Required if the 'ARM_SUBSCRIPTION_ID' environment variable is not set") cmd.Flags().String("resourceGroup", "", "name prefix of the two resource groups your cluster / IAM resources will be created in (required)") must(cobra.MarkFlagRequired(cmd.Flags(), "resourceGroup")) cmd.Flags().String("region", "", "region the resources will be created in, e.g., westus (required)") @@ -45,6 +48,7 @@ func runIAMCreateAzure(cmd *cobra.Command, _ []string) error { // azureIAMCreateFlags contains the parsed flags of the iam create azure command. type azureIAMCreateFlags struct { + subscriptionID string region string resourceGroup string servicePrincipal string @@ -52,6 +56,14 @@ type azureIAMCreateFlags struct { func (f *azureIAMCreateFlags) parse(flags *pflag.FlagSet) error { var err error + f.subscriptionID, err = flags.GetString("subscriptionID") + if err != nil { + return fmt.Errorf("getting 'subscriptionID' flag: %w", err) + } + if f.subscriptionID == "" && os.Getenv("ARM_SUBSCRIPTION_ID") == "" { + return errors.New("either flag 'subscriptionID' or environment variable 'ARM_SUBSCRIPTION_ID' must be set") + } + f.region, err = flags.GetString("region") if err != nil { return fmt.Errorf("getting 'region' flag: %w", err) @@ -75,6 +87,7 @@ type azureIAMCreator struct { func (c *azureIAMCreator) getIAMConfigOptions() *cloudcmd.IAMConfigOptions { return &cloudcmd.IAMConfigOptions{ Azure: cloudcmd.AzureIAMConfig{ + SubscriptionID: c.flags.subscriptionID, Location: c.flags.region, ResourceGroup: c.flags.resourceGroup, ServicePrincipal: c.flags.servicePrincipal, @@ -83,6 +96,7 @@ func (c *azureIAMCreator) getIAMConfigOptions() *cloudcmd.IAMConfigOptions { } func (c *azureIAMCreator) printConfirmValues(cmd *cobra.Command) { + cmd.Printf("Subscription ID:\t%s\n", c.flags.subscriptionID) cmd.Printf("Region:\t\t\t%s\n", c.flags.region) cmd.Printf("Resource Group:\t\t%s\n", c.flags.resourceGroup) cmd.Printf("Service Principal:\t%s\n\n", c.flags.servicePrincipal) diff --git a/cli/internal/cmd/iamupgradeapply_test.go b/cli/internal/cmd/iamupgradeapply_test.go index e1d4c19ce..786c24857 100644 --- a/cli/internal/cmd/iamupgradeapply_test.go +++ b/cli/internal/cmd/iamupgradeapply_test.go @@ -171,14 +171,6 @@ type stubConfigFetcher struct { fetchLatestErr error } -func (s *stubConfigFetcher) FetchSEVSNPVersion(context.Context, attestationconfigapi.SEVSNPVersionAPI) (attestationconfigapi.SEVSNPVersionAPI, error) { - panic("not implemented") -} - -func (s *stubConfigFetcher) FetchSEVSNPVersionList(context.Context, attestationconfigapi.SEVSNPVersionList) (attestationconfigapi.SEVSNPVersionList, error) { - panic("not implemented") -} - -func (s *stubConfigFetcher) FetchSEVSNPVersionLatest(context.Context, variant.Variant) (attestationconfigapi.SEVSNPVersionAPI, error) { - return attestationconfigapi.SEVSNPVersionAPI{}, s.fetchLatestErr +func (s *stubConfigFetcher) FetchLatestVersion(context.Context, variant.Variant) (attestationconfigapi.Entry, error) { + return attestationconfigapi.Entry{}, s.fetchLatestErr } diff --git a/cli/internal/cmd/init.go b/cli/internal/cmd/init.go index a1e3e3632..138f22392 100644 --- a/cli/internal/cmd/init.go +++ b/cli/internal/cmd/init.go @@ -7,7 +7,6 @@ SPDX-License-Identifier: AGPL-3.0-only package cmd import ( - "context" "fmt" "io" "os" @@ -106,5 +105,5 @@ func (c *kubeconfigMerger) kubeconfigEnvVar() string { } type grpcDialer interface { - Dial(ctx context.Context, target string) (*grpc.ClientConn, error) + Dial(target string) (*grpc.ClientConn, error) } diff --git a/cli/internal/cmd/init_test.go b/cli/internal/cmd/init_test.go index 8d6d2b1bb..568c31ff8 100644 --- a/cli/internal/cmd/init_test.go +++ b/cli/internal/cmd/init_test.go @@ -278,6 +278,14 @@ type stubHelmApplier struct { err error } +func (s stubHelmApplier) AnnotateCoreDNSResources(_ context.Context) error { + return nil +} + +func (s stubHelmApplier) CleanupCoreDNSResources(_ context.Context) error { + return nil +} + func (s stubHelmApplier) PrepareHelmCharts( _ helm.Options, _ *state.State, _ string, _ uri.MasterSecret, ) (helm.Applier, bool, error) { @@ -531,9 +539,9 @@ func defaultConfigWithExpectedMeasurements(t *testing.T, conf *config.Config, cs conf.Provider.GCP.Project = "test-project" conf.Provider.GCP.Zone = "test-zone" conf.Provider.GCP.ServiceAccountKeyPath = "test-key-path" - conf.Attestation.GCPSEVES.Measurements[4] = measurements.WithAllBytes(0x44, measurements.Enforce, measurements.PCRMeasurementLength) - conf.Attestation.GCPSEVES.Measurements[9] = measurements.WithAllBytes(0x11, measurements.Enforce, measurements.PCRMeasurementLength) - conf.Attestation.GCPSEVES.Measurements[12] = measurements.WithAllBytes(0xcc, measurements.Enforce, measurements.PCRMeasurementLength) + conf.Attestation.GCPSEVSNP.Measurements[4] = measurements.WithAllBytes(0x44, measurements.Enforce, measurements.PCRMeasurementLength) + conf.Attestation.GCPSEVSNP.Measurements[9] = measurements.WithAllBytes(0x11, measurements.Enforce, measurements.PCRMeasurementLength) + conf.Attestation.GCPSEVSNP.Measurements[12] = measurements.WithAllBytes(0xcc, measurements.Enforce, measurements.PCRMeasurementLength) zone = "europe-west3-b" instanceType = "n2d-standard-4" diskType = "pd-ssd" diff --git a/cli/internal/cmd/recover.go b/cli/internal/cmd/recover.go index 4541fd08d..17ffa4c32 100644 --- a/cli/internal/cmd/recover.go +++ b/cli/internal/cmd/recover.go @@ -217,7 +217,7 @@ type recoverDoer struct { // Do performs the recover streaming rpc. func (d *recoverDoer) Do(ctx context.Context) (retErr error) { - conn, err := d.dialer.Dial(ctx, d.endpoint) + conn, err := d.dialer.Dial(d.endpoint) if err != nil { return fmt.Errorf("dialing recovery server: %w", err) } diff --git a/cli/internal/cmd/upgradeapply_test.go b/cli/internal/cmd/upgradeapply_test.go index f396cc828..db4012596 100644 --- a/cli/internal/cmd/upgradeapply_test.go +++ b/cli/internal/cmd/upgradeapply_test.go @@ -375,6 +375,14 @@ type mockApplier struct { mock.Mock } +func (m *mockApplier) AnnotateCoreDNSResources(_ context.Context) error { + return nil +} + +func (m *mockApplier) CleanupCoreDNSResources(_ context.Context) error { + return nil +} + func (m *mockApplier) PrepareHelmCharts( helmOpts helm.Options, stateFile *state.State, str string, masterSecret uri.MasterSecret, ) (helm.Applier, bool, error) { diff --git a/cli/internal/cmd/verify.go b/cli/internal/cmd/verify.go index 5a84c3df0..523920a20 100644 --- a/cli/internal/cmd/verify.go +++ b/cli/internal/cmd/verify.go @@ -21,10 +21,9 @@ import ( "strconv" "strings" - tpmProto "github.com/google/go-tpm-tools/proto/tpm" - "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" "github.com/edgelesssys/constellation/v2/internal/atls" + azuretdx "github.com/edgelesssys/constellation/v2/internal/attestation/azure/tdx" "github.com/edgelesssys/constellation/v2/internal/attestation/choose" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/snp" @@ -38,6 +37,12 @@ import ( "github.com/edgelesssys/constellation/v2/internal/grpc/dialer" "github.com/edgelesssys/constellation/v2/internal/verify" "github.com/edgelesssys/constellation/v2/verify/verifyproto" + + "github.com/google/go-sev-guest/proto/sevsnp" + "github.com/google/go-tdx-guest/abi" + "github.com/google/go-tdx-guest/proto/tdx" + "github.com/google/go-tpm-tools/proto/attest" + tpmProto "github.com/google/go-tpm-tools/proto/tpm" "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -106,24 +111,7 @@ func runVerify(cmd *cobra.Command, _ []string) error { dialer: dialer.New(nil, nil, &net.Dialer{}), log: log, } - formatterFactory := func(output string, attestation variant.Variant, log debugLog) (attestationDocFormatter, error) { - if output == "json" && - (!attestation.Equal(variant.AzureSEVSNP{}) && - !attestation.Equal(variant.AWSSEVSNP{}) && - !attestation.Equal(variant.GCPSEVSNP{})) { - return nil, errors.New("json output is only supported for SEV-SNP") - } - switch output { - case "json": - return &jsonAttestationDocFormatter{log}, nil - case "raw": - return &rawAttestationDocFormatter{log}, nil - case "": - return &defaultAttestationDocFormatter{log}, nil - default: - return nil, fmt.Errorf("invalid output value for formatter: %s", output) - } - } + v := &verifyCmd{ fileHandler: fileHandler, log: log, @@ -132,13 +120,12 @@ func runVerify(cmd *cobra.Command, _ []string) error { return err } v.log.Debug("Using flags", "clusterID", v.flags.clusterID, "endpoint", v.flags.endpoint, "ownerID", v.flags.ownerID) + fetcher := attestationconfigapi.NewFetcher() - return v.verify(cmd, verifyClient, formatterFactory, fetcher) + return v.verify(cmd, verifyClient, fetcher) } -type formatterFactory func(output string, attestation variant.Variant, log debugLog) (attestationDocFormatter, error) - -func (c *verifyCmd) verify(cmd *cobra.Command, verifyClient verifyClient, factory formatterFactory, configFetcher attestationconfigapi.Fetcher) error { +func (c *verifyCmd) verify(cmd *cobra.Command, verifyClient verifyClient, configFetcher attestationconfigapi.Fetcher) error { c.log.Debug(fmt.Sprintf("Loading configuration file from %q", c.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))) conf, err := config.New(c.fileHandler, constants.ConfigFilename, configFetcher, c.flags.force) var configValidationErr *config.ValidationError @@ -151,10 +138,7 @@ func (c *verifyCmd) verify(cmd *cobra.Command, verifyClient verifyClient, factor stateFile, err := state.ReadFromFile(c.fileHandler, constants.StateFilename) if err != nil { - return fmt.Errorf("reading state file: %w", err) - } - if err := stateFile.Validate(state.PostInit, conf.GetAttestationConfig().GetVariant()); err != nil { - return fmt.Errorf("validating state file: %w", err) + stateFile = state.New() // A state file is only required if the user has not provided IP or ID flags } ownerID, clusterID, err := c.validateIDFlags(cmd, stateFile) @@ -202,20 +186,27 @@ func (c *verifyCmd) verify(cmd *cobra.Command, verifyClient verifyClient, factor return fmt.Errorf("verifying: %w", err) } - // certificates are only available for Azure SEV-SNP and AWS SEV-SNP - formatter, err := factory(c.flags.output, conf.GetAttestationConfig().GetVariant(), c.log) - if err != nil { - return fmt.Errorf("creating formatter: %w", err) - } - attDocOutput, err := formatter.format( - cmd.Context(), - rawAttestationDoc, - (!attConfig.GetVariant().Equal(variant.AzureSEVSNP{}) && !attConfig.GetVariant().Equal(variant.AWSSEVSNP{})), - attConfig, - ) - if err != nil { - return fmt.Errorf("printing attestation document: %w", err) + var attDocOutput string + switch c.flags.output { + case "json": + attDocOutput, err = formatJSON(cmd.Context(), rawAttestationDoc, attConfig, c.log) + if err != nil { + return fmt.Errorf("printing attestation document: %w", err) + } + + case "raw": + attDocOutput = fmt.Sprintf("Attestation Document:\n%s\n", rawAttestationDoc) + + case "": + attDocOutput, err = formatDefault(cmd.Context(), rawAttestationDoc, attConfig, c.log) + if err != nil { + return fmt.Errorf("printing attestation document: %w", err) + } + + default: + return fmt.Errorf("invalid output value for formatter: %s", c.flags.output) } + cmd.Println(attDocOutput) cmd.PrintErrln("Verification OK") @@ -255,82 +246,92 @@ func (c *verifyCmd) validateEndpointFlag(cmd *cobra.Command, stateFile *state.St return endpoint, nil } -// an attestationDocFormatter formats the attestation document. -type attestationDocFormatter interface { - // format returns the raw or formatted attestation doc depending on the rawOutput argument. - format(ctx context.Context, docString string, PCRsOnly bool, attestationCfg config.AttestationCfg) (string, error) -} - -type jsonAttestationDocFormatter struct { - log debugLog -} - -// format returns the json formatted attestation doc. -func (f *jsonAttestationDocFormatter) format(ctx context.Context, docString string, _ bool, - attestationCfg config.AttestationCfg, +// formatJSON returns the json formatted attestation doc. +func formatJSON(ctx context.Context, docString []byte, attestationCfg config.AttestationCfg, log debugLog, ) (string, error) { - var doc attestationDoc - if err := json.Unmarshal([]byte(docString), &doc); err != nil { - return "", fmt.Errorf("unmarshal attestation document: %w", err) + doc, err := unmarshalAttDoc(docString, attestationCfg.GetVariant()) + if err != nil { + return "", fmt.Errorf("unmarshalling attestation document: %w", err) } - instanceInfo, err := extractInstanceInfo(doc) - if err != nil { + switch attestationCfg.GetVariant() { + case variant.AWSSEVSNP{}, variant.AzureSEVSNP{}, variant.GCPSEVSNP{}: + return snpFormatJSON(ctx, doc.InstanceInfo, attestationCfg, log) + case variant.AzureTDX{}: + return tdxFormatJSON(doc.InstanceInfo, attestationCfg) + default: + return "", fmt.Errorf("json output is not supported for variant %s", attestationCfg.GetVariant()) + } +} + +func snpFormatJSON(ctx context.Context, instanceInfoRaw []byte, attestationCfg config.AttestationCfg, log debugLog, +) (string, error) { + var instanceInfo snp.InstanceInfo + if err := json.Unmarshal(instanceInfoRaw, &instanceInfo); err != nil { return "", fmt.Errorf("unmarshalling instance info: %w", err) } - report, err := verify.NewReport(ctx, instanceInfo, attestationCfg, f.log) + report, err := verify.NewReport(ctx, instanceInfo, attestationCfg, log) if err != nil { return "", fmt.Errorf("parsing SNP report: %w", err) } jsonBytes, err := json.Marshal(report) - return string(jsonBytes), err } -type rawAttestationDocFormatter struct { - log debugLog -} +func tdxFormatJSON(instanceInfoRaw []byte, attestationCfg config.AttestationCfg) (string, error) { + var rawQuote []byte -// format returns the raw attestation doc. -func (f *rawAttestationDocFormatter) format(_ context.Context, docString string, _ bool, - _ config.AttestationCfg, -) (string, error) { - b := &strings.Builder{} - b.WriteString("Attestation Document:\n") - b.WriteString(fmt.Sprintf("%s\n", docString)) - return b.String(), nil -} + if attestationCfg.GetVariant().Equal(variant.AzureTDX{}) { + var instanceInfo azuretdx.InstanceInfo + if err := json.Unmarshal(instanceInfoRaw, &instanceInfo); err != nil { + return "", fmt.Errorf("unmarshalling instance info: %w", err) + } + rawQuote = instanceInfo.AttestationReport + } -type defaultAttestationDocFormatter struct { - log debugLog + tdxQuote, err := abi.QuoteToProto(rawQuote) + if err != nil { + return "", fmt.Errorf("converting quote to proto: %w", err) + } + quote, ok := tdxQuote.(*tdx.QuoteV4) + if !ok { + return "", fmt.Errorf("unexpected quote type: %T", tdxQuote) + } + + quoteJSON, err := json.Marshal(quote) + return string(quoteJSON), err } // format returns the formatted attestation doc. -func (f *defaultAttestationDocFormatter) format(ctx context.Context, docString string, PCRsOnly bool, - attestationCfg config.AttestationCfg, +func formatDefault(ctx context.Context, docString []byte, attestationCfg config.AttestationCfg, log debugLog, ) (string, error) { b := &strings.Builder{} b.WriteString("Attestation Document:\n") - var doc attestationDoc - if err := json.Unmarshal([]byte(docString), &doc); err != nil { - return "", fmt.Errorf("unmarshal attestation document: %w", err) + doc, err := unmarshalAttDoc(docString, attestationCfg.GetVariant()) + if err != nil { + return "", fmt.Errorf("unmarshalling attestation document: %w", err) } - if err := f.parseQuotes(b, doc.Attestation.Quotes, attestationCfg.GetMeasurements()); err != nil { + if err := parseQuotes(b, doc.Attestation.Quotes, attestationCfg.GetMeasurements()); err != nil { return "", fmt.Errorf("parse quote: %w", err) } - if PCRsOnly { + + // If we have a non SNP variant, print only the PCRs + if !(attestationCfg.GetVariant().Equal(variant.AzureSEVSNP{}) || + attestationCfg.GetVariant().Equal(variant.AWSSEVSNP{}) || + attestationCfg.GetVariant().Equal(variant.GCPSEVSNP{})) { return b.String(), nil } - instanceInfo, err := extractInstanceInfo(doc) - if err != nil { + // SNP reports contain extra information that we can print + var instanceInfo snp.InstanceInfo + if err := json.Unmarshal(doc.InstanceInfo, &instanceInfo); err != nil { return "", fmt.Errorf("unmarshalling instance info: %w", err) } - report, err := verify.NewReport(ctx, instanceInfo, attestationCfg, f.log) + report, err := verify.NewReport(ctx, instanceInfo, attestationCfg, log) if err != nil { return "", fmt.Errorf("parsing SNP report: %w", err) } @@ -339,7 +340,7 @@ func (f *defaultAttestationDocFormatter) format(ctx context.Context, docString s } // parseQuotes parses the base64-encoded quotes and writes their details to the output builder. -func (f *defaultAttestationDocFormatter) parseQuotes(b *strings.Builder, quotes []*tpmProto.Quote, expectedPCRs measurements.M) error { +func parseQuotes(b *strings.Builder, quotes []*tpmProto.Quote, expectedPCRs measurements.M) error { writeIndentfln(b, 1, "Quote:") var pcrNumbers []uint32 @@ -366,18 +367,6 @@ func (f *defaultAttestationDocFormatter) parseQuotes(b *strings.Builder, quotes return nil } -// attestationDoc is the attestation document returned by the verifier. -type attestationDoc struct { - Attestation struct { - AkPub string `json:"ak_pub"` - Quotes []*tpmProto.Quote `json:"quotes"` - EventLog string `json:"event_log"` - TeeAttestation interface{} `json:"TeeAttestation"` - } `json:"Attestation"` - InstanceInfo string `json:"InstanceInfo"` - UserData string `json:"UserData"` -} - type constellationVerifier struct { dialer grpcInsecureDialer log debugLog @@ -386,11 +375,11 @@ type constellationVerifier struct { // Verify retrieves an attestation statement from the Constellation and verifies it using the validator. func (v *constellationVerifier) Verify( ctx context.Context, endpoint string, req *verifyproto.GetAttestationRequest, validator atls.Validator, -) (string, error) { +) ([]byte, error) { v.log.Debug(fmt.Sprintf("Dialing endpoint: %q", endpoint)) - conn, err := v.dialer.DialInsecure(ctx, endpoint) + conn, err := v.dialer.DialInsecure(endpoint) if err != nil { - return "", fmt.Errorf("dialing init server: %w", err) + return nil, fmt.Errorf("dialing init server: %w", err) } defer conn.Close() @@ -399,28 +388,28 @@ func (v *constellationVerifier) Verify( v.log.Debug("Sending attestation request") resp, err := client.GetAttestation(ctx, req) if err != nil { - return "", fmt.Errorf("getting attestation: %w", err) + return nil, fmt.Errorf("getting attestation: %w", err) } v.log.Debug("Verifying attestation") signedData, err := validator.Validate(ctx, resp.Attestation, req.Nonce) if err != nil { - return "", fmt.Errorf("validating attestation: %w", err) + return nil, fmt.Errorf("validating attestation: %w", err) } if !bytes.Equal(signedData, []byte(constants.ConstellationVerifyServiceUserData)) { - return "", errors.New("signed data in attestation does not match expected user data") + return nil, errors.New("signed data in attestation does not match expected user data") } - return string(resp.Attestation), nil + return resp.Attestation, nil } type verifyClient interface { - Verify(ctx context.Context, endpoint string, req *verifyproto.GetAttestationRequest, validator atls.Validator) (string, error) + Verify(ctx context.Context, endpoint string, req *verifyproto.GetAttestationRequest, validator atls.Validator) ([]byte, error) } type grpcInsecureDialer interface { - DialInsecure(ctx context.Context, endpoint string) (conn *grpc.ClientConn, err error) + DialInsecure(endpoint string) (conn *grpc.ClientConn, err error) } // writeIndentfln writes a formatted string to the builder with the given indentation level @@ -432,19 +421,6 @@ func writeIndentfln(b *strings.Builder, indentLvl int, format string, args ...an b.WriteString(fmt.Sprintf(format+"\n", args...)) } -func extractInstanceInfo(doc attestationDoc) (snp.InstanceInfo, error) { - instanceInfoString, err := base64.StdEncoding.DecodeString(doc.InstanceInfo) - if err != nil { - return snp.InstanceInfo{}, fmt.Errorf("decode instance info: %w", err) - } - - var instanceInfo snp.InstanceInfo - if err := json.Unmarshal(instanceInfoString, &instanceInfo); err != nil { - return snp.InstanceInfo{}, fmt.Errorf("unmarshal instance info: %w", err) - } - return instanceInfo, nil -} - func addPortIfMissing(endpoint string, defaultPort int) (string, error) { if endpoint == "" { return "", errors.New("endpoint is empty") @@ -544,3 +520,26 @@ func decodeMeasurement(encoded string) ([]byte, error) { } return decoded, nil } + +func unmarshalAttDoc(attDocJSON []byte, attestationVariant variant.Variant) (vtpm.AttestationDocument, error) { + attDoc := vtpm.AttestationDocument{ + Attestation: &attest.Attestation{}, + } + + // Explicitly initialize this struct, as TeeAttestation + // is a "oneof" protobuf field, which needs an explicit + // type to be set to be unmarshaled correctly. + switch attestationVariant { + case variant.AzureTDX{}: + attDoc.Attestation.TeeAttestation = &attest.Attestation_TdxAttestation{ + TdxAttestation: &tdx.QuoteV4{}, + } + default: + attDoc.Attestation.TeeAttestation = &attest.Attestation_SevSnpAttestation{ + SevSnpAttestation: &sevsnp.Attestation{}, + } + } + + err := json.Unmarshal(attDocJSON, &attDoc) + return attDoc, err +} diff --git a/cli/internal/cmd/verify_test.go b/cli/internal/cmd/verify_test.go index a695a7c2f..3e161c8c8 100644 --- a/cli/internal/cmd/verify_test.go +++ b/cli/internal/cmd/verify_test.go @@ -47,7 +47,6 @@ func TestVerify(t *testing.T) { testCases := map[string]struct { provider cloudprovider.Provider protoClient *stubVerifyClient - formatter *stubAttDocFormatter nodeEndpointFlag string clusterIDFlag string stateFile *state.State @@ -62,7 +61,6 @@ func TestVerify(t *testing.T) { protoClient: &stubVerifyClient{}, stateFile: defaultStateFile(cloudprovider.GCP), wantEndpoint: "192.0.2.1:1234", - formatter: &stubAttDocFormatter{}, }, "azure": { provider: cloudprovider.Azure, @@ -71,7 +69,6 @@ func TestVerify(t *testing.T) { protoClient: &stubVerifyClient{}, stateFile: defaultStateFile(cloudprovider.Azure), wantEndpoint: "192.0.2.1:1234", - formatter: &stubAttDocFormatter{}, }, "default port": { provider: cloudprovider.GCP, @@ -80,7 +77,6 @@ func TestVerify(t *testing.T) { protoClient: &stubVerifyClient{}, stateFile: defaultStateFile(cloudprovider.GCP), wantEndpoint: "192.0.2.1:" + strconv.Itoa(constants.VerifyServiceNodePortGRPC), - formatter: &stubAttDocFormatter{}, }, "endpoint not set": { provider: cloudprovider.GCP, @@ -91,8 +87,7 @@ func TestVerify(t *testing.T) { s.Infrastructure.ClusterEndpoint = "" return s }(), - formatter: &stubAttDocFormatter{}, - wantErr: true, + wantErr: true, }, "endpoint from state file": { provider: cloudprovider.GCP, @@ -104,7 +99,6 @@ func TestVerify(t *testing.T) { return s }(), wantEndpoint: "192.0.2.1:" + strconv.Itoa(constants.VerifyServiceNodePortGRPC), - formatter: &stubAttDocFormatter{}, }, "override endpoint from details file": { provider: cloudprovider.GCP, @@ -117,7 +111,6 @@ func TestVerify(t *testing.T) { return s }(), wantEndpoint: "192.0.2.2:1234", - formatter: &stubAttDocFormatter{}, }, "invalid endpoint": { provider: cloudprovider.GCP, @@ -125,7 +118,6 @@ func TestVerify(t *testing.T) { clusterIDFlag: zeroBase64, protoClient: &stubVerifyClient{}, stateFile: defaultStateFile(cloudprovider.GCP), - formatter: &stubAttDocFormatter{}, wantErr: true, }, "neither owner id nor cluster id set": { @@ -137,7 +129,6 @@ func TestVerify(t *testing.T) { s.ClusterValues.ClusterID = "" return s }(), - formatter: &stubAttDocFormatter{}, protoClient: &stubVerifyClient{}, wantErr: true, }, @@ -151,14 +142,12 @@ func TestVerify(t *testing.T) { return s }(), wantEndpoint: "192.0.2.1:1234", - formatter: &stubAttDocFormatter{}, }, "config file not existing": { provider: cloudprovider.GCP, clusterIDFlag: zeroBase64, nodeEndpointFlag: "192.0.2.1:1234", stateFile: defaultStateFile(cloudprovider.GCP), - formatter: &stubAttDocFormatter{}, skipConfigCreation: true, wantErr: true, }, @@ -168,7 +157,6 @@ func TestVerify(t *testing.T) { clusterIDFlag: zeroBase64, protoClient: &stubVerifyClient{verifyErr: rpcStatus.Error(codes.Internal, "failed")}, stateFile: defaultStateFile(cloudprovider.Azure), - formatter: &stubAttDocFormatter{}, wantErr: true, }, "error protoClient GetState not rpc": { @@ -177,18 +165,19 @@ func TestVerify(t *testing.T) { clusterIDFlag: zeroBase64, protoClient: &stubVerifyClient{verifyErr: someErr}, stateFile: defaultStateFile(cloudprovider.Azure), - formatter: &stubAttDocFormatter{}, wantErr: true, }, - "format error": { + "state file is not required if flags are given": { provider: cloudprovider.Azure, nodeEndpointFlag: "192.0.2.1:1234", clusterIDFlag: zeroBase64, protoClient: &stubVerifyClient{}, - stateFile: defaultStateFile(cloudprovider.Azure), wantEndpoint: "192.0.2.1:1234", - formatter: &stubAttDocFormatter{formatErr: someErr}, - wantErr: true, + }, + "no state file and no flags": { + provider: cloudprovider.Azure, + protoClient: &stubVerifyClient{}, + wantErr: true, }, } @@ -206,7 +195,9 @@ func TestVerify(t *testing.T) { cfg := defaultConfigWithExpectedMeasurements(t, config.Default(), tc.provider) require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, cfg)) } - require.NoError(tc.stateFile.WriteToFile(fileHandler, constants.StateFilename)) + if tc.stateFile != nil { + require.NoError(tc.stateFile.WriteToFile(fileHandler, constants.StateFilename)) + } v := &verifyCmd{ fileHandler: fileHandler, @@ -214,12 +205,10 @@ func TestVerify(t *testing.T) { flags: verifyFlags{ clusterID: tc.clusterIDFlag, endpoint: tc.nodeEndpointFlag, + output: "raw", }, } - formatterFac := func(_ string, _ variant.Variant, _ debugLog) (attestationDocFormatter, error) { - return tc.formatter, nil - } - err := v.verify(cmd, tc.protoClient, formatterFac, stubAttestationFetcher{}) + err := v.verify(cmd, tc.protoClient, stubAttestationFetcher{}) if tc.wantErr { assert.Error(err) } else { @@ -231,36 +220,22 @@ func TestVerify(t *testing.T) { } } -type stubAttDocFormatter struct { - formatErr error -} - -func (f *stubAttDocFormatter) format(_ context.Context, _ string, _ bool, _ config.AttestationCfg) (string, error) { - return "", f.formatErr -} - -func TestFormat(t *testing.T) { - formatter := func() *defaultAttestationDocFormatter { - return &defaultAttestationDocFormatter{ - log: logger.NewTest(t), - } - } - +func TestFormatDefault(t *testing.T) { testCases := map[string]struct { - formatter *defaultAttestationDocFormatter - doc string - wantErr bool + doc []byte + attCfg config.AttestationCfg + wantErr bool }{ "invalid doc": { - formatter: formatter(), - doc: "invalid", - wantErr: true, + doc: []byte("invalid"), + attCfg: &config.AzureSEVSNP{}, + wantErr: true, }, } for name, tc := range testCases { t.Run(name, func(t *testing.T) { - _, err := tc.formatter.format(context.Background(), tc.doc, false, nil) + _, err := formatDefault(context.Background(), tc.doc, tc.attCfg, logger.NewTest(t)) if tc.wantErr { assert.Error(t, err) } else { @@ -354,9 +329,9 @@ type stubVerifyClient struct { endpoint string } -func (c *stubVerifyClient) Verify(_ context.Context, endpoint string, _ *verifyproto.GetAttestationRequest, _ atls.Validator) (string, error) { +func (c *stubVerifyClient) Verify(_ context.Context, endpoint string, _ *verifyproto.GetAttestationRequest, _ atls.Validator) ([]byte, error) { c.endpoint = endpoint - return "", c.verifyErr + return nil, c.verifyErr } type stubVerifyAPI struct { @@ -502,9 +477,8 @@ func TestParseQuotes(t *testing.T) { assert := assert.New(t) b := &strings.Builder{} - parser := &defaultAttestationDocFormatter{} - err := parser.parseQuotes(b, tc.quotes, tc.expectedPCRs) + err := parseQuotes(b, tc.quotes, tc.expectedPCRs) if tc.wantErr { assert.Error(err) } else { diff --git a/cli/internal/terraform/variables.go b/cli/internal/terraform/variables.go index 081ae5946..86af569e0 100644 --- a/cli/internal/terraform/variables.go +++ b/cli/internal/terraform/variables.go @@ -172,7 +172,7 @@ type GCPNodeGroup struct { DiskType string `hcl:"disk_type" cty:"disk_type"` } -// GCPIAMVariables is user configuration for creating the IAM confioguration with Terraform on GCP. +// GCPIAMVariables is user configuration for creating the IAM configuration with Terraform on GCP. type GCPIAMVariables struct { // Project is the ID of the GCP project to use. Project string `hcl:"project_id" cty:"project_id"` @@ -193,6 +193,8 @@ func (v *GCPIAMVariables) String() string { // AzureClusterVariables is user configuration for creating a cluster with Terraform on Azure. type AzureClusterVariables struct { + // SubscriptionID is the Azure subscription ID to use. + SubscriptionID string `hcl:"subscription_id" cty:"subscription_id"` // Name of the cluster. Name string `hcl:"name" cty:"name"` // ImageID is the ID of the Azure image to use. @@ -254,6 +256,8 @@ type AzureNodeGroup struct { // AzureIAMVariables is user configuration for creating the IAM configuration with Terraform on Microsoft Azure. type AzureIAMVariables struct { + // SubscriptionID is the Azure subscription ID to use. + SubscriptionID string `hcl:"subscription_id,optional" cty:"subscription_id"` // TODO(v2.18): remove optional tag. This is only required for migration from var files that dont have the value yet. // Location is the Azure location to use. (e.g. westus) Location string `hcl:"location" cty:"location"` // ServicePrincipal is the name of the service principal to use. diff --git a/cli/internal/terraform/variables_test.go b/cli/internal/terraform/variables_test.go index 306acd6ae..02567c314 100644 --- a/cli/internal/terraform/variables_test.go +++ b/cli/internal/terraform/variables_test.go @@ -180,7 +180,8 @@ service_account_id = "my-service-account" func TestAzureClusterVariables(t *testing.T) { vars := AzureClusterVariables{ - Name: "cluster-name", + SubscriptionID: "01234567-cdef-0123-4567-89abcdef0123", + Name: "cluster-name", NodeGroups: map[string]AzureNodeGroup{ constants.ControlPlaneDefault: { Role: "ControlPlane", @@ -207,7 +208,8 @@ func TestAzureClusterVariables(t *testing.T) { } // test that the variables are correctly rendered - want := `name = "cluster-name" + want := `subscription_id = "01234567-cdef-0123-4567-89abcdef0123" +name = "cluster-name" image_id = "image-0123456789abcdef" create_maa = true debug = true @@ -241,13 +243,15 @@ additional_tags = null func TestAzureIAMVariables(t *testing.T) { vars := AzureIAMVariables{ + SubscriptionID: "01234567-cdef-0123-4567-89abcdef0123", Location: "eu-central-1", ServicePrincipal: "my-service-principal", ResourceGroup: "my-resource-group", } // test that the variables are correctly rendered - want := `location = "eu-central-1" + want := `subscription_id = "01234567-cdef-0123-4567-89abcdef0123" +location = "eu-central-1" service_principal_name = "my-service-principal" resource_group_name = "my-resource-group" ` diff --git a/csi/kms/BUILD.bazel b/csi/kms/BUILD.bazel index 19d174a01..81dd9ecd8 100644 --- a/csi/kms/BUILD.bazel +++ b/csi/kms/BUILD.bazel @@ -8,7 +8,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//keyservice/keyserviceproto", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//credentials/insecure", ], ) @@ -20,7 +20,7 @@ go_test( deps = [ "//keyservice/keyserviceproto", "@com_github_stretchr_testify//assert", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//test/bufconn", "@org_uber_go_goleak//:goleak", ], diff --git a/csi/kms/constellation.go b/csi/kms/constellation.go index dbc310bdb..9ae1733ae 100644 --- a/csi/kms/constellation.go +++ b/csi/kms/constellation.go @@ -31,7 +31,7 @@ func NewConstellationKMS(endpoint string) *ConstellationKMS { // GetDEK request a data encryption key derived from the Constellation's master secret. func (k *ConstellationKMS) GetDEK(ctx context.Context, dekID string, dekSize int) ([]byte, error) { - conn, err := grpc.DialContext(ctx, k.endpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.NewClient(k.endpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, err } diff --git a/csi/test/BUILD.bazel b/csi/test/BUILD.bazel index b62498c20..5a27fdf89 100644 --- a/csi/test/BUILD.bazel +++ b/csi/test/BUILD.bazel @@ -28,6 +28,8 @@ go_test( "RM": "$(rlocationpath @coreutils//:bin/rm)", "UMOUNT": "$(rlocationpath @util-linux//:bin/umount)", }, + # This test frequently runs into https://github.com/martinjungblut/go-cryptsetup/issues/13. + flaky = 1, # keep tags = [ "integration", diff --git a/debugd/filebeat/Dockerfile b/debugd/filebeat/Dockerfile index 635a76178..2aa6f6b4c 100644 --- a/debugd/filebeat/Dockerfile +++ b/debugd/filebeat/Dockerfile @@ -1,7 +1,9 @@ -FROM fedora:40@sha256:5ce8497aeea599bf6b54ab3979133923d82aaa4f6ca5ced1812611b197c79eb0 AS release +FROM fedora:40@sha256:7cdd2b48396929bb8723ea2fa60e03bee39cc22e2a853cbd891587fab4eb1bc9 AS release RUN dnf install -y https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.6.2-x86_64.rpm +RUN dnf install -y systemd-libs + COPY debugd/filebeat/templates/ /usr/share/constellogs/templates/ ENTRYPOINT ["/usr/share/filebeat/bin/filebeat", "-e", "--path.home", "/usr/share/filebeat", "--path.data", "/usr/share/filebeat/data"] diff --git a/debugd/internal/cdbg/cmd/BUILD.bazel b/debugd/internal/cdbg/cmd/BUILD.bazel index 94420b1c1..e48d0d5d1 100644 --- a/debugd/internal/cdbg/cmd/BUILD.bazel +++ b/debugd/internal/cdbg/cmd/BUILD.bazel @@ -22,7 +22,7 @@ go_library( "//internal/logger", "@com_github_spf13_afero//:afero", "@com_github_spf13_cobra//:cobra", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//credentials/insecure", ], ) diff --git a/debugd/internal/cdbg/cmd/deploy.go b/debugd/internal/cdbg/cmd/deploy.go index 95c3d147e..d66cf10b7 100644 --- a/debugd/internal/cdbg/cmd/deploy.go +++ b/debugd/internal/cdbg/cmd/deploy.go @@ -203,8 +203,7 @@ type closeAndWait func() // newDebugdClient creates a new gRPC client for the debugd service and logs the connection state changes. func newDebugdClient(ctx context.Context, ip string, log *slog.Logger) (pb.DebugdClient, closeAndWait, error) { - conn, err := grpc.DialContext( - ctx, + conn, err := grpc.NewClient( net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort)), grpc.WithTransportCredentials(insecure.NewCredentials()), logger.GetClientUnaryInterceptor(log), @@ -271,9 +270,11 @@ func uploadFiles(ctx context.Context, client pb.DebugdClient, in deployOnEndpoin case pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_FINISHED: in.log.Info("Files already uploaded") case pb.UploadFilesStatus_UPLOAD_FILES_UPLOAD_FAILED: - return fmt.Errorf("uploading files to %v failed: %v", in.debugdEndpoint, uploadResponse) + return fmt.Errorf("uploading files to %v failed: %s: %s", in.debugdEndpoint, uploadResponse.Status, uploadResponse.Error) case pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_STARTED: return fmt.Errorf("upload already started on %v", in.debugdEndpoint) + case pb.UploadFilesStatus_UPLOAD_FILES_START_FAILED: + return fmt.Errorf("overriding service units failed on %v: %s: %s", in.debugdEndpoint, uploadResponse.Status, uploadResponse.Error) default: return fmt.Errorf("unknown upload status %v", uploadResponse.Status) } diff --git a/debugd/internal/debugd/deploy/BUILD.bazel b/debugd/internal/debugd/deploy/BUILD.bazel index 16ba9cdf3..29bdd0ccf 100644 --- a/debugd/internal/debugd/deploy/BUILD.bazel +++ b/debugd/internal/debugd/deploy/BUILD.bazel @@ -18,7 +18,7 @@ go_library( "//internal/constants", "@com_github_coreos_go_systemd_v22//dbus", "@com_github_spf13_afero//:afero", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//credentials/insecure", ], ) @@ -39,7 +39,7 @@ go_test( "@com_github_spf13_afero//:afero", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_uber_go_goleak//:goleak", ], ) diff --git a/debugd/internal/debugd/deploy/download.go b/debugd/internal/debugd/deploy/download.go index affe685d3..96ae8fd2f 100644 --- a/debugd/internal/debugd/deploy/download.go +++ b/debugd/internal/debugd/deploy/download.go @@ -53,7 +53,7 @@ func (d *Download) DownloadInfo(ctx context.Context, ip string) error { log := d.log.With(slog.String("ip", ip)) serverAddr := net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort)) - client, closer, err := d.newClient(ctx, serverAddr, log) + client, closer, err := d.newClient(serverAddr, log) if err != nil { return err } @@ -74,7 +74,7 @@ func (d *Download) DownloadDeployment(ctx context.Context, ip string) error { log := d.log.With(slog.String("ip", ip)) serverAddr := net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort)) - client, closer, err := d.newClient(ctx, serverAddr, log) + client, closer, err := d.newClient(serverAddr, log) if err != nil { return err } @@ -117,17 +117,17 @@ func (d *Download) DownloadDeployment(ctx context.Context, ip string) error { return nil } -func (d *Download) newClient(ctx context.Context, serverAddr string, log *slog.Logger) (pb.DebugdClient, io.Closer, error) { +func (d *Download) newClient(serverAddr string, log *slog.Logger) (pb.DebugdClient, io.Closer, error) { log.Info("Connecting to server") - conn, err := d.dial(ctx, serverAddr) + conn, err := d.dial(serverAddr) if err != nil { return nil, nil, fmt.Errorf("connecting to other instance via gRPC: %w", err) } return pb.NewDebugdClient(conn), conn, nil } -func (d *Download) dial(ctx context.Context, target string) (*grpc.ClientConn, error) { - return grpc.DialContext(ctx, target, +func (d *Download) dial(target string) (*grpc.ClientConn, error) { + return grpc.NewClient(target, d.grpcWithDialer(), grpc.WithTransportCredentials(insecure.NewCredentials()), ) diff --git a/debugd/internal/debugd/deploy/service.go b/debugd/internal/debugd/deploy/service.go index 2c71891cc..114e5da58 100644 --- a/debugd/internal/debugd/deploy/service.go +++ b/debugd/internal/debugd/deploy/service.go @@ -61,6 +61,7 @@ type SystemdUnit struct { type ServiceManager struct { log *slog.Logger dbus dbusClient + journal journalReader fs afero.Fs systemdUnitFilewriteLock sync.Mutex } @@ -71,6 +72,7 @@ func NewServiceManager(log *slog.Logger) *ServiceManager { return &ServiceManager{ log: log, dbus: &dbusWrapper{}, + journal: &journalctlWrapper{}, fs: fs, systemdUnitFilewriteLock: sync.Mutex{}, } @@ -89,6 +91,8 @@ type dbusConn interface { // StopUnitContext is similar to StartUnitContext, but stops the specified unit // rather than starting it. StopUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) + // ResetFailedUnitContext resets the "failed" state of a unit. + ResetFailedUnitContext(ctx context.Context, name string) error // RestartUnitContext restarts a service. If a service is restarted that isn't // running it will be started. RestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) @@ -99,6 +103,11 @@ type dbusConn interface { Close() } +type journalReader interface { + // ReadJournal reads the journal for a specific unit. + readJournal(unit string) string +} + // SystemdAction will perform a systemd action on a service unit (start, stop, restart, reload). func (s *ServiceManager) SystemdAction(ctx context.Context, request ServiceManagerRequest) error { log := s.log.With(slog.String("unit", request.Unit), slog.String("action", request.Action.String())) @@ -115,6 +124,9 @@ func (s *ServiceManager) SystemdAction(ctx context.Context, request ServiceManag case Stop: _, err = conn.StopUnitContext(ctx, request.Unit, "replace", resultChan) case Restart: + if err = conn.ResetFailedUnitContext(ctx, request.Unit); err != nil { + s.log.Error("Failed to reset unit failed state", "error", err.Error(), "unit", request.Unit) + } _, err = conn.RestartUnitContext(ctx, request.Unit, "replace", resultChan) case Reload: err = conn.ReloadContext(ctx) @@ -139,7 +151,8 @@ func (s *ServiceManager) SystemdAction(ctx context.Context, request ServiceManag return nil default: - return fmt.Errorf("performing action %q on systemd unit %q failed: expected %q but received %q", request.Action.String(), request.Unit, "done", result) + serviceJournal := s.journal.readJournal(request.Unit) + return fmt.Errorf("performing action %q on systemd unit %q failed: expected %q but received %q. systemd unit journal entries: %s", request.Action.String(), request.Unit, "done", result, serviceJournal) } } @@ -172,7 +185,7 @@ func (s *ServiceManager) OverrideServiceUnitExecStart(ctx context.Context, unitN if strings.Contains(execStart, "\n") || strings.Contains(execStart, "\r") { return fmt.Errorf("execStart must not contain newlines") } - overrideUnitContents := fmt.Sprintf("[Service]\nExecStart=\nExecStart=%s $CONSTELLATION_DEBUG_FLAGS\n", execStart) + overrideUnitContents := fmt.Sprintf("[Service]\nExecStart=\nExecStart=%s\n", execStart) s.systemdUnitFilewriteLock.Lock() defer s.systemdUnitFilewriteLock.Unlock() path := filepath.Join(systemdUnitFolder, unitName+".service.d", "override.conf") diff --git a/debugd/internal/debugd/deploy/service_test.go b/debugd/internal/debugd/deploy/service_test.go index 7ee879644..f0b398333 100644 --- a/debugd/internal/debugd/deploy/service_test.go +++ b/debugd/internal/debugd/deploy/service_test.go @@ -104,6 +104,7 @@ func TestSystemdAction(t *testing.T) { manager := ServiceManager{ log: logger.NewTest(t), dbus: &tc.dbus, + journal: &stubJournalReader{}, fs: fs, systemdUnitFilewriteLock: sync.Mutex{}, } @@ -183,6 +184,7 @@ func TestWriteSystemdUnitFile(t *testing.T) { manager := ServiceManager{ log: logger.NewTest(t), dbus: &tc.dbus, + journal: &stubJournalReader{}, fs: fs, systemdUnitFilewriteLock: sync.Mutex{}, } @@ -218,7 +220,7 @@ func TestOverrideServiceUnitExecStart(t *testing.T) { }, unitName: "test", execStart: "/run/state/bin/test", - wantFileContents: "[Service]\nExecStart=\nExecStart=/run/state/bin/test $CONSTELLATION_DEBUG_FLAGS\n", + wantFileContents: "[Service]\nExecStart=\nExecStart=/run/state/bin/test\n", wantActionCalls: []dbusConnActionInput{ {name: "test.service", mode: "replace"}, }, @@ -264,7 +266,7 @@ func TestOverrideServiceUnitExecStart(t *testing.T) { }, unitName: "test", execStart: "/run/state/bin/test", - wantFileContents: "[Service]\nExecStart=\nExecStart=/run/state/bin/test $CONSTELLATION_DEBUG_FLAGS\n", + wantFileContents: "[Service]\nExecStart=\nExecStart=/run/state/bin/test\n", wantActionCalls: []dbusConnActionInput{ {name: "test.service", mode: "replace"}, }, @@ -296,6 +298,7 @@ func TestOverrideServiceUnitExecStart(t *testing.T) { manager := ServiceManager{ log: logger.NewTest(t), dbus: &tc.dbus, + journal: &stubJournalReader{}, fs: fs, systemdUnitFilewriteLock: sync.Mutex{}, } @@ -353,6 +356,10 @@ func (c *fakeDbusConn) StopUnitContext(_ context.Context, name string, mode stri return c.jobID, c.actionErr } +func (c *fakeDbusConn) ResetFailedUnitContext(_ context.Context, _ string) error { + return nil +} + func (c *fakeDbusConn) RestartUnitContext(_ context.Context, name string, mode string, ch chan<- string) (int, error) { c.inputs = append(c.inputs, dbusConnActionInput{name: name, mode: mode}) ch <- c.result @@ -367,3 +374,9 @@ func (c *fakeDbusConn) ReloadContext(_ context.Context) error { } func (c *fakeDbusConn) Close() {} + +type stubJournalReader struct{} + +func (s *stubJournalReader) readJournal(_ string) string { + return "" +} diff --git a/debugd/internal/debugd/deploy/wrappers.go b/debugd/internal/debugd/deploy/wrappers.go index 9ec9f0b01..1c5acaee3 100644 --- a/debugd/internal/debugd/deploy/wrappers.go +++ b/debugd/internal/debugd/deploy/wrappers.go @@ -8,6 +8,7 @@ package deploy import ( "context" + "os/exec" "github.com/coreos/go-systemd/v22/dbus" ) @@ -37,6 +38,10 @@ func (c *dbusConnWrapper) StopUnitContext(ctx context.Context, name string, mode return c.conn.StopUnitContext(ctx, name, mode, ch) } +func (c *dbusConnWrapper) ResetFailedUnitContext(ctx context.Context, name string) error { + return c.conn.ResetFailedUnitContext(ctx, name) +} + func (c *dbusConnWrapper) RestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) { return c.conn.RestartUnitContext(ctx, name, mode, ch) } @@ -48,3 +53,85 @@ func (c *dbusConnWrapper) ReloadContext(ctx context.Context) error { func (c *dbusConnWrapper) Close() { c.conn.Close() } + +type journalctlWrapper struct{} + +func (j *journalctlWrapper) readJournal(unit string) string { + out, _ := exec.CommandContext(context.Background(), "journalctl", "-u", unit, "--no-pager").CombinedOutput() + return string(out) +} + +/* +// Preferably, we would use the systemd journal API directly. +// However, this requires linking against systemd libraries, so we go with the easier journalctl command for now. + +type sdJournalWrapper struct{} + +// readJournal reads the journal for a specific unit. +func (s *sdJournalWrapper) readJournal(unit string) string { + journal, err := sdjournal.NewJournal() + if err != nil { + log.Printf("opening journal: %s", err) + return "" + } + defer journal.Close() + + // Filter the journal for the specified unit + filters := []string{ + fmt.Sprintf("_SYSTEMD_UNIT=%s", unit), + fmt.Sprintf("UNIT=%s", unit), + fmt.Sprintf("OBJECT_SYSTEMD_UNIT=%s", unit), + fmt.Sprintf("_SYSTEMD_SLICE=%s", unit), + fmt.Sprintf("_SYSTEMD_USER_UNIT=%s", unit), + fmt.Sprintf("USER_UNIT=%s", unit), + fmt.Sprintf("COREDUMP_USER_UNIT=%s", unit), + fmt.Sprintf("OBJECT_SYSTEMD_USER_UNIT=%s", unit), + fmt.Sprintf("_SYSTEMD_USER_SLICE=%s", unit), + } + for _, filter := range filters { + if err := journal.AddMatch(filter); err != nil { + log.Printf("applying filter %q: %s", filter, err) + return "" + } + if err := journal.AddDisjunction(); err != nil { + log.Printf("adding disjunction to journal filter: %s", err) + return "" + } + } + + // Seek to the beginning of the journal + if err := journal.SeekHead(); err != nil { + log.Printf("seeking journal tail: %s", err) + return "" + } + + // Iterate over the journal entries + var previousCursor string + journalLog := &strings.Builder{} + for { + if _, err := journal.Next(); err != nil { + log.Printf("getting next entry in journal: %s", err) + return "" + } + + entry, err := journal.GetEntry() + if err != nil { + log.Printf("getting journal entry: %s", err) + return "" + } + + // Abort if we reached the end of the journal, i.e. the cursor didn't change + if entry.Cursor == previousCursor { + break + } + previousCursor = entry.Cursor + + if _, err := journalLog.WriteString(entry.Fields[sdjournal.SD_JOURNAL_FIELD_MESSAGE] + "\n"); err != nil { + log.Printf("copying journal entry to buffer: %s", err) + return "" + } + } + + return strings.TrimSpace(journalLog.String()) +} +*/ diff --git a/debugd/internal/debugd/logcollector/logcollector.go b/debugd/internal/debugd/logcollector/logcollector.go index 9723d102f..152a79894 100644 --- a/debugd/internal/debugd/logcollector/logcollector.go +++ b/debugd/internal/debugd/logcollector/logcollector.go @@ -11,7 +11,6 @@ package logcollector import ( "context" "fmt" - "io" "log/slog" "os" "os/exec" @@ -130,7 +129,7 @@ func getTemplate(ctx context.Context, logger *slog.Logger, image, templateDir, d "--name=template", image, } - createContainerCmd := exec.CommandContext(ctx, "podman", createContainerArgs...) + createContainerCmd := podman(ctx, createContainerArgs...) logger.Info("Creating template container") if out, err := createContainerCmd.CombinedOutput(); err != nil { return nil, fmt.Errorf("creating template container: %w\n%s", err, out) @@ -145,7 +144,7 @@ func getTemplate(ctx context.Context, logger *slog.Logger, image, templateDir, d "template:/usr/share/constellogs/templates/", destDir, } - copyFromCmd := exec.CommandContext(ctx, "podman", copyFromArgs...) + copyFromCmd := podman(ctx, copyFromArgs...) logger.Info("Copying templates") if out, err := copyFromCmd.CombinedOutput(); err != nil { return nil, fmt.Errorf("copying templates: %w\n%s", err, out) @@ -155,7 +154,7 @@ func getTemplate(ctx context.Context, logger *slog.Logger, image, templateDir, d "rm", "template", } - removeContainerCmd := exec.CommandContext(ctx, "podman", removeContainerArgs...) + removeContainerCmd := podman(ctx, removeContainerArgs...) logger.Info("Removing template container") if out, err := removeContainerCmd.CombinedOutput(); err != nil { return nil, fmt.Errorf("removing template container: %w\n%s", err, out) @@ -176,40 +175,43 @@ func startPod(ctx context.Context, logger *slog.Logger) error { "create", "logcollection", } - createPodCmd := exec.CommandContext(ctx, "podman", createPodArgs...) + createPodCmd := podman(ctx, createPodArgs...) logger.Info(fmt.Sprintf("Create pod command: %v", createPodCmd.String())) if out, err := createPodCmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to create pod: %w; output: %s", err, out) } // start logstash container - logstashLog := newCmdLogger(logger.WithGroup("logstash")) runLogstashArgs := []string{ "run", - "--rm", + "-d", + "--restart=unless-stopped", "--name=logstash", "--pod=logcollection", - "--log-driver=none", + "--log-driver=journald", "--volume=/run/logstash/pipeline:/usr/share/logstash/pipeline/:ro", versions.LogstashImage, } - runLogstashCmd := exec.CommandContext(ctx, "podman", runLogstashArgs...) + runLogstashCmd := podman(ctx, runLogstashArgs...) logger.Info(fmt.Sprintf("Run logstash command: %v", runLogstashCmd.String())) - runLogstashCmd.Stdout = logstashLog - runLogstashCmd.Stderr = logstashLog - if err := runLogstashCmd.Start(); err != nil { + if out, err := runLogstashCmd.CombinedOutput(); err != nil { + logger.Error("Could not start logstash container", "err", err, "output", out) return fmt.Errorf("failed to start logstash: %w", err) } + if out, err := podman(ctx, "wait", "logstash", "--condition=running", "--interval=15s").CombinedOutput(); err != nil { + logger.Error("Logstash container failed to reach healthy status", "err", err, "output", out) + return fmt.Errorf("waiting for logstash container to reach healthy status: %w; output: %s", err, out) + } // start filebeat container - filebeatLog := newCmdLogger(logger.WithGroup("filebeat")) runFilebeatArgs := []string{ "run", - "--rm", + "-d", + "--restart=unless-stopped", "--name=filebeat", "--pod=logcollection", "--privileged", - "--log-driver=none", + "--log-driver=journald", "--volume=/run/log/journal:/run/log/journal:ro", "--volume=/etc/machine-id:/etc/machine-id:ro", "--volume=/run/systemd:/run/systemd:ro", @@ -218,13 +220,16 @@ func startPod(ctx context.Context, logger *slog.Logger) error { "--volume=/run/filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro", versions.FilebeatImage, } - runFilebeatCmd := exec.CommandContext(ctx, "podman", runFilebeatArgs...) + runFilebeatCmd := podman(ctx, runFilebeatArgs...) logger.Info(fmt.Sprintf("Run filebeat command: %v", runFilebeatCmd.String())) - runFilebeatCmd.Stdout = filebeatLog - runFilebeatCmd.Stderr = filebeatLog - if err := runFilebeatCmd.Start(); err != nil { + if out, err := runFilebeatCmd.CombinedOutput(); err != nil { + logger.Error("Could not start filebeat container", "err", err, "output", out) return fmt.Errorf("failed to run filebeat: %w", err) } + if out, err := podman(ctx, "wait", "filebeat", "--condition=running", "--interval=15s").CombinedOutput(); err != nil { + logger.Error("Filebeat container failed to reach healthy status", "err", err, "output", out) + return fmt.Errorf("waiting for filebeat container to reach healthy status: %w; output: %s", err, out) + } return nil } @@ -295,17 +300,9 @@ func setCloudMetadata(ctx context.Context, m map[string]string, provider cloudpr } } -func newCmdLogger(logger *slog.Logger) io.Writer { - return &cmdLogger{logger: logger} -} - -type cmdLogger struct { - logger *slog.Logger -} - -func (c *cmdLogger) Write(p []byte) (n int, err error) { - c.logger.Info(string(p)) - return len(p), nil +func podman(ctx context.Context, args ...string) *exec.Cmd { + args = append([]string{"--runtime=runc"}, args...) + return exec.CommandContext(ctx, "podman", args...) } type providerMetadata interface { diff --git a/debugd/internal/debugd/server/BUILD.bazel b/debugd/internal/debugd/server/BUILD.bazel index ee0de46c2..6d8d298be 100644 --- a/debugd/internal/debugd/server/BUILD.bazel +++ b/debugd/internal/debugd/server/BUILD.bazel @@ -13,7 +13,7 @@ go_library( "//debugd/service", "//internal/constants", "//internal/logger", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//keepalive", ], ) @@ -32,7 +32,7 @@ go_test( "//internal/logger", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//credentials/insecure", "@org_uber_go_goleak//:goleak", ], diff --git a/debugd/internal/debugd/server/server.go b/debugd/internal/debugd/server/server.go index aeae7c4a1..64bbbc042 100644 --- a/debugd/internal/debugd/server/server.go +++ b/debugd/internal/debugd/server/server.go @@ -106,6 +106,7 @@ func (s *debugdServer) UploadFiles(stream pb.Debugd_UploadFilesServer) error { s.log.With(slog.Any("error", err)).Error("Uploading files failed") return stream.SendAndClose(&pb.UploadFilesResponse{ Status: pb.UploadFilesStatus_UPLOAD_FILES_UPLOAD_FAILED, + Error: err.Error(), }) } @@ -124,6 +125,7 @@ func (s *debugdServer) UploadFiles(stream pb.Debugd_UploadFilesServer) error { s.log.With(slog.Any("error", overrideUnitErr)).Error("Overriding service units failed") return stream.SendAndClose(&pb.UploadFilesResponse{ Status: pb.UploadFilesStatus_UPLOAD_FILES_START_FAILED, + Error: overrideUnitErr.Error(), }) } return stream.SendAndClose(&pb.UploadFilesResponse{ @@ -155,8 +157,8 @@ func Start(log *slog.Logger, wg *sync.WaitGroup, serv pb.DebugdServer) { go func() { defer wg.Done() - grpcLog := log.WithGroup("gRPC") - logger.ReplaceGRPCLogger(slog.New(logger.NewLevelHandler(slog.LevelWarn, grpcLog.Handler()))) + grpcLog := logger.GRPCLogger(log) + logger.ReplaceGRPCLogger(grpcLog) grpcServer := grpc.NewServer( logger.GetServerStreamInterceptor(grpcLog), diff --git a/debugd/internal/debugd/server/server_test.go b/debugd/internal/debugd/server/server_test.go index 3ae8b3312..30d2a2c9e 100644 --- a/debugd/internal/debugd/server/server_test.go +++ b/debugd/internal/debugd/server/server_test.go @@ -371,8 +371,8 @@ type netDialer interface { DialContext(_ context.Context, network, address string) (net.Conn, error) } -func dial(ctx context.Context, dialer netDialer, target string) (*grpc.ClientConn, error) { - return grpc.DialContext(ctx, target, +func dial(dialer netDialer, target string) (*grpc.ClientConn, error) { + return grpc.NewClient(target, grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) { return dialer.DialContext(ctx, "tcp", addr) }), @@ -414,7 +414,7 @@ func setupServerWithConn(endpoint string, serv *debugdServer) (*grpc.Server, *gr lis := dialer.GetListener(endpoint) go grpcServ.Serve(lis) - conn, err := dial(context.Background(), dialer, endpoint) + conn, err := dial(dialer, endpoint) if err != nil { return nil, nil, err } diff --git a/debugd/logstash/Dockerfile b/debugd/logstash/Dockerfile index 92efbdb30..e0db1695a 100644 --- a/debugd/logstash/Dockerfile +++ b/debugd/logstash/Dockerfile @@ -1,11 +1,11 @@ -FROM fedora:40@sha256:5ce8497aeea599bf6b54ab3979133923d82aaa4f6ca5ced1812611b197c79eb0 AS build +FROM fedora:40@sha256:7cdd2b48396929bb8723ea2fa60e03bee39cc22e2a853cbd891587fab4eb1bc9 AS build ARG LOGSTASH_VER=8.6.1 RUN curl -fsSLO https://artifacts.opensearch.org/logstash/logstash-oss-with-opensearch-output-plugin-$LOGSTASH_VER-linux-x64.tar.gz RUN tar -zxvf logstash-oss-with-opensearch-output-plugin-$LOGSTASH_VER-linux-x64.tar.gz -FROM fedora:40@sha256:5ce8497aeea599bf6b54ab3979133923d82aaa4f6ca5ced1812611b197c79eb0 AS release +FROM fedora:40@sha256:7cdd2b48396929bb8723ea2fa60e03bee39cc22e2a853cbd891587fab4eb1bc9 AS release COPY --from=build logstash-* /usr/share/logstash diff --git a/debugd/metricbeat/Dockerfile b/debugd/metricbeat/Dockerfile index a399973da..108882355 100644 --- a/debugd/metricbeat/Dockerfile +++ b/debugd/metricbeat/Dockerfile @@ -1,4 +1,4 @@ -FROM fedora:40@sha256:5ce8497aeea599bf6b54ab3979133923d82aaa4f6ca5ced1812611b197c79eb0 AS release +FROM fedora:40@sha256:7cdd2b48396929bb8723ea2fa60e03bee39cc22e2a853cbd891587fab4eb1bc9 AS release RUN dnf install -y https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-8.9.2-x86_64.rpm diff --git a/debugd/service/debugd.pb.go b/debugd/service/debugd.pb.go index 94849aae9..742b39998 100644 --- a/debugd/service/debugd.pb.go +++ b/debugd/service/debugd.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.1 -// protoc v4.22.1 +// protoc-gen-go v1.35.1 +// protoc v5.29.0--rc2 // source: debugd/service/debugd.proto package service @@ -181,11 +181,9 @@ type SetInfoRequest struct { func (x *SetInfoRequest) Reset() { *x = SetInfoRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SetInfoRequest) String() string { @@ -196,7 +194,7 @@ func (*SetInfoRequest) ProtoMessage() {} func (x *SetInfoRequest) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -228,11 +226,9 @@ type SetInfoResponse struct { func (x *SetInfoResponse) Reset() { *x = SetInfoResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SetInfoResponse) String() string { @@ -243,7 +239,7 @@ func (*SetInfoResponse) ProtoMessage() {} func (x *SetInfoResponse) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -273,11 +269,9 @@ type GetInfoRequest struct { func (x *GetInfoRequest) Reset() { *x = GetInfoRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GetInfoRequest) String() string { @@ -288,7 +282,7 @@ func (*GetInfoRequest) ProtoMessage() {} func (x *GetInfoRequest) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -313,11 +307,9 @@ type GetInfoResponse struct { func (x *GetInfoResponse) Reset() { *x = GetInfoResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GetInfoResponse) String() string { @@ -328,7 +320,7 @@ func (*GetInfoResponse) ProtoMessage() {} func (x *GetInfoResponse) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -361,11 +353,9 @@ type Info struct { func (x *Info) Reset() { *x = Info{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Info) String() string { @@ -376,7 +366,7 @@ func (*Info) ProtoMessage() {} func (x *Info) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -413,11 +403,9 @@ type DownloadFilesRequest struct { func (x *DownloadFilesRequest) Reset() { *x = DownloadFilesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DownloadFilesRequest) String() string { @@ -428,7 +416,7 @@ func (*DownloadFilesRequest) ProtoMessage() {} func (x *DownloadFilesRequest) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -457,11 +445,9 @@ type FileTransferMessage struct { func (x *FileTransferMessage) Reset() { *x = FileTransferMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FileTransferMessage) String() string { @@ -472,7 +458,7 @@ func (*FileTransferMessage) ProtoMessage() {} func (x *FileTransferMessage) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -536,11 +522,9 @@ type FileTransferHeader struct { func (x *FileTransferHeader) Reset() { *x = FileTransferHeader{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FileTransferHeader) String() string { @@ -551,7 +535,7 @@ func (*FileTransferHeader) ProtoMessage() {} func (x *FileTransferHeader) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -598,11 +582,9 @@ type Chunk struct { func (x *Chunk) Reset() { *x = Chunk{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Chunk) String() string { @@ -613,7 +595,7 @@ func (*Chunk) ProtoMessage() {} func (x *Chunk) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -648,15 +630,14 @@ type UploadFilesResponse struct { unknownFields protoimpl.UnknownFields Status UploadFilesStatus `protobuf:"varint,1,opt,name=status,proto3,enum=debugd.UploadFilesStatus" json:"status,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` } func (x *UploadFilesResponse) Reset() { *x = UploadFilesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *UploadFilesResponse) String() string { @@ -667,7 +648,7 @@ func (*UploadFilesResponse) ProtoMessage() {} func (x *UploadFilesResponse) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -689,6 +670,13 @@ func (x *UploadFilesResponse) GetStatus() UploadFilesStatus { return UploadFilesStatus_UPLOAD_FILES_SUCCESS } +func (x *UploadFilesResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + type ServiceUnit struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -700,11 +688,9 @@ type ServiceUnit struct { func (x *ServiceUnit) Reset() { *x = ServiceUnit{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ServiceUnit) String() string { @@ -715,7 +701,7 @@ func (*ServiceUnit) ProtoMessage() {} func (x *ServiceUnit) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -754,11 +740,9 @@ type UploadSystemdServiceUnitsRequest struct { func (x *UploadSystemdServiceUnitsRequest) Reset() { *x = UploadSystemdServiceUnitsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *UploadSystemdServiceUnitsRequest) String() string { @@ -769,7 +753,7 @@ func (*UploadSystemdServiceUnitsRequest) ProtoMessage() {} func (x *UploadSystemdServiceUnitsRequest) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -801,11 +785,9 @@ type UploadSystemdServiceUnitsResponse struct { func (x *UploadSystemdServiceUnitsResponse) Reset() { *x = UploadSystemdServiceUnitsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_debugd_service_debugd_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_debugd_service_debugd_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *UploadSystemdServiceUnitsResponse) String() string { @@ -816,7 +798,7 @@ func (*UploadSystemdServiceUnitsResponse) ProtoMessage() {} func (x *UploadSystemdServiceUnitsResponse) ProtoReflect() protoreflect.Message { mi := &file_debugd_service_debugd_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -880,79 +862,80 @@ var file_debugd_service_debugd_proto_rawDesc = []byte{ 0x22, 0x35, 0x0a, 0x05, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x61, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x04, 0x6c, 0x61, 0x73, 0x74, 0x22, 0x48, 0x0a, 0x13, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x08, 0x52, 0x04, 0x6c, 0x61, 0x73, 0x74, 0x22, 0x5e, 0x0a, 0x13, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x22, 0x3d, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x22, 0x4d, 0x0a, 0x20, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x22, - 0x64, 0x0a, 0x21, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x2a, 0x3f, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x45, 0x54, 0x5f, 0x49, 0x4e, - 0x46, 0x4f, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, - 0x53, 0x45, 0x54, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, - 0x5f, 0x53, 0x45, 0x54, 0x10, 0x01, 0x2a, 0xb1, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x6c, 0x6f, 0x61, - 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x14, - 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x53, 0x55, 0x43, - 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, - 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x41, - 0x49, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, - 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x53, - 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, 0x55, 0x50, 0x4c, 0x4f, - 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, - 0x5f, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x55, - 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x53, 0x54, 0x41, 0x52, - 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x2a, 0x75, 0x0a, 0x1f, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, + 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x3d, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x4d, 0x0a, 0x20, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, + 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, + 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x05, 0x75, 0x6e, + 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x64, 0x65, 0x62, 0x75, + 0x67, 0x64, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x05, + 0x75, 0x6e, 0x69, 0x74, 0x73, 0x22, 0x64, 0x0a, 0x21, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x64, 0x65, 0x62, + 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2a, 0x3f, 0x0a, 0x0d, 0x53, + 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x10, + 0x53, 0x45, 0x54, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, + 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, 0x54, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, + 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x53, 0x45, 0x54, 0x10, 0x01, 0x2a, 0xb1, 0x01, 0x0a, + 0x11, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, + 0x45, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, + 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x55, 0x50, 0x4c, + 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, + 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x41, 0x4c, 0x52, + 0x45, 0x41, 0x44, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x21, + 0x0a, 0x1d, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x41, + 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, + 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, + 0x53, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, + 0x2a, 0x75, 0x0a, 0x1f, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x24, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x53, 0x59, + 0x53, 0x54, 0x45, 0x4d, 0x44, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, + 0x49, 0x54, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x44, 0x5f, - 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x49, 0x54, 0x53, 0x5f, 0x53, 0x55, - 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x55, 0x50, 0x4c, 0x4f, 0x41, - 0x44, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x44, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, - 0x45, 0x5f, 0x55, 0x4e, 0x49, 0x54, 0x53, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, - 0x01, 0x32, 0x94, 0x03, 0x0a, 0x06, 0x44, 0x65, 0x62, 0x75, 0x67, 0x64, 0x12, 0x3c, 0x0a, 0x07, - 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, - 0x2e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x17, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x07, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x47, - 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, - 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0b, 0x55, 0x70, 0x6c, 0x6f, - 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, - 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1b, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x4e, 0x0a, 0x0d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, - 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, - 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x46, 0x69, - 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x71, 0x0a, 0x18, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, - 0x73, 0x12, 0x28, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x49, 0x54, 0x53, 0x5f, 0x46, 0x41, + 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x01, 0x32, 0x94, 0x03, 0x0a, 0x06, 0x44, 0x65, 0x62, 0x75, + 0x67, 0x64, 0x12, 0x3c, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, + 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x53, + 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x3c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x64, 0x65, + 0x62, 0x75, 0x67, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x47, 0x65, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, + 0x0a, 0x0b, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1b, 0x2e, + 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x66, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1b, 0x2e, 0x64, 0x65, 0x62, + 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x4e, 0x0a, 0x0d, 0x44, + 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x64, + 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x64, 0x65, 0x62, + 0x75, 0x67, 0x64, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x71, 0x0a, 0x18, 0x55, + 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x12, 0x28, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, + 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x29, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, - 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x64, 0x65, - 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x64, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x73, - 0x79, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x38, + 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x64, 0x67, + 0x65, 0x6c, 0x65, 0x73, 0x73, 0x73, 0x79, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x6c, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, + 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -969,7 +952,7 @@ func file_debugd_service_debugd_proto_rawDescGZIP() []byte { var file_debugd_service_debugd_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_debugd_service_debugd_proto_msgTypes = make([]protoimpl.MessageInfo, 13) -var file_debugd_service_debugd_proto_goTypes = []interface{}{ +var file_debugd_service_debugd_proto_goTypes = []any{ (SetInfoStatus)(0), // 0: debugd.SetInfoStatus (UploadFilesStatus)(0), // 1: debugd.UploadFilesStatus (UploadSystemdServiceUnitsStatus)(0), // 2: debugd.UploadSystemdServiceUnitsStatus @@ -1018,169 +1001,11 @@ func file_debugd_service_debugd_proto_init() { if File_debugd_service_debugd_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_debugd_service_debugd_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetInfoRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetInfoResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInfoRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInfoResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Info); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DownloadFilesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FileTransferMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FileTransferHeader); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Chunk); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UploadFilesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceUnit); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UploadSystemdServiceUnitsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_debugd_service_debugd_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UploadSystemdServiceUnitsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_debugd_service_debugd_proto_msgTypes[6].OneofWrappers = []interface{}{ + file_debugd_service_debugd_proto_msgTypes[6].OneofWrappers = []any{ (*FileTransferMessage_Header)(nil), (*FileTransferMessage_Chunk)(nil), } - file_debugd_service_debugd_proto_msgTypes[7].OneofWrappers = []interface{}{} + file_debugd_service_debugd_proto_msgTypes[7].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/debugd/service/debugd.proto b/debugd/service/debugd.proto index db9c3b896..77bc94a60 100644 --- a/debugd/service/debugd.proto +++ b/debugd/service/debugd.proto @@ -58,6 +58,7 @@ message Chunk { message UploadFilesResponse { UploadFilesStatus status = 1; + string error = 2; } enum UploadFilesStatus { diff --git a/dev-docs/chain-of-trust.jpg b/dev-docs/chain-of-trust.jpg new file mode 100644 index 000000000..713e4715e Binary files /dev/null and b/dev-docs/chain-of-trust.jpg differ diff --git a/dev-docs/howto/bare-metal/README.md b/dev-docs/howto/bare-metal/README.md new file mode 100644 index 000000000..e4df4cd97 --- /dev/null +++ b/dev-docs/howto/bare-metal/README.md @@ -0,0 +1,66 @@ +# Bare-metal SNP setup for Constellation + +## Prepare Host + +The bare-metal host machine needs to be able to start SEV-SNP VMs. +A thorough explanation can be found here: . + +First checkout the snp-latest branch: + +```bash +git clone https://github.com/AMDESE/AMDSEV.git +cd AMDSEV +git checkout snp-latest +``` + +Then enable TPM2 support by setting `-DTPM2_ENABLE` in the OVMF build command +found in `common.sh`: + +```patch +diff --git a/common.sh b/common.sh +index 9eee947..52bf507 100755 +--- a/common.sh ++++ b/common.sh +@@ -155,7 +155,7 @@ build_install_ovmf() + GCCVERS="GCC5" + fi + +- BUILD_CMD="nice build -q --cmd-len=64436 -DDEBUG_ON_SERIAL_PORT=TRUE -n $(getconf _NPROCESSORS_ONLN) ${GCCVERS:+-t $GCCVERS} -a X64 -p OvmfPkg/OvmfPkgX64.dsc" ++ BUILD_CMD="nice build -q --cmd-len=64436 -DTPM2_ENABLE -DDEBUG_ON_SERIAL_PORT=TRUE -n $(getconf _NPROCESSORS_ONLN) ${GCCVERS:+-t $GCCVERS} -a X64 -p OvmfPkg/OvmfPkgX64.dsc" + + # initialize git repo, or update existing remote to currently configured one + if [ -d ovmf ]; then +``` + +Build and package the binaries. Then install the newly build kernel: + +```bash +./build.sh --package +cd linux +dpkg -i linux-image-6.9.0-rc7-snp-host-05b10142ac6a_6.9.0-rc7-g05b10142ac6a-2_amd64.deb +``` + +Reboot, verify that the right BIOS setting are set as described in + +and select the new kernel in the boot menu. Note that GRUB usually automatically +select the newest installed kernel as default. + +Download a Constellation qemu image, the `constellation-conf.yaml`, and +the `launch-constellation.sh` script in the directory right next to the +`AMDSEV` folder. + +```bash +wget https://raw.githubusercontent.com/edgelesssys/constellation/main/dev-docs/howto/bare-metal/launch-constellation.sh +wget https://cdn.confidential.cloud/constellation/v1/ref/main/stream/console/v2.17.0-pre.0.20240516182331-5fb2a2cb89f2/image/csp/qemu/qemu-vtpm/image.raw +wget < link to the constellation CLI provided by Edgeless > +wget < link to the constellation config provided by Edgeless > +``` + +Install and setup [docker](https://docs.docker.com/engine/install/), +install swtpm, dnsmasq and tmux. + +Then simply run: + +```bash +sudo ./launch-constellation.sh +``` diff --git a/dev-docs/howto/bare-metal/launch-constellation.sh b/dev-docs/howto/bare-metal/launch-constellation.sh new file mode 100644 index 000000000..27fc4f83b --- /dev/null +++ b/dev-docs/howto/bare-metal/launch-constellation.sh @@ -0,0 +1,202 @@ +#!/usr/bin/env bash + +set -euo pipefail + +set -x + +function cleanup { + kill -SIGTERM "$(cat "${PWD}"/qemu-dnsmasq-br0.pid)" || true + rm "${PWD}"/qemu-dnsmasq-br0.pid || true + + kill -SIGTERM "$(cat "${PWD}"/swtpm0.pid)" || true + kill -SIGTERM "$(cat "${PWD}"/swtpm1.pid)" || true + + ip l delete br0 || true + ip l delete tap0 || true + ip l delete tap1 || true + + rm -r "${PWD}"/tpm0 || true + rm -r "${PWD}"/tpm1 || true + + rm OVMF_VARS_0.fd || true + rm OVMF_VARS_1.fd || true + + rm dnsmasq.leases || true + rm dnsmasq.log || true + + rm constellation-mastersecret.json || true + rm constellation-admin.conf || true + rm constellation-cluster.log || true + rm constellation-debug.log || true + rm constellation-state.yaml || true + rm -r constellation-upgrade || true + + docker stop metadata-server || true +} + +trap cleanup EXIT + +get_mac() { + printf '52:54:%02X:%02X:%02X:%02X' $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) +} + +mac_0=$(get_mac) +mac_1=$(get_mac) + +# Regarding network setup see: https://bbs.archlinux.org/viewtopic.php?id=207907 + +dd if=/dev/zero of=disk0.img iflag=fullblock bs=1M count=10000 && sync +dd if=/dev/zero of=disk1.img iflag=fullblock bs=1M count=10000 && sync + +DEFAULT_INTERFACE=$(ip r show default | cut -d' ' -f5) + +ip link add name br0 type bridge || true +ip addr add 10.42.0.1/16 dev br0 || true +ip link set br0 up + +dnsmasq \ + --pid-file="${PWD}"/qemu-dnsmasq-br0.pid \ + --interface=br0 \ + --bind-interfaces \ + --log-facility="${PWD}"/dnsmasq.log \ + --dhcp-range=10.42.0.2,10.42.255.254 \ + --dhcp-leasefile="${PWD}"/dnsmasq.leases \ + --dhcp-host="${mac_0}",10.42.1.1,control-plane0 \ + --dhcp-host="${mac_1}",10.42.2.1,worker0 + +password=$(tr -dc 'A-Za-z0-9!?%=' < /dev/urandom | head -c 32) || true +password_hex=$(echo -n "${password}" | xxd -p -u -c 256) +echo "${password_hex}" + +# htpasswd from apache2-utils +password_bcrypt=$(htpasswd -bnBC 10 "" "${password}" | tr -d ':\n') + +docker run \ + -dit \ + --rm \ + --name metadata-server \ + --net=host \ + --mount type=bind,source="$(pwd)"/dnsmasq.leases,target=/dnsmasq.leases \ + ghcr.io/edgelesssys/constellation/qemu-metadata-api:v2.17.0-pre.0.20240603111213-d7ce6af383f2 \ + --dnsmasq-leases /dnsmasq.leases --initsecrethash "${password_bcrypt}" + +cat > ./constellation-state.yaml <<- EOM +version: v1 # Schema version of this state file. +# State of the cluster's cloud resources. These values are retrieved during +infrastructure: + uid: qemu # Unique identifier the cluster's cloud resources are tagged with. + clusterEndpoint: 10.42.1.1 # Endpoint the cluster can be reached at. This is the endpoint that is being used by the CLI. + inClusterEndpoint: 10.42.1.1 # The Cluster uses to reach itself. This might differ from the ClusterEndpoint in case e.g., + initSecret: "${password_hex}" # Secret used to authenticate the bootstrapping node. + # List of Subject Alternative Names (SANs) to add to the Kubernetes API server certificate. + apiServerCertSANs: + - 10.42.1.1 + name: mini-qemu # Name used in the cluster's named resources. + ipCidrNode: 10.42.0.0/16 # CIDR range of the cluster's nodes. +# DO NOT EDIT. State of the Constellation Kubernetes cluster. +clusterValues: + clusterID: "" # Unique identifier of the cluster. + ownerID: "" # Unique identifier of the owner of the cluster. + measurementSalt: "" # Salt used to generate the ClusterID on the bootstrapping node. +EOM + +sysctl net.ipv4.ip_forward=1 +sysctl net.ipv6.conf.default.forwarding=1 +sysctl net.ipv6.conf.all.forwarding=1 + +iptables -t nat -C POSTROUTING -o "${DEFAULT_INTERFACE}" -j MASQUERADE || iptables -t nat -I POSTROUTING -o "${DEFAULT_INTERFACE}" -j MASQUERADE +iptables -C FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT || iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +iptables -P FORWARD ACCEPT + +ip tuntap add dev tap0 mode tap user "${USER}" || true +ip link set tap0 up promisc on +ip link set tap0 master br0 + +iptables -C FORWARD -i tap0 -o "${DEFAULT_INTERFACE}" -j ACCEPT || iptables -I FORWARD -i tap0 -o "${DEFAULT_INTERFACE}" -j ACCEPT + +ip tuntap add dev tap1 mode tap user "${USER}" || true +ip link set tap1 up promisc on +ip link set tap1 master br0 + +iptables -C FORWARD -i tap1 -o "${DEFAULT_INTERFACE}" -j ACCEPT || iptables -I FORWARD -i tap1 -o "${DEFAULT_INTERFACE}" -j ACCEPT + +# +# ovmf +# + +cp AMDSEV/usr/local/share/qemu/OVMF_VARS.fd OVMF_VARS_0.fd +cp AMDSEV/usr/local/share/qemu/OVMF_VARS.fd OVMF_VARS_1.fd + +# +# swtpm +# + +mkdir "${PWD}"/tpm0 || true +swtpm_setup --tpm2 --tpmstate "${PWD}/tpm0" --create-ek-cert --create-platform-cert --allow-signing --overwrite --pcr-banks - --logfile "${PWD}/tpm0/setup.log" +swtpm socket --tpm2 --tpmstate dir="${PWD}/tpm0",mode=0600 --ctrl type=unixio,path="${PWD}/tpm0/swtpm-sock" --log file="${PWD}/tpm0/tpm.log",level=20,truncate --pid file="${PWD}/swtpm0.pid" & + +mkdir "${PWD}"/tpm1 || true +swtpm_setup --tpm2 --tpmstate "${PWD}/tpm1" --create-ek-cert --create-platform-cert --allow-signing --overwrite --pcr-banks - --logfile "${PWD}/tpm1/setup.log" +swtpm socket --tpm2 --tpmstate dir="${PWD}/tpm1",mode=0600 --ctrl type=unixio,path="${PWD}/tpm1/swtpm-sock" --log file="${PWD}/tpm1/tpm.log",level=20,truncate --pid file="${PWD}/swtpm1.pid" & + +tmux new-session -d -s const-sess + +tmux split-window +tmux split-window + +launch_cmd_base_sev="AMDSEV/usr/local/bin/qemu-system-x86_64 \ + -enable-kvm \ + -cpu EPYC-v4 \ + -machine q35,smm=off \ + -smp 4,maxcpus=255 \ + -m 2048M,slots=5,maxmem=$((2048 + 8192))M \ + -no-reboot \ + -bios AMDSEV/usr/local/share/qemu/OVMF_CODE.fd \ + -drive file=./image.raw,if=none,id=disk1,format=raw,readonly=on \ + -device virtio-blk-pci,drive=disk1,id=virtio-disk1,disable-legacy=on,iommu_platform=true,bootindex=1 \ + -machine memory-encryption=sev0,vmport=off \ + -object memory-backend-memfd,id=ram1,size=2048M,share=true,prealloc=false \ + -machine memory-backend=ram1 \ + -object sev-snp-guest,id=sev0,cbitpos=51,reduced-phys-bits=1 \ + -nographic \ + -device virtio-blk-pci,drive=disk2,id=virtio-disk2 \ + -tpmdev emulator,id=tpm0,chardev=chrtpm \ + -device tpm-crb,tpmdev=tpm0" + +# shellcheck disable=2034 +launch_cmd_base_no_sev="AMDSEV/usr/local/bin/qemu-system-x86_64 \ + -enable-kvm \ + -cpu EPYC-v4 \ + -machine q35 \ + -smp 1,maxcpus=255 \ + -m 2048M,slots=5,maxmem=10240M \ + -no-reboot \ + -drive if=pflash,format=raw,unit=0,file=${PWD}/OVMF_CODE.fd,readonly=true \ + -drive file=./image.raw,if=none,id=disk1,format=raw,readonly=on \ + -device virtio-blk-pci,drive=disk1,id=virtio-disk1,disable-legacy=on,iommu_platform=true,bootindex=1 \ + -nographic \ + -device virtio-blk-pci,drive=disk2,id=virtio-disk2 \ + -tpmdev emulator,id=tpm0,chardev=chrtpm \ + -device tpm-crb,tpmdev=tpm0" + +launch_cmd_0="${launch_cmd_base_sev} \ + -drive if=pflash,format=raw,unit=0,file=${PWD}/OVMF_VARS_0.fd \ + -device virtio-net,netdev=network0,mac=${mac_0} \ + -netdev tap,id=network0,ifname=tap0,script=no,downscript=no \ + -drive file=./disk0.img,id=disk2,if=none,format=raw \ + -chardev socket,id=chrtpm,path=${PWD}/tpm0/swtpm-sock" +launch_cmd_1="${launch_cmd_base_sev} \ + -drive if=pflash,format=raw,unit=0,file=${PWD}/OVMF_VARS_1.fd \ + -device virtio-net,netdev=network0,mac=${mac_1} \ + -netdev tap,id=network0,ifname=tap1,script=no,downscript=no \ + -drive file=./disk1.img,id=disk2,if=none,format=raw \ + -chardev socket,id=chrtpm,path=${PWD}/tpm1/swtpm-sock" + +init_cmd="./constellation apply --skip-phases infrastructure" + +tmux send -t const-sess:0.0 "${launch_cmd_0}" ENTER +sleep 3 +tmux send -t const-sess:0.1 "${launch_cmd_1}" ENTER +tmux send -t const-sess:0.2 "${init_cmd}" ENTER + +tmux a -t const-sess diff --git a/dev-docs/howto/vpn/helm/templates/_helpers.tpl b/dev-docs/howto/vpn/helm/templates/_helpers.tpl index a5218b3ee..ab8a91e66 100644 --- a/dev-docs/howto/vpn/helm/templates/_helpers.tpl +++ b/dev-docs/howto/vpn/helm/templates/_helpers.tpl @@ -39,4 +39,6 @@ app.kubernetes.io/instance: {{ .Release.Name }} value: {{ .Values.serviceCIDR | quote }} - name: VPN_FRONTEND_POD value: {{ include "..fullname" . }}-frontend-0 +- name: VPN_MTU + value: {{ .Values.mtu | quote }} {{- end }} diff --git a/dev-docs/howto/vpn/helm/values.yaml b/dev-docs/howto/vpn/helm/values.yaml index 13281c917..607a2775d 100644 --- a/dev-docs/howto/vpn/helm/values.yaml +++ b/dev-docs/howto/vpn/helm/values.yaml @@ -8,6 +8,10 @@ serviceCIDR: "10.96.0.0/12" # on-prem IP ranges to expose to Constellation. Must contain at least one CIDR. peerCIDRs: [] +# MTU to set on the VPN route. Leave empty if path MTU discovery is supported end-to-end. +# See also https://docs.strongswan.org/docs/5.9/howtos/forwarding.html#_mtumss_issues. +mtu: 1300 + # IPSec configuration ipsec: # pre-shared key used for authentication @@ -15,4 +19,4 @@ ipsec: # Address of the peer's gateway router. peer: "" -image: "ghcr.io/edgelesssys/constellation/vpn@sha256:34e28ced172d04dfdadaadbefb1a53b5857cb24fb24e275fbbc537f3639a789e" +image: "ghcr.io/edgelesssys/constellation/vpn@sha256:88b6a0265052cb0a68d20d9b20e0d42ef15e7a80e5f71201ecf32e004de2356e" diff --git a/dev-docs/howto/vpn/on-prem-terraform/.terraform.lock.hcl b/dev-docs/howto/vpn/on-prem-terraform/.terraform.lock.hcl index a11464c43..78936e6a3 100644 --- a/dev-docs/howto/vpn/on-prem-terraform/.terraform.lock.hcl +++ b/dev-docs/howto/vpn/on-prem-terraform/.terraform.lock.hcl @@ -2,50 +2,56 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "3.92.0" - constraints = "3.92.0" + version = "4.1.0" + constraints = "4.1.0" hashes = [ - "h1:+bZPRgjpUA6LivvMIS1UdwRWUgzoYBp/nhEpbL4aXHM=", - "h1:D5lngW1uKlPM2EUCdNG1f2FvPGHYRklDFN8b2jPCIpM=", - "h1:nTP2ZYfuEpMP+PkkgRdhQphNmWWJuKdE9Z4TzeC7ydo=", - "h1:sqVZftg9rJGDiiPiY9l1V/a+5CWkxNcj22sBu8HsJBY=", - "h1:swoRk2drVrD8v7GrW/2OJSk06v2I2zGk3XPAgBDbw9A=", - "zh:04292e149676ba956d738e85faeb6d6ebd3759e8310f1c4155e67402eb5ae0f7", - "zh:0963b4528f25d01d5c733e17de31e2c0b94790fd02931b2a47cd051b20dd0d96", - "zh:133563e16e8a4a7139ac11d94e68de8d1d5e3a62a532e64ac936735d7b1e04db", - "zh:2b219f1b40881d3bdd89257c916f255a7e36904ddc65dbbafee80763661b4636", - "zh:4b4e11a4e3716b290b3b173dfd15b06814b2f6f148f663e3c67a677c95526339", - "zh:5607c7bff3019c3b31488be1a8a9d77a96d27b199a1d8b789e4c2d4c90805674", - "zh:6469aef7728947dacb47785e6082d2d95ebd336a8798f3be6cece5a13145108c", - "zh:69e563f4e6397e1ebaef6f554d296238ec1d9dadc4b865c36743bd8366a888da", - "zh:887a223b7a9ec4e66634dbb65d9dcc53f0be06d058d9a209927ad49702ae790c", - "zh:b03c273367885c5489a24c31859af81ea58cb169431c0da97a175945ec968f53", - "zh:dd7b704ceaf98ce591e111a9c5085465c946f4f8f357089c0e27e990a669ba39", + "h1:K2OLOYxwF/onOegr+Y6Sfu/DjEjDLobQBBrLBF3i9TI=", + "h1:cwtEEnEESVOgcxtXGz0A2wXCiNZIzm3dC2xHmYuxg9M=", + "h1:dKXFrVrjv579ax6iX4wc6lmEAVFsr3iTDjErnPHIjH4=", + "h1:iqN6KxIOGYv0N1p5xfNTgsjvDHpE3bZM8s5vIAEgfnQ=", + "h1:qDmSr5+vMVdWmfBEaIwqSLo5ZLyYk7KYoJo5flny6lk=", + "zh:3f332bca3a8b7dc982e428e09c73862d1afda34c2ad7803e70d8ba7b9e2445fd", + "zh:66b7e4a7a4fd06e0a5a3a22b4f76bda48e50ed3dd26c388738d9cc882b801bce", + "zh:6a271175d6e079241f24129f5026e0b16f04e7a548807f115600003d615e0ec3", + "zh:7a6abc7e2ae8d1041d0446bbe87156e0436639676ee1fad40321e8ee6759a454", + "zh:903f6e7f03e5952347ce6ee589d58c829179f2f22220f25cf52ae4efecd7053c", + "zh:a572b9834cf3b51799c82c5009705c59309d947a6ecdb7e17729868c55e7d0e0", + "zh:a7fca14338f0cfb82b17ce085400c210cbc986a87086702e3a11efcb4e53d6e4", + "zh:af36c7004702b0a273794914a17a77af1eb972caaad64e0068739e55c1488845", + "zh:b36f308db1cdc02dee659e3e518186d7dec970d88b6149be3f6b3f8d544e4282", + "zh:bedf6d13cf4bccc128d8cbb0703a3a8b547629674439ffda5e73563ab775d0f7", + "zh:d1df286a2e5d4a5f6a7f4d29700a25588167ccffa31c686550ef617503df3254", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.6.0" - constraints = "3.6.0" + version = "3.6.2" + constraints = "3.6.2" hashes = [ - "h1:5KeoKSVKVHJW308uiTgslxFbjQAdWzBGUFK68vgMRWY=", - "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", - "h1:R5Ucn26riKIEijcsiOMBR3uOAjuOMfI1x7XvH4P6B1w=", - "h1:p6WG1IPHnqx1fnJVKNjv733FBaArIugqy58HRZnpPCk=", - "h1:t0mRdJzegohRKhfdoQEJnv3JRISSezJRblN0HIe67vo=", - "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", - "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", - "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", - "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", - "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", + "h1:5lstwe/L8AZS/CP0lil2nPvmbbjAu8kCaU/ogSGNbxk=", + "h1:Gd3WitYIzSYo/Suo+PMxpZpIGpRPrwl0JU0+DhxycFM=", + "h1:J9EOvuE7qCS/S0lqMX6DNqsh/wq2uhwxE2bOpSn0/hc=", + "h1:R5qdQjKzOU16TziCN1vR3Exr/B+8WGK80glLTT4ZCPk=", + "h1:UQlmHGddu39vVzG8kruMsde4GHlG+1S7OLqFApbJvtc=", + "h1:VYBb5/CQ1tPhV92eUsfxSZ4Ta2OCfNggYwE+Qo+yCD0=", + "h1:VavG5unYCa3SYISMKF9pzc3718M0bhPlcbUZZGl7wuo=", + "h1:jke+2u84Hrc7szJKevP1BKFn1o3pfxYhYtity2RPCS8=", + "h1:m/7/S7a6RzGgeRAJJCsDza2kbaNmFpQDDd849RxD2FE=", + "h1:uOP0uuF8PKF98YlLqgtjdHBELJLI4BMOOHYXQMYhdlI=", + "h1:wmG0QFjQ2OfyPy6BB7mQ57WtoZZGGV07uAPQeDmIrAE=", + "zh:0ef01a4f81147b32c1bea3429974d4d104bbc4be2ba3cfa667031a8183ef88ec", + "zh:1bcd2d8161e89e39886119965ef0f37fcce2da9c1aca34263dd3002ba05fcb53", + "zh:37c75d15e9514556a5f4ed02e1548aaa95c0ecd6ff9af1119ac905144c70c114", + "zh:4210550a767226976bc7e57d988b9ce48f4411fa8a60cd74a6b246baf7589dad", + "zh:562007382520cd4baa7320f35e1370ffe84e46ed4e2071fdc7e4b1a9b1f8ae9b", + "zh:5efb9da90f665e43f22c2e13e0ce48e86cae2d960aaf1abf721b497f32025916", + "zh:6f71257a6b1218d02a573fc9bff0657410404fb2ef23bc66ae8cd968f98d5ff6", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", - "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", - "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", - "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", - "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", - "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", + "zh:9647e18f221380a85f2f0ab387c68fdafd58af6193a932417299cdcae4710150", + "zh:bb6297ce412c3c2fa9fec726114e5e0508dd2638cad6a0cb433194930c97a544", + "zh:f83e925ed73ff8a5ef6e3608ad9225baa5376446349572c2449c0c0b3cf184b7", + "zh:fbef0781cb64de76b1df1ca11078aecba7800d82fd4a956302734999cfd9a4af", ] } diff --git a/dev-docs/howto/vpn/on-prem-terraform/main.tf b/dev-docs/howto/vpn/on-prem-terraform/main.tf index 365407d74..0ba91742b 100644 --- a/dev-docs/howto/vpn/on-prem-terraform/main.tf +++ b/dev-docs/howto/vpn/on-prem-terraform/main.tf @@ -2,17 +2,21 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.92.0" + version = "4.1.0" } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } } } provider "azurerm" { features {} + subscription_id = var.subscription_id + # This enables all resource providers. + # In the future, we might want to use `resource_providers_to_register` to registers just the ones we need. + resource_provider_registrations = "all" } locals { @@ -103,7 +107,7 @@ resource "azurerm_route_table" "route_table" { name = "vpn-routes" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name - disable_bgp_route_propagation = false + bgp_route_propagation_enabled = false dynamic "route" { for_each = var.remote_ts diff --git a/dev-docs/howto/vpn/on-prem-terraform/variables.tf b/dev-docs/howto/vpn/on-prem-terraform/variables.tf index 652916678..86d74ea18 100644 --- a/dev-docs/howto/vpn/on-prem-terraform/variables.tf +++ b/dev-docs/howto/vpn/on-prem-terraform/variables.tf @@ -1,3 +1,9 @@ +variable "subscription_id" { + type = string + description = "Azure subscription ID. This can also be sourced from the ARM_SUBSCRIPTION_ID environment variable: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs#subscription_id" + default = "" +} + variable "resource_group_location" { type = string default = "westeurope" diff --git a/dev-docs/miniconstellation/azure-terraform/.terraform.lock.hcl b/dev-docs/miniconstellation/azure-terraform/.terraform.lock.hcl index b29acb322..842851385 100644 --- a/dev-docs/miniconstellation/azure-terraform/.terraform.lock.hcl +++ b/dev-docs/miniconstellation/azure-terraform/.terraform.lock.hcl @@ -2,74 +2,86 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "3.92.0" - constraints = "3.92.0" + version = "4.1.0" + constraints = "4.1.0" hashes = [ - "h1:+bZPRgjpUA6LivvMIS1UdwRWUgzoYBp/nhEpbL4aXHM=", - "h1:D5lngW1uKlPM2EUCdNG1f2FvPGHYRklDFN8b2jPCIpM=", - "h1:nTP2ZYfuEpMP+PkkgRdhQphNmWWJuKdE9Z4TzeC7ydo=", - "h1:sqVZftg9rJGDiiPiY9l1V/a+5CWkxNcj22sBu8HsJBY=", - "h1:swoRk2drVrD8v7GrW/2OJSk06v2I2zGk3XPAgBDbw9A=", - "zh:04292e149676ba956d738e85faeb6d6ebd3759e8310f1c4155e67402eb5ae0f7", - "zh:0963b4528f25d01d5c733e17de31e2c0b94790fd02931b2a47cd051b20dd0d96", - "zh:133563e16e8a4a7139ac11d94e68de8d1d5e3a62a532e64ac936735d7b1e04db", - "zh:2b219f1b40881d3bdd89257c916f255a7e36904ddc65dbbafee80763661b4636", - "zh:4b4e11a4e3716b290b3b173dfd15b06814b2f6f148f663e3c67a677c95526339", - "zh:5607c7bff3019c3b31488be1a8a9d77a96d27b199a1d8b789e4c2d4c90805674", - "zh:6469aef7728947dacb47785e6082d2d95ebd336a8798f3be6cece5a13145108c", - "zh:69e563f4e6397e1ebaef6f554d296238ec1d9dadc4b865c36743bd8366a888da", - "zh:887a223b7a9ec4e66634dbb65d9dcc53f0be06d058d9a209927ad49702ae790c", - "zh:b03c273367885c5489a24c31859af81ea58cb169431c0da97a175945ec968f53", - "zh:dd7b704ceaf98ce591e111a9c5085465c946f4f8f357089c0e27e990a669ba39", + "h1:K2OLOYxwF/onOegr+Y6Sfu/DjEjDLobQBBrLBF3i9TI=", + "h1:cwtEEnEESVOgcxtXGz0A2wXCiNZIzm3dC2xHmYuxg9M=", + "h1:dKXFrVrjv579ax6iX4wc6lmEAVFsr3iTDjErnPHIjH4=", + "h1:iqN6KxIOGYv0N1p5xfNTgsjvDHpE3bZM8s5vIAEgfnQ=", + "h1:qDmSr5+vMVdWmfBEaIwqSLo5ZLyYk7KYoJo5flny6lk=", + "zh:3f332bca3a8b7dc982e428e09c73862d1afda34c2ad7803e70d8ba7b9e2445fd", + "zh:66b7e4a7a4fd06e0a5a3a22b4f76bda48e50ed3dd26c388738d9cc882b801bce", + "zh:6a271175d6e079241f24129f5026e0b16f04e7a548807f115600003d615e0ec3", + "zh:7a6abc7e2ae8d1041d0446bbe87156e0436639676ee1fad40321e8ee6759a454", + "zh:903f6e7f03e5952347ce6ee589d58c829179f2f22220f25cf52ae4efecd7053c", + "zh:a572b9834cf3b51799c82c5009705c59309d947a6ecdb7e17729868c55e7d0e0", + "zh:a7fca14338f0cfb82b17ce085400c210cbc986a87086702e3a11efcb4e53d6e4", + "zh:af36c7004702b0a273794914a17a77af1eb972caaad64e0068739e55c1488845", + "zh:b36f308db1cdc02dee659e3e518186d7dec970d88b6149be3f6b3f8d544e4282", + "zh:bedf6d13cf4bccc128d8cbb0703a3a8b547629674439ffda5e73563ab775d0f7", + "zh:d1df286a2e5d4a5f6a7f4d29700a25588167ccffa31c686550ef617503df3254", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/cloudinit" { - version = "2.3.3" - constraints = "2.3.3" + version = "2.3.4" + constraints = "2.3.4" hashes = [ - "h1:6utKe3l0lf4+hw+uVK8XJVNdOmp7tOTcycyFvv1pGAA=", - "h1:GmJ8PxLjjPr+lh02Bw3u7RYqA3UtpE2hQ1T43Vt7PTQ=", - "h1:TCZQjXesJ9qbOZaHjJse/WyOxYQwp7wUX3VNxL/qo1c=", - "h1:U6EC4/cJJ6Df3LztUQ/I4YuljGQQeQ+LdLndAwSSiTs=", - "h1:ZmQ97fIcPW7hj/vynRB4zbtObK0Z/LVJPvCwlNd78zA=", - "zh:0bd6ee14ca5cf0f0c83d3bb965346b1225ccd06a6247e80774aaaf54c729daa7", - "zh:3055ad0dcc98de1d4e45b72c5889ae91b62f4ae4e54dbc56c4821be0fdfbed91", - "zh:32764cfcff0d7379ca8b7dde376ac5551854d454c5881945f1952b785a312fa2", - "zh:55c2a4dc3ebdeaa1dec3a36db96dab253c7fa10b9fe1209862e1ee77a01e0aa1", - "zh:5c71f260ba5674d656d12f67cde3bb494498e6b6b6e66945ef85688f185dcf63", + "h1:+J2rgfJH5B0vyFR0Wfcoyt4SHWfZLDe+WtUMtmZLDeY=", + "h1:/Ty/HXg0Bti5T+Zk6XvhwEHyKGiOV5LzCrbLiekjuLU=", + "h1:S3j8poSaLbaftlKq2STBkQEkZH253ZLaHhBHBifdpBQ=", + "h1:TSeGg71hzb+ahU16viRNFxDVgpC3krXqK9Lm4dg9v3Y=", + "h1:ZJGY2ywdCKnbMMAlyAv0n5cwVpHaicKVheNYbdCkZTw=", + "h1:cVIIhnXweOHavu1uV2bdKScTjLbM1WnKM/25wqYBJWo=", + "h1:iDq03pOzp/UsXya2h+32VOOrvGdJgI9L2/EZJoN9t4A=", + "h1:jTcgflH266LJFwqejIEHndaLn+TwrrYqim3rQmw15qI=", + "h1:mPi6Snl6LCYgO2tMxEs+YMuKw+YQ1MJ3E+uf+f/74yA=", + "h1:pb1C8Lrfp4VnPRm6Uo+jEWbKvqsGunHxDO7pWtc/yRI=", + "h1:qsx0lvgUWVL7D2EvWAuO+WyOO/fVneGD8FG2REcNVhI=", + "zh:09f1f1e1d232da96fbf9513b0fb5263bc2fe9bee85697aa15d40bb93835efbeb", + "zh:381e74b90d7a038c3a8dcdcc2ce8c72d6b86da9f208a27f4b98cabe1a1032773", + "zh:398eb321949e28c4c5f7c52e9b1f922a10d0b2b073b7db04cb69318d24ffc5a9", + "zh:4a425679614a8f0fe440845828794e609b35af17db59134c4f9e56d61e979813", + "zh:4d955d8608ece4984c9f1dacda2a59fdb4ea6b0243872f049b388181aab8c80a", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:9617280a853ec7caedb8beb7864e4b29faf9c850a453283980c28fccef2c493d", - "zh:ac8bda21950f8dddade3e9bc15f7bcfdee743738483be5724169943cafa611f5", - "zh:ba9ab567bbe63dee9197a763b3104ea9217ba27449ed54d3afa6657f412e3496", - "zh:effd1a7e34bae3879c02f03ed3afa979433a518e11de1f8afd35a8710231ac14", - "zh:f021538c86d0ac250d75e59efde6d869bbfff711eb744c8bddce79d2475bf46d", - "zh:f1e3984597948a2103391a26600e177b19f16a5a4c66acee27a4343fb141571f", + "zh:a48fbee1d58d55a1f4c92c2f38c83a37c8b2f2701ed1a3c926cefb0801fa446a", + "zh:b748fe6631b16a1dafd35a09377c3bffa89552af584cf95f47568b6cd31fc241", + "zh:d4b931f7a54603fa4692a2ec6e498b95464babd2be072bed5c7c2e140a280d99", + "zh:f1c9337fcfe3a7be39d179eb7986c22a979cfb2c587c05f1b3b83064f41785c5", + "zh:f58fc57edd1ee3250a28943cd84de3e4b744cdb52df0356a53403fc240240636", + "zh:f5f50de0923ff530b03e1bca0ac697534d61bb3e5fc7f60e13becb62229097a9", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.6.0" - constraints = "3.6.0" + version = "3.6.2" + constraints = "3.6.2" hashes = [ - "h1:5KeoKSVKVHJW308uiTgslxFbjQAdWzBGUFK68vgMRWY=", - "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", - "h1:R5Ucn26riKIEijcsiOMBR3uOAjuOMfI1x7XvH4P6B1w=", - "h1:p6WG1IPHnqx1fnJVKNjv733FBaArIugqy58HRZnpPCk=", - "h1:t0mRdJzegohRKhfdoQEJnv3JRISSezJRblN0HIe67vo=", - "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", - "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", - "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", - "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", - "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", + "h1:5lstwe/L8AZS/CP0lil2nPvmbbjAu8kCaU/ogSGNbxk=", + "h1:Gd3WitYIzSYo/Suo+PMxpZpIGpRPrwl0JU0+DhxycFM=", + "h1:J9EOvuE7qCS/S0lqMX6DNqsh/wq2uhwxE2bOpSn0/hc=", + "h1:R5qdQjKzOU16TziCN1vR3Exr/B+8WGK80glLTT4ZCPk=", + "h1:UQlmHGddu39vVzG8kruMsde4GHlG+1S7OLqFApbJvtc=", + "h1:VYBb5/CQ1tPhV92eUsfxSZ4Ta2OCfNggYwE+Qo+yCD0=", + "h1:VavG5unYCa3SYISMKF9pzc3718M0bhPlcbUZZGl7wuo=", + "h1:jke+2u84Hrc7szJKevP1BKFn1o3pfxYhYtity2RPCS8=", + "h1:m/7/S7a6RzGgeRAJJCsDza2kbaNmFpQDDd849RxD2FE=", + "h1:uOP0uuF8PKF98YlLqgtjdHBELJLI4BMOOHYXQMYhdlI=", + "h1:wmG0QFjQ2OfyPy6BB7mQ57WtoZZGGV07uAPQeDmIrAE=", + "zh:0ef01a4f81147b32c1bea3429974d4d104bbc4be2ba3cfa667031a8183ef88ec", + "zh:1bcd2d8161e89e39886119965ef0f37fcce2da9c1aca34263dd3002ba05fcb53", + "zh:37c75d15e9514556a5f4ed02e1548aaa95c0ecd6ff9af1119ac905144c70c114", + "zh:4210550a767226976bc7e57d988b9ce48f4411fa8a60cd74a6b246baf7589dad", + "zh:562007382520cd4baa7320f35e1370ffe84e46ed4e2071fdc7e4b1a9b1f8ae9b", + "zh:5efb9da90f665e43f22c2e13e0ce48e86cae2d960aaf1abf721b497f32025916", + "zh:6f71257a6b1218d02a573fc9bff0657410404fb2ef23bc66ae8cd968f98d5ff6", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", - "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", - "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", - "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", - "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", - "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", + "zh:9647e18f221380a85f2f0ab387c68fdafd58af6193a932417299cdcae4710150", + "zh:bb6297ce412c3c2fa9fec726114e5e0508dd2638cad6a0cb433194930c97a544", + "zh:f83e925ed73ff8a5ef6e3608ad9225baa5376446349572c2449c0c0b3cf184b7", + "zh:fbef0781cb64de76b1df1ca11078aecba7800d82fd4a956302734999cfd9a4af", ] } diff --git a/dev-docs/miniconstellation/azure-terraform/main.tf b/dev-docs/miniconstellation/azure-terraform/main.tf index bc27ec01b..c67b662c2 100644 --- a/dev-docs/miniconstellation/azure-terraform/main.tf +++ b/dev-docs/miniconstellation/azure-terraform/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.92.0" + version = "4.1.0" } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } tls = { source = "hashicorp/tls" @@ -14,7 +14,7 @@ terraform { } cloudinit = { source = "hashicorp/cloudinit" - version = "2.3.3" + version = "2.3.4" } } } @@ -22,6 +22,9 @@ terraform { provider "azurerm" { use_oidc = true features {} + # This enables all resource providers. + # In the future, we might want to use `resource_providers_to_register` to registers just the ones we need. + resource_provider_registrations = "all" } provider "tls" {} diff --git a/dev-docs/security-overview.md b/dev-docs/security-overview.md new file mode 100644 index 000000000..a2b03ab0e --- /dev/null +++ b/dev-docs/security-overview.md @@ -0,0 +1,236 @@ +# Constellation - Security Protocols Overview + +The security of Constellation is based on a set of protocols. +The protocols are outlined in the following. +The following diagram sketches the basic trust relationships between the entities in a Constellation cluster. +![chain of trust](chain-of-trust.jpg) + +## Software components + +Abstractly, the Constellation software comprises three core components: +1. The command-line interface (CLI) executable, which is run by the cluster administrator on their local machine. +2. The node images, which are run inside Confidential VMs (CVMs). +Among other, each node image contains a Linux kernel and a user mode program called Bootstrapper. +3. The Constellation service containers, which are run on Kubernetes. +There are three core services: KeyService, JoinService, and VerificationService. + +## CLI: root of trust +The CLI executable is signed by Edgeless Systems. +To ensure non-repudiability for CLI releases, Edgeless Systems publishes corresponding signatures to the public ledger of the [Sigstore project](https://www.sigstore.dev/). +There's a [step-by-step guide](https://docs.edgeless.systems/constellation/workflows/verify-cli) on how to verify CLI signatures based on Sigstore. + +The CLI contains the [measurements](https://github.com/edgelesssys/constellation/blob/edc0c7068ef4527efeaf584a2a35e0f51f58c426/internal/attestation/measurements/measurements_enterprise.go#L21) of the latest Constellation node image for all supported cloud platforms. +The CLI writes these measurements as part of the *attestation config* to a cluster's config file with the ["config generate" command](https://docs.edgeless.systems/constellation/workflows/config). +Note that Constellation currently uses 16 TPM-based runtime measurements for each cloud platform. +The purpose and source of the measurements are described in the [next section](#remote-attestation-of-nodes). +In addition to the measurements, the attestation config contains expected patch levels for the CPU microcode and the X.509 certificate of the CPU vendor's remote attestation infrastructure. +An example of an attestation config is given [below](#attestation-config). + +In case a different version of the node image is to be used, the corresponding measurements can be fetched using the CLI's ["config fetch-measurements" command](https://docs.edgeless.systems/constellation/reference/cli#constellation-config-fetch-measurements). +This command downloads the measurements and the corresponding signature from Edgeless Systems from https://cdn.confidential.cloud. +See for example the following files corresponding to node image v2.16.3: +* [Measurements](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json) +* [Signature](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json.sig) + +In addition to the attestation config, the CLI contains the following data in hardcoded form: +* The [long-term public key of Edgeless Systems](https://github.com/edgelesssys/constellation/blob/edc0c7068ef4527efeaf584a2a35e0f51f58c426/internal/constants/constants.go#L264) to verify the signature of downloaded measurements. +* The [hashes of the expected Kubernetes binaries](https://github.com/edgelesssys/constellation/blob/edc0c7068ef4527efeaf584a2a35e0f51f58c426/internal/versions/versions.go#L199). +* The [Helm charts used for the installation of services](https://github.com/edgelesssys/constellation/tree/main/internal/constellation/helm/charts), which include hashes of the respective containers. +Note that the Helm charts and the hashes are [generated at build time](https://github.com/edgelesssys/constellation/blob/main/internal/constellation/helm/imageversion/imageversion.go). +A future version of the CLI will provide a command to print the Helm charts. + +## Cluster creation + +When a cluster is [created](https://docs.edgeless.systems/constellation/workflows/create), the CLI interacts with the API of the respective infrastructure provider, for example Azure, and launches CVMs with the applicable node image. +These CVMs are called *nodes*. +On each node, the Bootstrapper is launched. + +The CLI automatically selects one of the nodes as *first node*. +The CLI automatically verifies the first node's remote-attestation statement using the attestation config. +Details on remote attestation are given in the [next section](#remote-attestation-of-nodes). + +Based on the remote-attestation statement, the CLI and the Bootstrapper running on the first node set up a temporary TLS connection between them. +We refer to this type of connection as "attested TLS" (aTLS). +This connection is mainly used for three things (see the the [interface definition](https://github.com/edgelesssys/constellation/blob/main/bootstrapper/initproto/init.proto) for a comprehensive list of exchanged data): +1. The CLI sends the hashes of the expected Kubernetes binaries to the first node. +2. The CLI generates the [master secret](https://docs.edgeless.systems/constellation/architecture/keys#master-secret) of the to-be-created cluster and sends it to the first node. +3. The first node generates a [kubeconfig file](https://www.redhat.com/sysadmin/kubeconfig) and sends it to the CLI. +The kubeconfig file contains Kubernetes credentials for the CLI and the Kubernetes cluster's public key, among others. + +After this, the aTLS connection is closed and the Bootstrapper marks the node irrevocably as "initialized". +This mechanism prevents a node from accidentally or maliciously joining different clusters. +On all supported CVM platforms this is currently implemented by *extending* TPM register 15 with the unique ID of the cluster (`clusterID`). +More information can be found in the [Constellation documentation](https://docs.edgeless.systems/constellation/architecture/keys#cluster-identity). + +For [launch digest-based attestation](#remote-attestation-of-nodes) on future CVM platforms, an alternative would be to extend `clusterID` to the so called RTMR registers of Intel TDX. +TDX provides four RTMRs, which are automatically included in the `auxiliary data` part of a remote-attestation statement. +For AMD SEV-SNP, a different solution exists. + +## Remote attestation of nodes + +To identify themselves, nodes use the remote-attestation functionality of the underlying CVM platform. +Constellation supports Intel TDX and AMD SEV-SNP based platforms. +Abstractly, Intel TDX and AMD SEV-SNP hash the initial memory contents of the CVMs. +This hash is also called `launch digest`. +The launch digest is reflected in each remote-attestation statement that is requested by the software inside the CVM. +Abstractly, a remote-attestation statement `R` from a CVM looks as follows: + +``` +R = Sig-CPU(, , ) +``` + +The `payload` is controlled by the software running inside the CVM. +In the case of a Constellation node, the `payload` is always the public key of the respective Bootstrapper running inside the CVM. +Thus, `R` can be seen as a certificate for that public key issued by the CPU. +Based on this, nodes establish attested TLS (aTLS) connections. +aTLS is used during [cluster creation](#cluster-creation) and when [growing a cluster](#cluster-growth). + +### Measurements + +In the ideal case, the underlying CVM platform does not inject any of its own software into a CVM. +In that case, a Constellation node image can contain its own firmware/UEFI. +This allows for the creation of node images for which the launch digest covers all defining parts of a node, including the firmware, the kernel, the kernel command line, and the disk image. +In this case, the launch digest is the only measurement that's required to verify the identity and integrity of a node. + +### Measured Boot as fallback + +However, currently, all supported CVM platforms (AWS, Azure, and GCP) inject custom firmware into CVMs. +Thus, in practice, Constellation relies on conventional [measured boot](https://docs.edgeless.systems/constellation/architecture/images#measured-boot) to reflect the identity and integrity of nodes. + +In measured boot, in general, the software components involved in the boot process of a system are "measured" into the 16 registers of a Trusted Platform Module (TPM). +The values of these registers are also called "runtime measurements". +All supported CVM platforms provide TPMs to CVMs. +Constellation nodes use these to measure their boot process. +They include the 16 runtime measurements as `auxiliary data` in `R`. +On each CVM platform, runtime measurements are taken differently. +Details on this are given in the [Constellation documentation](https://docs.edgeless.systems/constellation/architecture/attestation#runtime-measurements). + +With measured boot, Constellation only checks the 16 runtime measurements during the verification of a node's remote-attestation statement. +The launch digest is not considered, because it only covers the firmware injected by the CVM platform and may change whenever the CVM platform is updated. +Currently, on AWS and GCP the TPM implementation resides outside the CVM. +On Azure, the TPM implementation is part of the injected firmware and resides inside the CVM. +More information can be found in the [Constellation documentation](https://docs.edgeless.systems/constellation/overview/clouds). + +## Kubernetes bootstrapping on the first node + +The Bootstrapper on the first node downloads and verifies the Kubernetes binaries, using the hashes it received from the CLI. +These binaries include for example [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/), [kube-apiserver](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/), and [etcd](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/). +With these, the Bootstrapper creates a single-node Kubernetes cluster. +Etcd is a distributed key-value store that Kubernetes uses to store configuration data for services. +The etcd agent runs on each control-plane node of a cluster. +The agents use mTLS for communication between them. +Etcd uses the Raft protocol (over mTLS) to distribute state between nodes. +All essential configuration data of a cluster is kept in etcd. + +Initially, the Bootstrapper on the first node [writes](https://github.com/edgelesssys/constellation/blob/d65987cb15cf9ebdbbd2975f177937c1acbc90f8/bootstrapper/internal/kubernetes/kubernetes.go#L173) the hashes of the expected Kubernetes binaries to a specific key in etcd. + +Next, the CLI the connects to the Kubernetes API server (kube-apiserver) using the kubeconfig file it received from the Bootstrapper. +This results in an mTLS connection between the CLI and the Kubernetes API server. +The CLI uses this connection for two essential operations at the Kubernetes level: + +1. It writes the attestation config to a specific key in etcd. +1. It executes the [hardcoded Helm charts](#cli-root-of-trust), which, most notably, install the three core services KeyService, JoinService, and VerificationService, the [constellation-node-operator](https://github.com/edgelesssys/constellation/tree/main/operators/constellation-node-operator), and a small number of standard services like Cilium and cert-manager. + +The latter causes the first node to download, verify, and run the containers defined in the Helm charts. +The containers that are specific to Constellation are hosted at `ghcr.io/edgelesssys`. + +After this, the Constellation cluster is operational on the first node. + +## Cluster growth + +Additional nodes can now join the cluster - either as control-plane nodes or as worker nodes. +For both, the process for joining the cluster is identical. +First, the Bootstrapper running on a *new node* contacts the JoinService of the existing cluster. +The JoinService verifies the remote-attestation statement of the new node using the attestation config stored in etcd. +On success, an aTLS connection between the two is created, which is used mainly for the following (see the the [interface definition](https://github.com/edgelesssys/constellation/blob/main/joinservice/joinproto/join.proto) for a comprehensive list of exchanged data): + +1. The new node sends a certificate signing request (CSR) for its *node certificate* to the JoinService. +1. The JoinService issues a corresponding certificate with a lifetime of one year and sends it to the new node. +The JoinService uses the signing key of the Kubernetes cluster for this, which is [generated by kubeadm](https://kubernetes.io/docs/setup/best-practices/certificates/). Note that the lifetime of the node certificate is a best practice only, as Constellation relies on the untrusted infrastructure to provide time when validating certificates. +1. The JoinService sends a [kubeadm token](https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-token/) to the new node. +1. The JoinService sends the hashes of the expected Kubernetes binaries to the new node. +1. The JoinService sends encryption key for the new node's local storage. +This key is generated and managed by the cluster's KeyService. +1. The JoinService sends the certificate of the cluster's control plane to the new node. + +After this, the aTLS connection is closed and the node is marked as "initialized" in the same way as described [above](#cluster-creation). + +The Bootstrapper downloads, verifies, and runs the given Kubernetes binaries. +Further, the Bootstrapper uses the kubeadm token to download the configuration of the cluster from the Kubernetes API server. +The kubeadm token is never used after this. + +The kubelet on the new node uses its own node certificate and the certificate of the cluster's control plane (which the new node both received from the JoinService) to establish an mTLS connection with the cluster's Kubernetes API server. +Once connected, the new node registers itself as control-plane node or worker node of the cluster. +This process uses the standard Kubernetes mechanisms for adding nodes. + +In Constellation, a virtual private network (VPN) exists between all nodes of a cluster. +This VPN is created with the help of Cilium. +To join this VPN, the new node generates WireGuard credentials for itself and writes the public key to etcd via the mTLS connection with the Kubernetes API server. +It also downloads the public keys of existing nodes from etcd. +Subsequently, the Cilium agents running on other nodes fetch the new node's public key from etcd as well. + +Note that etcd communication between nodes is an exception: This traffic always goes via mTLS based on node certificates. + +## Cluster upgrade + +Whenever a cluster is [upgraded](https://docs.edgeless.systems/constellation/workflows/upgrade), the CLI connects to the Kubernetes API server and, essentially, updates the following data in etcd: + +1. The attestation config +1. The hashes of the expected Kubernetes binaries + +Further, the CLI applies updated Helm charts to update the cluster's services. +Again, these Helm charts are hardcoded in the CLI. +See the [implementation](https://github.com/edgelesssys/constellation/blob/d65987cb15cf9ebdbbd2975f177937c1acbc90f8/cli/internal/cmd/apply.go#L358) of the `apply()` function for a sequence diagram of all steps. +Subsequently, the constellation-node-operator replaces existing nodes with new ones. +New nodes go through the [usual process for joining the cluster](#cluster-growth). + +## Examples + +This section gives real life examples of key data structures and the corresponding commands to retrieve those. + +### Attestation config + +```bash +kubectl -n kube-system get cm join-config -o json +``` +```json +{ + "apiVersion": "v1", + "binaryData": { + "measurementSalt": "2A4Fzfdr/61XbJvk1PDqzh0R4rVnEujyXudsfgRZzUY=" + }, + "data": { + "attestationConfig": "{\"measurements\":{\"1\":{\"expected\":\"3695dcc55e3aa34027c27793c85c723c697d708c42d1f73bd6fa4f26608a5b24\",\"warnOnly\":true},\"11\":{\"expected\":\"f09cef0d077127fb26bc8d013fc09e13afbb70f0f734ced98f46666544998efe\",\"warnOnly\":true},\"12\":{\"expected\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"warnOnly\":true},\"13\":{\"expected\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"warnOnly\":true},\"14\":{\"expected\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"warnOnly\":true},\"15\":{\"expected\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"warnOnly\":true},\"2\":{\"expected\":\"3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\",\"warnOnly\":true},\"3\":{\"expected\":\"3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\",\"warnOnly\":true},\"4\":{\"expected\":\"e5020193148fbad0dbaf618fb3ef15665c72ff87a54e24b2d8f5bdf9719bb50b\",\"warnOnly\":true},\"6\":{\"expected\":\"3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\",\"warnOnly\":true},\"8\":{\"expected\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"warnOnly\":true},\"9\":{\"expected\":\"37ef16fd0ae8d2fb3b1914f0b8ff046e765b57fec6739d2ebf1fd4d182071437\",\"warnOnly\":true}},\"bootloaderVersion\":\"latest\",\"teeVersion\":\"latest\",\"snpVersion\":\"latest\",\"microcodeVersion\":\"latest\",\"amdRootKey\":\"-----BEGIN CERTIFICATE-----\\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\\nAFZEAwoKCQ==\\n-----END CERTIFICATE-----\\n\",\"amdSigningKey\":\"\"}" + }, + "kind": "ConfigMap", + "metadata": { + "creationTimestamp": "2024-09-25T11:11:50Z", + "name": "join-config", + "namespace": "kube-system", + "resourceVersion": "387", + "uid": "fdd0d5eb-cf58-4608-99c9-eede08895615" + } +} +``` +### Hashes of Kubernetes binaries +```bash +kubectl -n kube-system get cm k8s-components-sha256-7b73c7675df78e5753b6e0fc86a9982127fd16141837599d5ce16df6bfe6a2a0 -o json +``` +```json +{ + "apiVersion": "v1", + "data": { + "cluster-version": "v1.29.8", + "components": "[{\"url\":\"https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz\",\"hash\":\"sha256:c2485ddb3ffc176578ae30ae58137f0b88e50f7c7f2af7d53a569276b2949a33\",\"install_path\":\"/opt/cni/bin\",\"extract\":true},{\"url\":\"https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.29.0/crictl-v1.29.0-linux-amd64.tar.gz\",\"hash\":\"sha256:d16a1ffb3938f5a19d5c8f45d363bd091ef89c0bc4d44ad16b933eede32fdcbb\",\"install_path\":\"/run/state/bin\",\"extract\":true},{\"url\":\"https://storage.googleapis.com/kubernetes-release/release/v1.29.8/bin/linux/amd64/kubelet\",\"hash\":\"sha256:df6e130928403af8b4f49f1197e26f2873a147cd0e23aa6597a26c982c652ae0\",\"install_path\":\"/run/state/bin/kubelet\"},{\"url\":\"https://storage.googleapis.com/kubernetes-release/release/v1.29.8/bin/linux/amd64/kubeadm\",\"hash\":\"sha256:fe054355e0ae8dc35d868a3d3bc408ccdff0969c20bf7a231ae9b71484e41be3\",\"install_path\":\"/run/state/bin/kubeadm\"},{\"url\":\"https://storage.googleapis.com/kubernetes-release/release/v1.29.8/bin/linux/amd64/kubectl\",\"hash\":\"sha256:038454e0d79748aab41668f44ca6e4ac8affd1895a94f592b9739a0ae2a5f06a\",\"install_path\":\"/run/state/bin/kubectl\"},{\"url\":\"data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtYXBpc2VydmVyOnYxLjI5LjhAc2hhMjU2OjZmNzJmYTkyNmM5YjA1ZTEwNjI5ZmUxYTA5MmZkMjhkY2Q2NWI0ZmRmZDBjYzdiZDU1Zjg1YTU3YTZiYTFmYTUifV0=\",\"install_path\":\"/opt/kubernetes/patches/kube-apiserver+json.json\"},{\"url\":\"data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtY29udHJvbGxlci1tYW5hZ2VyOnYxLjI5LjhAc2hhMjU2OjZmMjdkNjNkZWQyMDYxNGM2ODU1NGI0NzdjZDdhNzhlZGE3OGE0OThhOTJiZmU4OTM1Y2Y5NjRjYTViNzRkMGIifV0=\",\"install_path\":\"/opt/kubernetes/patches/kube-controller-manager+json.json\"},{\"url\":\"data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtc2NoZWR1bGVyOnYxLjI5LjhAc2hhMjU2OmRhNzRhNjY2NzVkOTVlMzllYzI1ZGE1ZTcwNzI5ZGE3NDZkMGZhMGIxNWVlMGRhODcyYWM5ODA1MTliYzI4YmQifV0=\",\"install_path\":\"/opt/kubernetes/patches/kube-scheduler+json.json\"},{\"url\":\"data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2V0Y2Q6My41LjEyLTBAc2hhMjU2OjQ0YThlMjRkY2JiYTM0NzBlZTFmZWUyMWQ1ZTg4ZDEyOGM5MzZlOWI1NWQ0YmM1MWZiZWY4MDg2ZjhlZDEyM2IifV0=\",\"install_path\":\"/opt/kubernetes/patches/etcd+json.json\"}]" + }, + "immutable": true, + "kind": "ConfigMap", + "metadata": { + "creationTimestamp": "2024-09-25T11:11:50Z", + "name": "k8s-components-sha256-7b73c7675df78e5753b6e0fc86a9982127fd16141837599d5ce16df6bfe6a2a0", + "namespace": "kube-system", + "resourceVersion": "356", + "uid": "6389c186-3bc8-4470-8af5-f6fed1addd69" + } +} +``` \ No newline at end of file diff --git a/dev-docs/workflows/bazel.md b/dev-docs/workflows/bazel.md index 2e8ee57ea..8dc38b7ea 100644 --- a/dev-docs/workflows/bazel.md +++ b/dev-docs/workflows/bazel.md @@ -3,6 +3,13 @@ Bazel is the primary build system for this project. It is used to build all Go code and will be used to build all artifacts in the future. Still, we aim to keep the codebase compatible with `go build` and `go test` as well. Whenever Go code is changed, you will have to run `bazel run //:tidy` to regenerate the Bazel build files for Go code. +Additionally, you need to update `MODULE.bazel`, together with `MODULE.bazel.lock`: + +``` +# if the steps below fail, try to recreate the lockfile from scratch by deleting it +bazel mod deps --lockfile_mode=update +bazel mod tidy +``` ## Bazel commands diff --git a/dev-docs/workflows/bump-go-version.md b/dev-docs/workflows/bump-go-version.md index 3ec607d17..09b3fad81 100644 --- a/dev-docs/workflows/bump-go-version.md +++ b/dev-docs/workflows/bump-go-version.md @@ -4,12 +4,11 @@ ## Steps -Replace "1.xx.x" with the new version in [WORKSPACE.bazel](/WORKSPACE.bazel): +Replace `"1.xx.x"` with the new version in [MODULE.bazel](/MODULE.bazel): ```starlark -load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk", "go_register_toolchains", "go_rules_dependencies") - -go_download_sdk( +go_sdk = use_extension("@io_bazel_rules_go//go:extensions.bzl", "go_sdk") +go_sdk.download( name = "go_sdk", patches = ["//3rdparty/bazel/org_golang:go_tls_max_handshake_size.patch"], version = "1.xx.x", <--- Replace this one @@ -17,3 +16,24 @@ go_download_sdk( ) ``` + +Replace `go-version: "1.xx.x"` with the new version in all GitHub actions and workflows. +You can use the following command to find replace all instances of `go-version: "1.xx.x"` in the `.github` directory: + +```bash +OLD_VERSION="1.xx.x" +NEW_VERSION="1.xx.y" +find .github -type f -exec sed -i "s/go-version: \"${OLD_VERSION}\"/go-version: \"${NEW_VERSION}\"/g" {} \; +sed -i "s/go ${OLD_VERSION}/go ${NEW_VERSION}/g" go.mod +sed -i "s/${OLD_VERSION}/${NEW_VERSION}/g" go.work +``` + +Or manually: + +```yaml +- name: Setup Go environment + uses: actions/setup-go@v5 + with: + go-version: "1.xx.x" <--- Replace this one + ~~~~~~~~ +``` diff --git a/dev-docs/workflows/github-actions.md b/dev-docs/workflows/github-actions.md index ef97ed332..89f9f5d3c 100644 --- a/dev-docs/workflows/github-actions.md +++ b/dev-docs/workflows/github-actions.md @@ -24,7 +24,7 @@ Here are some examples for test suites you might want to run. Values for `sonobu * `--mode certified-conformance` * For K8s conformance certification test suite -Check [Sonobuoy docs](https://sonobuoy.io/docs/latest/e2eplugin/) for more examples. +Check [Sonobuoy docs](https://sonobuoy.io/docs/v0.57.1/e2eplugin/) for more examples. When using `--mode` be aware that `--e2e-focus` and `e2e-skip` will be overwritten. [Check in the source code](https://github.com/vmware-tanzu/sonobuoy/blob/e709787426316423a4821927b1749d5bcc90cb8c/cmd/sonobuoy/app/modes.go#L130) what the different modes do. diff --git a/dev-docs/workflows/qemu.md b/dev-docs/workflows/qemu.md index 3f294cc8b..dd327d31b 100644 --- a/dev-docs/workflows/qemu.md +++ b/dev-docs/workflows/qemu.md @@ -20,7 +20,7 @@ Follow the steps in our [libvirt readme](../../nix/container/README.md) if you w ### Install required packages -[General reference](https://ubuntu.com/server/docs/virtualization-libvirt) +[General reference](https://documentation.ubuntu.com/server/how-to/virtualisation/libvirt/) ```shell-session sudo apt install qemu-kvm libvirt-daemon-system xsltproc diff --git a/dev-docs/workflows/release.md b/dev-docs/workflows/release.md index 3460edb15..be873d563 100644 --- a/dev-docs/workflows/release.md +++ b/dev-docs/workflows/release.md @@ -46,6 +46,8 @@ Releases should be performed using [the automated release pipeline](https://gith 6. look over the autogenerated draft release. When fixing the changelog, prioritize updating the PR title/labels/description and regenerating the changelog over fixing things in the final changelog. The changelog should be primarily aimed at users. Rule of thumb: first part of the sentence should describe what changed for the user, second part can describe what has been changed to achieve this. 7. in the GitHub release UI, make sure the tag to create on release is set to `$ver`, and the target commit is set to the temporary release branch. 8. publish. +9. follow [post release steps](#post-release-steps). + ### Minor release @@ -78,21 +80,14 @@ Releases should be performed using [the automated release pipeline](https://gith 8. set the Target to `tmp/${ver}` 9. in the GitHub release UI, make sure the tag to create on release is set to `$ver`, and the target commit is set to the temporary release branch. 10. publish. +11. follow [post release steps](#post-release-steps). ## Post release steps 1. Publish the [provider release](https://github.com/edgelesssys/terraform-provider-constellation/releases) -2. Merge the versioned docs PR -3. Close fixed "known issues" -4. Milestones management - 1. Create a new milestone for the next release - 2. Add the next release manager and an approximate release date to the milestone description - 3. Close the milestone for the release - 4. Move open issues and PRs from closed milestone to next milestone -5. If the release is a minor version release, bump the pre-release version in the `version.txt` file. -6. Update the `fromVersion` in `e2e-test-release.yml` and `e2e-test-weekly.yaml` to the newly released version. To check the current values, run: `grep "fromVersion: \[.*\]" -R .github`. -7. Reset `UpgradeRequiresIAMMigration` in [`iamupgrade.go`](https://github.com/edgelesssys/constellation/blob/a88a731576184e3c5ee8527741c4a0cdaa4e9b24/cli/internal/cloudcmd/iamupgrade.go#L23). -8. Write an email to STACKIT to inform them of the new relase. For this, you require the name and UUID of the release image. You can find the email address in our internal [wiki](https://github.com/edgelesssys/wiki/blob/master/documentation/constellation/stackit.md): +2. Merge the automated post release PR +3. Write an email to STACKIT to inform them of the new release. For this, you require the name and UUID of the release image. You can find the email address in our internal [wiki](https://github.com/edgelesssys/wiki/blob/master/documentation/constellation/stackit.md): + ```shell-session export OS_CLOUD=stackit openstack image list | grep constellation @@ -100,6 +95,10 @@ Releases should be performed using [the automated release pipeline](https://gith # | 25edf48d-161f-452b-b420-963c3a80abd8 | constellation-stable-v2.16.4-qemu-vtpm | active | ``` +4. Close fixed "known issues" +5. Move open issues and PRs from this release's closed milestone to next milestone +6. Reset `UpgradeRequiresIAMMigration` in [`iamupgrade.go`](https://github.com/edgelesssys/constellation/blob/a88a731576184e3c5ee8527741c4a0cdaa4e9b24/cli/internal/cloudcmd/iamupgrade.go#L23). + ## Troubleshooting: Pipeline cleanup No manual steps should be necessary anymore but in case you encounter issues, create a ticket to fix it. These are instructions to do some cleanup steps manually: diff --git a/dev-docs/workflows/terraform-provider.md b/dev-docs/workflows/terraform-provider.md index 7f255710f..3dff8e290 100644 --- a/dev-docs/workflows/terraform-provider.md +++ b/dev-docs/workflows/terraform-provider.md @@ -12,7 +12,7 @@ The [`devbuild` target](./build-develop-deploy.md), will create a `terraform` di with the provider binary and some utility files in the dedicated local Terraform registry directory. ```bash -bazel run //:devbuild' +bazel run //:devbuild ``` > [!IMPORTANT] when making changes on the provider without a commit, subsequent applies will fail due to the changed binary hash. To solve this, in your Terraform directory run: diff --git a/disk-mapper/internal/recoveryserver/BUILD.bazel b/disk-mapper/internal/recoveryserver/BUILD.bazel index 966b93afd..fc1c24a53 100644 --- a/disk-mapper/internal/recoveryserver/BUILD.bazel +++ b/disk-mapper/internal/recoveryserver/BUILD.bazel @@ -14,7 +14,7 @@ go_library( "//internal/grpc/grpclog", "//internal/kms/kms", "//internal/logger", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//status", ], diff --git a/disk-mapper/internal/recoveryserver/recoveryserver.go b/disk-mapper/internal/recoveryserver/recoveryserver.go index 5234d2e63..f4a58724e 100644 --- a/disk-mapper/internal/recoveryserver/recoveryserver.go +++ b/disk-mapper/internal/recoveryserver/recoveryserver.go @@ -59,7 +59,7 @@ func New(issuer atls.Issuer, factory kmsFactory, log *slog.Logger) *RecoveryServ grpcServer := grpc.NewServer( grpc.Creds(atlscredentials.New(issuer, nil)), - logger.GetServerStreamInterceptor(log.WithGroup("gRPC")), + logger.GetServerStreamInterceptor(logger.GRPCLogger(log)), ) recoverproto.RegisterAPIServer(grpcServer, server) diff --git a/disk-mapper/internal/recoveryserver/recoveryserver_test.go b/disk-mapper/internal/recoveryserver/recoveryserver_test.go index cf4e6c043..1a7722bb7 100644 --- a/disk-mapper/internal/recoveryserver/recoveryserver_test.go +++ b/disk-mapper/internal/recoveryserver/recoveryserver_test.go @@ -123,7 +123,7 @@ func TestRecover(t *testing.T) { diskKey, measurementSecret, serveErr = server.Serve(serveCtx, listener, serverUUID) }() - conn, err := dialer.New(nil, nil, netDialer).Dial(ctx, "192.0.2.1:1234") + conn, err := dialer.New(nil, nil, netDialer).Dial("192.0.2.1:1234") require.NoError(err) defer conn.Close() diff --git a/disk-mapper/internal/rejoinclient/BUILD.bazel b/disk-mapper/internal/rejoinclient/BUILD.bazel index 01f0c26e5..77238f692 100644 --- a/disk-mapper/internal/rejoinclient/BUILD.bazel +++ b/disk-mapper/internal/rejoinclient/BUILD.bazel @@ -12,7 +12,7 @@ go_library( "//internal/role", "//joinservice/joinproto", "@io_k8s_utils//clock", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", ], ) @@ -31,7 +31,7 @@ go_test( "//joinservice/joinproto", "@com_github_stretchr_testify//assert", "@io_k8s_utils//clock/testing", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_uber_go_goleak//:goleak", ], ) diff --git a/disk-mapper/internal/rejoinclient/rejoinclient.go b/disk-mapper/internal/rejoinclient/rejoinclient.go index bedb01535..ac0e17871 100644 --- a/disk-mapper/internal/rejoinclient/rejoinclient.go +++ b/disk-mapper/internal/rejoinclient/rejoinclient.go @@ -123,7 +123,7 @@ func (c *RejoinClient) requestRejoinTicket(endpoint string) (*joinproto.IssueRej ctx, cancel := c.timeoutCtx() defer cancel() - conn, err := c.dialer.Dial(ctx, endpoint) + conn, err := c.dialer.Dial(endpoint) if err != nil { return nil, err } @@ -185,7 +185,7 @@ func (c *RejoinClient) timeoutCtx() (context.Context, context.CancelFunc) { } type grpcDialer interface { - Dial(ctx context.Context, target string) (*grpc.ClientConn, error) + Dial(target string) (*grpc.ClientConn, error) } type metadataAPI interface { diff --git a/disk-mapper/recoverproto/recover.pb.go b/disk-mapper/recoverproto/recover.pb.go index 46d6943fa..0a071e68b 100644 --- a/disk-mapper/recoverproto/recover.pb.go +++ b/disk-mapper/recoverproto/recover.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.1 -// protoc v4.22.1 +// protoc-gen-go v1.35.1 +// protoc v5.29.0--rc2 // source: disk-mapper/recoverproto/recover.proto package recoverproto @@ -35,11 +35,9 @@ type RecoverMessage struct { func (x *RecoverMessage) Reset() { *x = RecoverMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_disk_mapper_recoverproto_recover_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_disk_mapper_recoverproto_recover_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *RecoverMessage) String() string { @@ -50,7 +48,7 @@ func (*RecoverMessage) ProtoMessage() {} func (x *RecoverMessage) ProtoReflect() protoreflect.Message { mi := &file_disk_mapper_recoverproto_recover_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -87,11 +85,9 @@ type RecoverResponse struct { func (x *RecoverResponse) Reset() { *x = RecoverResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_disk_mapper_recoverproto_recover_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_disk_mapper_recoverproto_recover_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *RecoverResponse) String() string { @@ -102,7 +98,7 @@ func (*RecoverResponse) ProtoMessage() {} func (x *RecoverResponse) ProtoReflect() protoreflect.Message { mi := &file_disk_mapper_recoverproto_recover_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -155,7 +151,7 @@ func file_disk_mapper_recoverproto_recover_proto_rawDescGZIP() []byte { } var file_disk_mapper_recoverproto_recover_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_disk_mapper_recoverproto_recover_proto_goTypes = []interface{}{ +var file_disk_mapper_recoverproto_recover_proto_goTypes = []any{ (*RecoverMessage)(nil), // 0: recoverproto.RecoverMessage (*RecoverResponse)(nil), // 1: recoverproto.RecoverResponse } @@ -174,32 +170,6 @@ func file_disk_mapper_recoverproto_recover_proto_init() { if File_disk_mapper_recoverproto_recover_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_disk_mapper_recoverproto_recover_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RecoverMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_disk_mapper_recoverproto_recover_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RecoverResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/docs/.gitignore b/docs/.gitignore index b2db0247a..ef904e99f 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,4 +1,3 @@ node_modules -package-lock.json .docusaurus build/ \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index dea229064..4814729e9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,7 +8,7 @@ During edits you can preview your changes using the [`docusaurus`](https://docus ```sh # requires node >=16.14 -npm install +npm ci # Install pinned dependencies npm run build npm run serve ``` diff --git a/docs/docs/architecture/attestation.md b/docs/docs/architecture/attestation.md index 5a8638964..9bd157460 100644 --- a/docs/docs/architecture/attestation.md +++ b/docs/docs/architecture/attestation.md @@ -78,15 +78,15 @@ The idea is that Constellation nodes should have verifiable integrity from the C The solution is a verifiable boot chain and an integrity-protected runtime environment. Constellation uses measured boot within CVMs, measuring each component in the boot process before executing it. -Outside of CC, it's usually implemented via TPMs. +Outside of CC, this is usually implemented via TPMs. CVM technologies differ in how they implement runtime measurements, but the general concepts are similar to those of a TPM. For simplicity, TPM terminology like *PCR* is used in the following. -When a Constellation node image boots inside a CVM, it uses measured boot for all stages and components of the boot chain. +When a Constellation node image boots inside a CVM, measured boot is used for all stages and components of the boot chain. This process goes up to the root filesystem. -The root filesystem is mounted read-only with integrity protection, guaranteeing forward integrity. +The root filesystem is mounted read-only with integrity protection. For the details on the image and boot stages see the [image architecture](../architecture/images.md) documentation. -Any changes to the image will inevitably also change the measured boot's PCR values. +Any changes to the image will inevitably also change the corresponding PCR values. To create a node attestation statement, the Constellation image obtains a CVM attestation statement from the hardware. This includes the runtime measurements and thereby binds the measured boot results to the CVM hardware measurement. @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -153,8 +153,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -184,8 +184,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -217,8 +217,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses a hypervisor-based vTPM for runtime measurements. @@ -249,16 +249,16 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ### CVM verification To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. For verification of the CVM technology, Constellation may expose additional options in its config file. - - + + On AWS, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the VM. @@ -279,8 +279,8 @@ You may customize certain parameters for verification of the attestation stateme This is the intermediate certificate for verifying the SEV-SNP report's signature. If it's not specified, the CLI fetches it from the AMD key distribution server. - - + + On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. @@ -302,22 +302,37 @@ You may customize certain parameters for verification of the attestation stateme More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. - - + + -On GCP, AMD SEV-ES is used to provide runtime encryption to the VMs. -The hypervisor-based vTPM is used to establish trust in the VM via [runtime measurements](#runtime-measurements). -There is no additional configuration available for GCP. +On GCP, AMD SEV-SNP is used to provide runtime encryption to the VMs. +An SEV-SNP attestation report is used to establish trust in the VM. +You may customize certain parameters for verification of the attestation statement using the Constellation config file. - - +* TCB versions + + You can set the minimum version numbers of components in the SEV-SNP TCB. + Use the latest versions to enforce that only machines with the most recent firmware updates are allowed to join the cluster. + Alternatively, you can set a lower minimum version to allow slightly out-of-date machines to still be able to join the cluster. + +* AMD Root Key Certificate + + This certificate is the root of trust for verifying the SEV-SNP certificate chain. + +* AMD Signing Key Certificate + + This is the intermediate certificate for verifying the SEV-SNP report's signature. + If it's not specified, the CLI fetches it from the AMD key distribution server. + + + On STACKIT, AMD SEV-ES is used to provide runtime encryption to the VMs. The hypervisor-based vTPM is used to establish trust in the VM via [runtime measurements](#runtime-measurements). There is no additional configuration available for STACKIT. - - + + ## Cluster attestation @@ -341,32 +356,52 @@ When an initialized node tries to join another cluster, its measurements inevita The [*VerificationService*](microservices.md#verificationservice) provides an endpoint for obtaining its hardware-based remote attestation statement, which includes the runtime measurements. A user can [verify](../workflows/verify-cluster.md) this statement and compare the measurements against the configured ground truth and, thus, verify the identity and integrity of all Constellation components and the cluster configuration. Subsequently, the user knows that the entire cluster is in the expected state and is trustworthy. -## Chain of trust +## Putting it all together -So far, this page described how an entire Constellation cluster can be verified using hardware attestation capabilities and runtime measurements. -The last missing link is how the ground truth in the form of runtime measurements can be securely distributed to the verifying party. +This section puts the aforementioned concepts together and illustrate how trust into a Constellation cluster is established and maintained. -The build process of Constellation images also creates the ground truth runtime measurements. The builds of Constellation images are reproducible and the measurements of an image can be recalculated and verified by everyone. -With every release, Edgeless Systems publishes signed runtime measurements. +### CLI and node images -The CLI executable is also signed by Edgeless Systems. -You can [verify its signature](../workflows/verify-cli.md). +It all starts with the CLI executable. The CLI is signed by Edgeless Systems. To ensure non-repudiability for CLI releases, Edgeless Systems publishes corresponding signatures to the public ledger of the [sigstore project](https://www.sigstore.dev/). There's a [step-by-step guide](../workflows/verify-cli.md) on how to verify CLI signatures based on sigstore. -The CLI contains the public key required to verify signed runtime measurements from Edgeless Systems. -When a cluster is [created](../workflows/create.md) or [upgraded](../workflows/upgrade.md), the CLI automatically verifies the measurements for the selected image. +The CLI contains the latest runtime measurements of the Constellation node image for all supported cloud platforms. In case a different version of the node image is to be used, the corresponding runtime measurements can be fetched using the CLI's [fetch-measurements command](../reference/cli.md#constellation-config-fetch-measurements). This command downloads the runtime measurements and the corresponding signature from cdn.confidential.cloud. See for example the following files corresponding to node image v2.16.3: -Thus, there's a chain of trust based on cryptographic signatures, which goes from CLI to runtime measurements to images. This is illustrated in the following diagram. +* [Measurements](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json) +* [Signature](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json.sig) + +The CLI contains the long-term public key of Edgeless Systems to verify the signature of downloaded runtime measurements. + +### Cluster creation + +When a cluster is [created](../workflows/create.md), the CLI automatically verifies the runtime measurements of the *first node* using remote attestation. Based on this, the CLI and the first node set up a temporary TLS connection. This [aTLS](#attested-tls-atls) connection is used for two things: + +1. The CLI sends the [master secret](../architecture/keys.md#master-secret) of the to-be-created cluster to the CLI. The master secret is generated by the first node. +2. The first node sends a [kubeconfig file](https://www.redhat.com/sysadmin/kubeconfig) with Kubernetes credentials to the CLI. + +After this, the aTLS connection is closed and the first node bootstraps the Kubernetes cluster. All subsequent interactions between the CLI and the cluster go via the [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) server running inside the cluster. The CLI (and other tools like kubectl) use the credentials referenced by the kubeconfig file to authenticate themselves towards the Kubernetes API server and to establish a mTLS connection. + +The CLI connects to the Kubernetes API to write the runtime measurements for the applicable node image to etcd. The JoinService uses these runtime measurements to verify all nodes that join the cluster subsequently. + +### Chain of trust + +In summary, there's a chain of trust based on cryptographic signatures that goes from the user to the cluster via the CLI. This is illustrated in the following diagram. ```mermaid flowchart LR - A[Edgeless]-- "signs (cosign)" -->B[CLI] - C[User]-- "verifies (cosign)" -->B[CLI] - B[CLI]-- "contains" -->D["Public Key"] - A[Edgeless]-- "signs" -->E["Runtime measurements"] - D["Public key"]-- "verifies" -->E["Runtime measurements"] - E["Runtime measurements"]-- "verify" -->F["Constellation cluster"] + A[User]-- "verifies" -->B[CLI] + B[CLI]-- "verifies" -->C([Runtime measurements]) + D[Edgeless Systems]-- "signs" -->B[CLI] + D[Edgeless Systems]-- "signs" -->C([Runtime measurements]) + B[CLI]-- "verifies (remote attestation)" -->E[First node] + E[First node]-- "verifies (remote attestation)" -->F[Other nodes] + C([Runtime measurements]) -.-> E[First node] + C([Runtime measurements]) -.-> F[Other nodes] ``` +### Upgrades + +Whenever a cluster is [upgraded](../workflows/upgrade.md) to a new version of the node image, the CLI sends the corresponding runtime measurements via the Kubernetes API server. The new runtime measurements are stored in etcd within the cluster and replace any previous runtime measurements. The new runtime measurements are then used automatically by the JoinService for the verification of new nodes. + ## References [^1]: Linux IMA produces runtime measurements of user-space binaries. diff --git a/docs/docs/architecture/keys.md b/docs/docs/architecture/keys.md index 553d9d4e2..49821cd0b 100644 --- a/docs/docs/architecture/keys.md +++ b/docs/docs/architecture/keys.md @@ -42,7 +42,6 @@ Each node creates its own [Curve25519](http://cr.yp.to/ecdh.html) encryption key A node uses another node's public key to decrypt and encrypt traffic from and to Cilium-managed endpoints running on that node. Connections are always encrypted peer-to-peer using [ChaCha20](http://cr.yp.to/chacha.html) with [Poly1305](http://cr.yp.to/mac.html). WireGuard implements [forward secrecy with key rotation every 2 minutes](https://lists.zx2c4.com/pipermail/wireguard/2017-December/002141.html). -Cilium supports [key rotation](https://docs.cilium.io/en/stable/security/network/encryption-ipsec/#key-rotation) for the long-term node keys via Kubernetes secrets. ## Storage encryption diff --git a/docs/docs/architecture/versions.md b/docs/docs/architecture/versions.md index b479292dc..6127bfb0c 100644 --- a/docs/docs/architecture/versions.md +++ b/docs/docs/architecture/versions.md @@ -16,6 +16,6 @@ Subsequent Constellation releases drop support for the oldest (and deprecated) K The following Kubernetes versions are currently supported: -* v1.27.13 -* v1.28.9 -* v1.29.4 +* v1.28.14 +* v1.29.9 +* v1.30.5 diff --git a/docs/docs/getting-started/first-steps-local.md b/docs/docs/getting-started/first-steps-local.md index 052d29eae..98f0302de 100644 --- a/docs/docs/getting-started/first-steps-local.md +++ b/docs/docs/getting-started/first-steps-local.md @@ -45,8 +45,8 @@ sudo iptables -P FORWARD ACCEPT ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -74,8 +74,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -145,8 +145,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -199,8 +199,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -211,8 +211,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -240,8 +240,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/docs/getting-started/first-steps.md b/docs/docs/getting-started/first-steps.md index 925ec7df9..128ac2849 100644 --- a/docs/docs/getting-started/first-steps.md +++ b/docs/docs/getting-started/first-steps.md @@ -13,43 +13,43 @@ If you encounter any problem with the following steps, make sure to use the [lat ## Create a cluster -1. Create the [configuration file](../workflows/config.md) and state file for your cloud provider. If you are following the steps of this guide, there is no need to edit the file. +1. Create the [configuration file](../workflows/config.md) and state file for your cloud provider. If you are following the steps of this guide, there is no need to edit the file. - - + + ```bash constellation config generate aws ``` - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate stackit ``` - - + + 2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). - - + + ```bash constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config @@ -76,11 +76,11 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + ```bash - constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config + constellation iam create azure --subscriptionID 00000000-0000-0000-0000-000000000000 --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config ``` This command creates IAM configuration on the Azure region `westus` creating a new resource group `constellTest` and a new service principal `spTest`. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. @@ -98,8 +98,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). - - + + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config @@ -109,16 +109,16 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - - + + To use Constellation on STACKIT, the cluster will use the User Access Token (UAT) that's generated [during the install step](./install.md). After creating the accounts, fill in the STACKIT details in `constellation-conf.yaml` under `provider.openstack`: - - `stackitProjectID`: STACKIT project id (can be found after login on ) + * `stackitProjectID`: STACKIT project id (can be found after login on the [STACKIT portal](https://portal.stackit.cloud)) - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/docs/getting-started/install.md b/docs/docs/getting-started/install.md index 99a8933e3..fa481d9b8 100644 --- a/docs/docs/getting-started/install.md +++ b/docs/docs/getting-started/install.md @@ -22,8 +22,8 @@ If you prefer to use Terraform, you can alternatively use the [Terraform provide The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -39,8 +39,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -56,9 +56,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -74,9 +74,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -92,9 +92,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -115,8 +115,8 @@ Invoke-WebRequest -OutFile ./constellation.exe -Uri 'https://github.com/edgeless 5. Click `New` 6. Enter the path to the folder containing the binary you want on your PATH: `C:\Program Files\Constellation\bin` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -132,8 +132,8 @@ If you don't have a cloud subscription, you can also set up a [local Constellati ### Required permissions - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -183,12 +183,12 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] +* `Microsoft.Attestation` * `Microsoft.Compute` * `Microsoft.Insights` * `Microsoft.ManagedIdentity` @@ -208,7 +208,7 @@ The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] +* `Microsoft.Attestation/attestationProviders/*` * `Microsoft.Compute/virtualMachineScaleSets/*` * `Microsoft.Insights/components/*` * `Microsoft.ManagedIdentity/userAssignedIdentities/*` @@ -226,10 +226,8 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -314,16 +312,16 @@ Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and ` Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + Constellation on STACKIT requires a User Access Token (UAT) for the OpenStack API and a STACKIT service account. The UAT already has all required permissions by default. The STACKIT service account needs the `editor` role to create STACKIT LoadBalancers. Look at the [STACKIT documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) on how to create the service account and assign the role. - - + + ### Authentication @@ -333,8 +331,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -350,8 +348,8 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - - + + **Testing** @@ -367,8 +365,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -391,13 +389,17 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + You need to authenticate with the infrastructure API (OpenStack) and create a service account (STACKIT API). 1. [Follow the STACKIT documentation](https://docs.stackit.cloud/stackit/en/step-1-generating-of-user-access-token-11763726.html) for obtaining a User Access Token (UAT) to use the infrastructure API -2. Create a configuration file under `~/.config/openstack/clouds.yaml` (`%AppData%\openstack\clouds.yaml` on Windows) with the credentials from the User Access Token +2. Create a configuration file with the credentials from the User Access Token under: + * Linux: `~/.config/openstack/clouds.yaml` + * macOS: `/Users//Library/Application Support/openstack/clouds.yaml` or `/etc/openstack/clouds.yaml` + * Windows: `%AppData%\openstack\clouds.yaml` + ```yaml clouds: @@ -414,6 +416,12 @@ You need to authenticate with the infrastructure API (OpenStack) and create a se identity_api_version: 3 ``` +:::caution + +`project_id` refers to the ID of your STACKIT project. The STACKIT portal also shows the OpenStack ID that's associated with your project in some places. Make sure you insert the STACKIT project ID in the `clouds.yaml` file. It's of the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. + +::: + 3. [Follow the STACKIT documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) for creating a service account and an access token 4. Assign the `editor` role to the service account by [following the documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) 5. Create a configuration file under `~/.stackit/credentials.json` (`%USERPROFILE%\.stackit\credentials.json` on Windows) @@ -422,9 +430,9 @@ You need to authenticate with the infrastructure API (OpenStack) and create a se {"STACKIT_SERVICE_ACCOUNT_TOKEN":"REPLACE_WITH_TOKEN"} ``` - + - + ## Next steps diff --git a/docs/docs/getting-started/marketplaces.md b/docs/docs/getting-started/marketplaces.md index b16d796d2..a6763a42a 100644 --- a/docs/docs/getting-started/marketplaces.md +++ b/docs/docs/getting-started/marketplaces.md @@ -4,8 +4,8 @@ Constellation is available through the Marketplaces of AWS, Azure, GCP, and STAC This document explains how to run Constellation with the dynamically billed cloud marketplace images. - - + + To use Constellation's marketplace images, ensure that you are subscribed to the [marketplace offering](https://aws.amazon.com/marketplace/pp/prodview-2mbn65nv57oys) through the web portal. @@ -15,8 +15,8 @@ Then, enable the use of marketplace images in your Constellation `constellation- yq eval -i ".provider.aws.useMarketplaceImage = true" constellation-conf.yaml ``` - - + + Constellation has a private marketplace plan. Please [contact us](https://www.edgeless.systems/enterprise-support/) to gain access. @@ -32,8 +32,8 @@ Then, enable the use of marketplace images in your Constellation `constellation- yq eval -i ".provider.azure.useMarketplaceImage = true" constellation-conf.yaml ``` - - + + To use a marketplace image, ensure that the account is entitled to use marketplace images by Edgeless Systems by accepting the terms through the [web portal](https://console.cloud.google.com/marketplace/vm/config/edgeless-systems-public/constellation). @@ -43,13 +43,13 @@ Then, enable the use of marketplace images in your Constellation `constellation- yq eval -i ".provider.gcp.useMarketplaceImage = true" constellation-conf.yaml ``` - - + + On STACKIT, the selected Constellation image is always a marketplace image. You can find more information on the STACKIT portal. - - + + Ensure that the cluster uses an official release image version (i.e., `.image=vX.Y.Z` in the `constellation-conf.yaml` file). diff --git a/docs/docs/overview/clouds.md b/docs/docs/overview/clouds.md index a7b1361e8..b2695d28e 100644 --- a/docs/docs/overview/clouds.md +++ b/docs/docs/overview/clouds.md @@ -12,46 +12,47 @@ For Constellation, the ideal environment provides the following: (1) is a functional must-have. (2)--(5) are required for remote attestation that fully keeps the infrastructure/cloud out. Constellation can work without them or with approximations, but won't protect against certain privileged attackers anymore. -The following table summarizes the state of features for different infrastructures as of June 2023. +The following table summarizes the state of features for different infrastructures. -| **Feature** | **Azure** | **GCP** | **AWS** | **STACKIT** | **OpenStack (Yoga)** | -|-----------------------------------|-----------|---------|---------|--------------|----------------------| -| **1. Custom images** | Yes | Yes | Yes | Yes | Yes | -| **2. SEV-SNP or TDX** | Yes | Yes | Yes | No | Depends on kernel/HV | -| **3. Raw guest attestation** | Yes | Yes | Yes | No | Depends on kernel/HV | -| **4. Reviewable firmware** | No | No | Yes | No | Depends on kernel/HV | -| **5. Confidential measured boot** | Yes | No | No | No | Depends on kernel/HV | - -## Microsoft Azure - -With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. -Regarding (3), Azure provides direct access to remote-attestation statements. -The firmware runs in an isolated domain inside the CVM and exposes a vTPM (5), but it's closed source (4). -On SEV-SNP, Azure uses VM Privilege Level (VMPL) isolation for the separation of firmware and the rest of the VM; on TDX, they use TD partitioning. -This firmware is signed by Azure. -The signature is reflected in the remote-attestation statements of CVMs. -Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). - -## Google Cloud Platform (GCP) - -The [CVMs Generally Available in GCP](https://cloud.google.com/confidential-computing/confidential-vm/docs/confidential-vm-overview#amd_sev) are based on AMD SEV but don't have SNP features enabled. -CVMs with [SEV-SNP enabled are in public preview](https://cloud.google.com/confidential-computing/confidential-vm/docs/confidential-vm-overview#amd_sev-snp). Regarding (3), with their SEV-SNP offering Google provides direct access to remote-attestation statements. -However, regarding (5), attestation is partially based on the [Shielded VM vTPM](https://cloud.google.com/compute/shielded-vm/docs/shielded-vm#vtpm) for [measured boot](../architecture/attestation.md#measured-boot), which is a vTPM managed by Google's hypervisor. -Hence, the hypervisor is currently part of Constellation's TCB. -Regarding (4), the CVMs still include closed-source firmware. - -In the past, Intel and Google have [collaborated](https://cloud.google.com/blog/products/identity-security/rsa-google-intel-confidential-computing-more-secure) to enhance the security of TDX. -Recently, Google has announced a [private preview for TDX](https://cloud.google.com/blog/products/identity-security/confidential-vms-on-intel-cpus-your-datas-new-intelligent-defense?hl=en). -With TDX on Google, Constellation has a similar TCB and attestation flow as with the current SEV-SNP offering. +| **Feature** | **AWS** | **Azure** | **GCP** | **STACKIT** | **OpenStack (Yoga)** | +|-----------------------------------|---------|-----------|---------|--------------|----------------------| +| **1. Custom images** | Yes | Yes | Yes | Yes | Yes | +| **2. SEV-SNP or TDX** | Yes | Yes | Yes | No | Depends on kernel/HV | +| **3. Raw guest attestation** | Yes | Yes | Yes | No | Depends on kernel/HV | +| **4. Reviewable firmware** | Yes | No* | No | No | Depends on kernel/HV | +| **5. Confidential measured boot** | No | Yes | No | No | Depends on kernel/HV | ## Amazon Web Services (AWS) Amazon EC2 [supports AMD SEV-SNP](https://aws.amazon.com/de/about-aws/whats-new/2023/04/amazon-ec2-amd-sev-snp/). -Regarding (3), AWS provides direct access to remote-attestation statements. +Regarding (3), AWS provides direct access to attestation statements. However, regarding (5), attestation is partially based on the [NitroTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) for [measured boot](../architecture/attestation.md#measured-boot), which is a vTPM managed by the Nitro hypervisor. Hence, the hypervisor is currently part of Constellation's TCB. Regarding (4), the [firmware is open source](https://github.com/aws/uefi) and can be reproducibly built. +## Microsoft Azure + +With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. +Regarding (3), Azure provides direct access to attestation statements. +The firmware runs in an isolated domain inside the CVM and exposes a vTPM (5), but it's closed source (4). +On SEV-SNP, Azure uses VM Privilege Level (VMPL) isolation for the separation of firmware and the rest of the VM; on TDX, they use TD partitioning. +This firmware is signed by Azure. +The signature is reflected in the attestation statements of CVMs. +Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). + +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. + +## Google Cloud Platform (GCP) + +The [CVMs Generally Available in GCP](https://cloud.google.com/confidential-computing/confidential-vm/docs/confidential-vm-overview#technologies) are based on AMD SEV-ES or SEV-SNP. +Regarding (3), with their SEV-SNP offering Google provides direct access to attestation statements. +However, regarding (5), attestation is partially based on the [Shielded VM vTPM](https://cloud.google.com/compute/shielded-vm/docs/shielded-vm#vtpm) for [measured boot](../architecture/attestation.md#measured-boot), which is a vTPM managed by Google's hypervisor. +Hence, the hypervisor is currently part of Constellation's TCB. +Regarding (4), the CVMs still include closed-source firmware. + +[TDX on Google](https://cloud.google.com/blog/products/identity-security/confidential-vms-on-intel-cpus-your-datas-new-intelligent-defense) is in public preview. +With it, Constellation would have a similar TCB and attestation flow as with the current SEV-SNP offering. + ## STACKIT [STACKIT Compute Engine](https://www.stackit.de/en/product/stackit-compute-engine/) supports AMD SEV-ES. A vTPM is used for measured boot, which is a vTPM managed by STACKIT's hypervisor. Hence, the hypervisor is currently part of Constellation's TCB. diff --git a/docs/docs/overview/confidential-kubernetes.md b/docs/docs/overview/confidential-kubernetes.md index ca20df4de..bff8c3322 100644 --- a/docs/docs/overview/confidential-kubernetes.md +++ b/docs/docs/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/docs/overview/performance/compute.md b/docs/docs/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/docs/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/docs/overview/performance/performance.md b/docs/docs/overview/performance/performance.md index 7f22a693e..59bf86602 100644 --- a/docs/docs/overview/performance/performance.md +++ b/docs/docs/overview/performance/performance.md @@ -1,18 +1,10 @@ # Performance analysis of Constellation -This section provides a comprehensive examination of the performance characteristics of Constellation, encompassing various aspects, including runtime encryption, I/O benchmarks, and real-world applications. +This section provides a comprehensive examination of the performance characteristics of Constellation. -## Impact of runtime encryption on performance +## Runtime encryption -All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. - -### AMD and Azure benchmarking - -AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. - -### AMD and Google benchmarking - -Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. ## I/O performance benchmarks diff --git a/docs/docs/reference/cli.md b/docs/docs/reference/cli.md index 909495b7f..99acef520 100644 --- a/docs/docs/reference/cli.md +++ b/docs/docs/reference/cli.md @@ -78,9 +78,9 @@ constellation config generate {aws|azure|gcp|openstack|qemu|stackit} [flags] ### Options ``` - -a, --attestation string attestation variant to use {aws-sev-snp|aws-nitro-tpm|azure-sev-snp|azure-tdx|azure-trustedlaunch|gcp-sev-es|gcp-sev-snp|qemu-vtpm}. If not specified, the default for the cloud provider is used + -a, --attestation string attestation variant to use {aws-sev-snp|aws-nitro-tpm|azure-sev-snp|azure-tdx|azure-trustedlaunch|gcp-sev-snp|gcp-sev-es|qemu-vtpm}. If not specified, the default for the cloud provider is used -h, --help help for generate - -k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR (default "v1.28") + -k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR (default "v1.29") -t, --tags strings additional tags for created resources given a list of key=value ``` @@ -655,6 +655,7 @@ constellation iam create azure [flags] --region string region the resources will be created in, e.g., westus (required) --resourceGroup string name prefix of the two resource groups your cluster / IAM resources will be created in (required) --servicePrincipal string name of the service principal that will be created (required) + --subscriptionID string subscription ID of the Azure account. Required if the 'ARM_SUBSCRIPTION_ID' environment variable is not set ``` ### Options inherited from parent commands diff --git a/docs/docs/reference/migration.md b/docs/docs/reference/migration.md index 36680eef6..0252c409f 100644 --- a/docs/docs/reference/migration.md +++ b/docs/docs/reference/migration.md @@ -3,39 +3,81 @@ This document describes breaking changes and migrations between Constellation releases. Use [`constellation config migrate`](./cli.md#constellation-config-migrate) to automatically update an old config file to a new format. -## Migrating from Azure's service principal authentication to managed identity authentication +## Migrations to v2.19.1 -- The `provider.azure.appClientID` and `provider.azure.appClientSecret` fields are no longer supported and should be removed. -- To keep using an existing UAMI, add the `Owner` permission with the scope of your `resourceGroup`. -- Otherwise, simply [create new Constellation IAM credentials](../workflows/config.md#creating-an-iam-configuration) and use the created UAMI. -- To migrate the authentication for an existing cluster on Azure to an UAMI with the necessary permissions: +### Azure + +* During the upgrade, security rules are migrated and the old ones need to be cleaned up manually by the user. The below script shows how to delete them through the Azure CLI: + +```bash +#!/usr/bin/env bash +name="" # the name provided in the config +uid="" # the cluster id can be retrieved via `yq '.infrastructure.uid' constellation-state.yaml` +resource_group="" # the RG can be retrieved via `yq '.provider.azure.resourceGroup' constellation-conf.yaml` + +rules=( + "kubernetes" + "bootstrapper" + "verify" + "recovery" + "join" + "debugd" + "konnectivity" +) + +for rule in "${rules[@]}"; do + echo "Deleting rule: ${rule}" + az network nsg rule delete \ + --resource-group "${resource_group}" \ + --nsg-name "${name}-${uid}" \ + --name "${rule}" +done + +echo "All specified rules have been deleted." +``` + +## Migrations to v2.19.0 + +### Azure + +* To allow seamless upgrades on Azure when Kubernetes services of type `LoadBalancer` are deployed, the target + load balancer in which the `cloud-controller-manager` creates load balancing rules was changed. Instead of using the load balancer + created and maintained by the CLI's Terraform code, the `cloud-controller-manager` now creates its own load balancer in Azure. + If your Constellation has services of type `LoadBalancer`, please remove them before the upgrade and re-apply them + afterward. + +## Migrating from Azure's service principal authentication to managed identity authentication (during the upgrade to Constellation v2.8.0) + +* The `provider.azure.appClientID` and `provider.azure.appClientSecret` fields are no longer supported and should be removed. +* To keep using an existing UAMI, add the `Owner` permission with the scope of your `resourceGroup`. +* Otherwise, simply [create new Constellation IAM credentials](../workflows/config.md#creating-an-iam-configuration) and use the created UAMI. +* To migrate the authentication for an existing cluster on Azure to an UAMI with the necessary permissions: 1. Remove the `aadClientId` and `aadClientSecret` from the azureconfig secret. 2. Set `useManagedIdentityExtension` to `true` and use the `userAssignedIdentity` from the Constellation config for the value of `userAssignedIdentityID`. 3. Restart the CSI driver, cloud controller manager, cluster autoscaler, and Constellation operator pods. - ## Migrating from CLI versions before 2.10 -- AWS cluster upgrades require additional IAM permissions for the newly introduced `aws-load-balancer-controller`. Please upgrade your IAM roles using `iam upgrade apply`. This will show necessary changes and apply them, if desired. -- The global `nodeGroups` field was added. -- The fields `instanceType`, `stateDiskSizeGB`, and `stateDiskType` for each cloud provider are now part of the configuration of individual node groups. -- The `constellation create` command no longer uses the flags `--control-plane-count` and `--worker-count`. Instead, the initial node count is configured per node group in the `nodeGroups` field. +* AWS cluster upgrades require additional IAM permissions for the newly introduced `aws-load-balancer-controller`. Please upgrade your IAM roles using `iam upgrade apply`. This will show necessary changes and apply them, if desired. +* The global `nodeGroups` field was added. +* The fields `instanceType`, `stateDiskSizeGB`, and `stateDiskType` for each cloud provider are now part of the configuration of individual node groups. +* The `constellation create` command no longer uses the flags `--control-plane-count` and `--worker-count`. Instead, the initial node count is configured per node group in the `nodeGroups` field. ## Migrating from CLI versions before 2.9 -- The `provider.azure.appClientID` and `provider.azure.clientSecretValue` fields were removed to enforce migration to managed identity authentication +* The `provider.azure.appClientID` and `provider.azure.clientSecretValue` fields were removed to enforce migration to managed identity authentication ## Migrating from CLI versions before 2.8 -- The `measurements` field for each cloud service provider was replaced with a global `attestation` field. -- The `confidentialVM`, `idKeyDigest`, and `enforceIdKeyDigest` fields for the Azure cloud service provider were removed in favor of using the global `attestation` field. -- The optional global field `attestationVariant` was replaced by the now required `attestation` field. +* The `measurements` field for each cloud service provider was replaced with a global `attestation` field. +* The `confidentialVM`, `idKeyDigest`, and `enforceIdKeyDigest` fields for the Azure cloud service provider were removed in favor of using the global `attestation` field. +* The optional global field `attestationVariant` was replaced by the now required `attestation` field. ## Migrating from CLI versions before 2.3 -- The `sshUsers` field was deprecated in v2.2 and has been removed from the configuration in v2.3. +* The `sshUsers` field was deprecated in v2.2 and has been removed from the configuration in v2.3. As an alternative for SSH, check the workflow section [Connect to nodes](../workflows/troubleshooting.md#node-shell-access). -- The `image` field for each cloud service provider has been replaced with a global `image` field. Use the following mapping to migrate your configuration: +* The `image` field for each cloud service provider has been replaced with a global `image` field. Use the following mapping to migrate your configuration:
Show all @@ -65,10 +107,11 @@ Use [`constellation config migrate`](./cli.md#constellation-config-migrate) to a | GCP | `projects/constellation-images/global/images/constellation-v2-2-0` | `v2.2.0` | | GCP | `projects/constellation-images/global/images/constellation-v2-1-0` | `v2.1.0` | | GCP | `projects/constellation-images/global/images/constellation-v2-0-0` | `v2.0.0` | +
-- The `enforcedMeasurements` field has been removed and merged with the `measurements` field. - - To migrate your config containing a new image (`v2.3` or greater), remove the old `measurements` and `enforcedMeasurements` entries from your config and run `constellation fetch-measurements` - - To migrate your config containing an image older than `v2.3`, remove the `enforcedMeasurements` entry and replace the entries in `measurements` as shown in the example below: +* The `enforcedMeasurements` field has been removed and merged with the `measurements` field. + * To migrate your config containing a new image (`v2.3` or greater), remove the old `measurements` and `enforcedMeasurements` entries from your config and run `constellation fetch-measurements` + * To migrate your config containing an image older than `v2.3`, remove the `enforcedMeasurements` entry and replace the entries in `measurements` as shown in the example below: ```diff measurements: diff --git a/docs/docs/workflows/config.md b/docs/docs/workflows/config.md index c59207054..95f791acd 100644 --- a/docs/docs/workflows/config.md +++ b/docs/docs/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,44 +14,44 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate aws ``` - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate stackit ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. @@ -62,20 +62,20 @@ If you are using the attestation variant `awsNitroTPM`, you can choose any of th The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m1a.4cd` VMs (4 vCPUs, 30 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. @@ -93,8 +93,8 @@ You can choose any of the SEV-enabled instance types. You can find a list of all The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. - - + + Fill the desired VM type into the `instanceType` fields in the `constellation-conf.yml` file. @@ -153,8 +153,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -178,13 +178,13 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). ```bash -constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest +constellation iam create azure --subscriptionID 00000000-0000-0000-0000-000000000000 --region=westus --resourceGroup=constellTest --servicePrincipal=spTest ``` This command creates IAM configuration on the Azure region `westus` creating a new resource group `constellTest` and a new service principal `spTest`. @@ -204,8 +204,8 @@ You can find a list of all [regions in Azure's documentation](https://azure.micr Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -219,21 +219,21 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + STACKIT requires manual creation and configuration of service accounts. Look at the [first steps](../getting-started/first-steps.md) for more information. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -264,8 +264,8 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -301,8 +301,8 @@ The following describes the configuration fields and how you obtain the required The user-assigned identity is used by instances of the cluster to access other cloud resources. For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). - - + + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -326,13 +326,13 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - - + + STACKIT requires manual creation and configuration of service accounts. Look at the [first steps](../getting-started/first-steps.md) for more information. - - + +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/docs/workflows/create.md b/docs/docs/workflows/create.md index 54bc9dcbc..6074ebb16 100644 --- a/docs/docs/workflows/create.md +++ b/docs/docs/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -27,8 +27,8 @@ If you don't have a cloud subscription, you can also set up a [local Constellati Before you create the cluster, make sure to have a [valid configuration file](./config.md). - - + + ```bash constellation apply @@ -36,8 +36,8 @@ constellation apply `apply` stores the state of your cluster's cloud resources in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Self-managed infrastructure allows for more flexibility in the setup, by separating the infrastructure setup from the Constellation cluster management. This provides flexibility in DevOps and can meet potential regulatory requirements. @@ -56,7 +56,7 @@ management tooling of your choice. You need to keep the essential functionality :::info - On Azure, if the enforcement policy is set to `MAAFallback` in `constellation-config.yaml`, a manual update to the MAA provider's policy is necessary. + On Azure, a manual update to the MAA provider's policy is necessary. You can apply the update with the following command after creating the infrastructure, with `` being the URL of the MAA provider (i.e., `$(terraform output attestation_url | jq -r)`, when using the minimal Terraform configuration). ```bash @@ -77,8 +77,8 @@ With the required cloud resources set up, continue with initializing your cluste constellation apply --skip-phases=infrastructure ``` - - + + Finally, configure `kubectl` for your cluster: diff --git a/docs/docs/workflows/recovery.md b/docs/docs/workflows/recovery.md index aea370e2f..592ae247b 100644 --- a/docs/docs/workflows/recovery.md +++ b/docs/docs/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via serial console output. In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -47,8 +47,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -82,8 +82,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the STACKIT portal to view all servers in your project. Select individual control plane nodes `--control-plane--` and check that enough members are in a *Running* state. @@ -149,8 +149,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster @@ -162,7 +162,7 @@ Recovering a cluster requires the following parameters: A cluster can be recovered like this: ```bash -$ constellation recover --master-secret constellation-mastersecret.json +$ constellation recover Pushed recovery key. Pushed recovery key. Pushed recovery key. diff --git a/docs/docs/workflows/reproducible-builds.md b/docs/docs/workflows/reproducible-builds.md new file mode 100644 index 000000000..e3bc46095 --- /dev/null +++ b/docs/docs/workflows/reproducible-builds.md @@ -0,0 +1,63 @@ +# Reproduce released artifacts + +Constellation has first-class support for [reproducible builds](https://reproducible-builds.org). +Reproducing the released artifacts is an alternative to [signature verification](verify-cli.md) that doesn't require trusting Edgeless Systems' release process. +The following sections describe how to rebuild an artifact and how Constellation ensures that the rebuild reproduces the artifacts bit-by-bit. + +## Build environment prerequisites + +The build systems used by Constellation - [Bazel](https://bazel.build/) and [Nix](https://nixos.org) - are designed for deterministic, reproducible builds. +These two dependencies should be the only prerequisites for a successful build. +However, it can't be ruled out completely that peculiarities of the host affect the build result. +Thus, we recommend the following host setup for best results: + +1. A Linux operating system not older than v5.4. +2. The GNU C library not older than v2.31 (avoid `musl`). +3. GNU `coreutils` not older than v8.30 (avoid `busybox`). +4. An `ext4` filesystem for building. +5. AppArmor turned off. + +This is given, for example, on an Ubuntu 22.04 system, which is also used for reproducibility tests. + +:::note + +To avoid any backwards-compatibility issues, the host software versions should also not be much newer than the Constellation release. + +::: + +## Run the build + +The following instructions outline qualitatively how to reproduce a build. +Constellation implements these instructions in the [Reproducible Builds workflow](https://github.com/edgelesssys/constellation/actions/workflows/reproducible-builds.yml), which continuously tests for reproducibility. +The workflow is a good place to look up specific version numbers and build steps. + +1. Check out the Constellation repository at the tag corresponding to the release. + + ```bash + git clone https://github.com/edgelesssys/constellation.git + cd constellation + git checkout v2.20.0 + ``` + +2. [Install the Bazel release](https://bazel.build/install) specified in `.bazelversion`. +3. [Install Nix](https://nixos.org/download/) (any recent version should do). +4. Run the build with `bazel build $target` for one of the following targets of interest: + + ```data + //cli:cli_enterprise_darwin_amd64 + //cli:cli_enterprise_darwin_arm64 + //cli:cli_enterprise_linux_amd64 + //cli:cli_enterprise_linux_arm64 + //cli:cli_enterprise_windows_amd64 + ``` + +5. Compare the build result with the downloaded release artifact. + + + +## Feedback + +Reproduction failures often indicate a bug in the build system or in the build definitions. +Therefore, we're interested in any reproducibility issues you might encounter. +[Start a bug report](https://github.com/edgelesssys/constellation/issues/new/choose) and describe the details of your build environment. +Make sure to include your result binary or a [`diffoscope`](https://diffoscope.org/) report, if possible. diff --git a/docs/docs/workflows/sbom.md b/docs/docs/workflows/sbom.md index 9ef6eb65c..6c1702dee 100644 --- a/docs/docs/workflows/sbom.md +++ b/docs/docs/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -11,13 +11,15 @@ SBOMs for Constellation are generated using [Syft](https://github.com/anchore/sy :::note The public key for Edgeless Systems' long-term code-signing key is: + ``` -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at https://edgeless.systems/es.pub and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -38,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/docs/workflows/scale.md b/docs/docs/workflows/scale.md index 0b52b9540..28f19e3f1 100644 --- a/docs/docs/workflows/scale.md +++ b/docs/docs/workflows/scale.md @@ -51,36 +51,36 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Go to Auto Scaling Groups and select the worker ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + Dynamic cluster scaling isn't yet supported for STACKIT. Support will be introduced in one of the upcoming releases. - - + + ## Control-plane node scaling @@ -88,35 +88,35 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - - + + 1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + Dynamic cluster scaling isn't yet supported for STACKIT. Support will be introduced in one of the upcoming releases. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/docs/workflows/storage.md b/docs/docs/workflows/storage.md index f1344d6ad..a5c52be90 100644 --- a/docs/docs/workflows/storage.md +++ b/docs/docs/workflows/storage.md @@ -21,37 +21,37 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for AWS Elastic Block Store** Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. - - + + **Constellation CSI driver for STACKIT / OpenStack Cinder** Mount [Cinder](https://docs.openstack.org/cinder/latest/) block storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-cloud-provider-openstack) for more information. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -60,8 +60,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + AWS comes with two storage classes by default. @@ -89,8 +89,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + Azure comes with two storage classes by default. @@ -118,8 +118,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -147,8 +147,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + STACKIT comes with two storage classes by default. @@ -176,8 +176,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) diff --git a/docs/docs/workflows/terminate.md b/docs/docs/workflows/terminate.md index 58c274bdd..2c45bebe3 100644 --- a/docs/docs/workflows/terminate.md +++ b/docs/docs/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-state.yaml constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/docs/workflows/terraform-provider.md b/docs/docs/workflows/terraform-provider.md index 8a3cedc62..c7a795d3f 100644 --- a/docs/docs/workflows/terraform-provider.md +++ b/docs/docs/workflows/terraform-provider.md @@ -21,8 +21,9 @@ This example shows how to set up a Constellation cluster with the reference IAM 2. Use one of the [example configurations for using the Constellation Terraform provider](https://github.com/edgelesssys/constellation/tree/main/terraform-provider-constellation/examples/full) or create a `main.tf` file and fill it with the resources you want to create. The [Constellation Terraform provider documentation](https://registry.terraform.io/providers/edgelesssys/constellation/latest) offers thorough documentation on the resources and their attributes. 3. Initialize and apply the Terraform configuration. - - + + + Initialize the providers and apply the configuration. ```bash @@ -31,10 +32,11 @@ This example shows how to set up a Constellation cluster with the reference IAM ``` Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - - - When creating a cluster on Azure, you need to manually patch the policy of the MAA provider before creating the Constellation cluster, as this feature isn't available in Azure's Terraform provider yet. The Constellation CLI provides a utility for patching, but you - can also do it manually. + + + +:::info +On SEV-SNP, you need to manually patch the policy of the MAA provider before creating the Constellation cluster, as this feature isn't available in Azure's Terraform provider yet. The Constellation CLI provides a utility for patching, but you can also do it manually. ```bash terraform init @@ -44,9 +46,7 @@ This example shows how to set up a Constellation cluster with the reference IAM terraform apply -target constellation_cluster.azure_example # adjust resource path if not using the example configuration ``` - Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - - Use the following policy if manually performing the patch. + Use the following policy if manually performing the patch. ``` version= 1.0; @@ -66,8 +66,20 @@ This example shows how to set up a Constellation cluster with the reference IAM }; ``` - - +::: + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + + Initialize the providers and apply the configuration. ```bash @@ -76,8 +88,8 @@ This example shows how to set up a Constellation cluster with the reference IAM ``` Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - - + + Initialize the providers and apply the configuration. ```bash @@ -86,9 +98,9 @@ This example shows how to set up a Constellation cluster with the reference IAM ``` Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - + - + 4. Connect to the cluster. ```bash diff --git a/docs/docs/workflows/troubleshooting.md b/docs/docs/workflows/troubleshooting.md index 3c952dddc..195bce1cc 100644 --- a/docs/docs/workflows/troubleshooting.md +++ b/docs/docs/workflows/troubleshooting.md @@ -40,6 +40,24 @@ Or alternatively, for `terminate`: ARM_SKIP_PROVIDER_REGISTRATION=true constellation terminate ``` +### Azure: Can't update attestation policy + +On Azure, you may receive the following error when running `apply` from within an Azure environment, e.g., an Azure VM: + +```shell-session +An error occurred: patching policies: updating attestation policy: unexpected status code: 403 Forbidden +``` + +The problem occurs because the Azure SDK we use internally attempts to [authenticate towards the Azure API with the managed identity of your current environment instead of the Azure CLI token](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential). + +We decided not to deviate from this behavior and comply with the ordering of credentials. + +A solution is to add the [required permissions](../getting-started/install.md#required-permissions) to the managed identity of your environment. For example, the managed identity of your Azure VM, instead of the account that you've authenticated with in the Azure CLI. + +If your setup requires a change in the ordering of credentials, please open an issue and explain your desired behavior. + + + ### Nodes fail to join with error `untrusted measurement value` This error indicates that a node's [attestation statement](../architecture/attestation.md) contains measurements that don't match the trusted values expected by the [JoinService](../architecture/microservices.md#joinservice). diff --git a/docs/docs/workflows/trusted-launch.md b/docs/docs/workflows/trusted-launch.md index 9bc7e785f..d6d01d8eb 100644 --- a/docs/docs/workflows/trusted-launch.md +++ b/docs/docs/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: diff --git a/docs/docs/workflows/upgrade.md b/docs/docs/workflows/upgrade.md index 7348c0dbc..3db2ecad6 100644 --- a/docs/docs/workflows/upgrade.md +++ b/docs/docs/workflows/upgrade.md @@ -1,6 +1,6 @@ # Upgrade your cluster -Constellation provides an easy way to upgrade all components of your cluster, without disrupting it's availability. +Constellation provides an easy way to upgrade all components of your cluster, without disrupting its availability. Specifically, you can upgrade the Kubernetes version, the nodes' image, and the Constellation microservices. You configure the desired versions in your local Constellation configuration and trigger upgrades with the `apply` command. To learn about available versions you use the `upgrade check` command. diff --git a/docs/docs/workflows/verify-cli.md b/docs/docs/workflows/verify-cli.md index 78341f314..e33569d37 100644 --- a/docs/docs/workflows/verify-cli.md +++ b/docs/docs/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -37,7 +37,7 @@ You don't need to verify the Constellation node images. This is done automatical This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. ::: -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/docs/workflows/verify-cluster.md b/docs/docs/workflows/verify-cluster.md index 20d416790..b6595ebf2 100644 --- a/docs/docs/workflows/verify-cluster.md +++ b/docs/docs/workflows/verify-cluster.md @@ -88,6 +88,7 @@ The `verify` command also allows you to verify any Constellation deployment that * The IP address of a running Constellation cluster's [VerificationService](../architecture/microservices.md#verificationservice). The `VerificationService` is exposed via a `NodePort` service using the external IP address of your cluster. Run `kubectl get nodes -o wide` and look for `EXTERNAL-IP`. * The cluster's *clusterID*. See [cluster identity](../architecture/keys.md#cluster-identity) for more details. +* A `constellation-conf.yaml` file with the expected measurements of the cluster in your working directory. For example: diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 2dc60e883..d5d220fdf 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -13,6 +13,7 @@ async function createConfig() { baseUrl: '/constellation/', onBrokenLinks: 'throw', onBrokenMarkdownLinks: 'throw', + onBrokenAnchors: 'throw', favicon: 'img/favicon.ico', // GitHub pages deployment config. @@ -22,9 +23,11 @@ async function createConfig() { // scripts scripts: [ - { src: 'https://plausible.io/js/plausible.js', async: true, defer: true, 'data-domain': 'docs.edgeless.systems' }, - { id: "Cookiebot", src: "https://consent.cookiebot.com/uc.js", "data-cbid": "a0cc864f-0b67-49be-8d65-9ed354de2ee6", "data-blockingmode": "auto" }, - { id: "CookieDeclaration", src: "https://consent.cookiebot.com/a0cc864f-0b67-49be-8d65-9ed354de2ee6/cd.js" } + { + src: '/constellation/gtagman.js', + async: true, + "data-cookieconsent": "ignore", + }, ], // Even if you don't use internalization, you can use this field to set useful @@ -58,10 +61,6 @@ async function createConfig() { theme: { customCss: require.resolve('./src/css/custom.css'), }, - gtag: { - trackingID: 'G-3DVYB2CHLG', - anonymizeIP: true, - } }), ], ], diff --git a/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 000000000..41c393918 --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,19659 @@ +{ + "name": "constellation-docs", + "version": "2.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "constellation-docs", + "version": "2.0.0", + "dependencies": { + "@cmfcmf/docusaurus-search-local": "1.2.0", + "@docusaurus/core": "3.6.2", + "@docusaurus/preset-classic": "3.6.2", + "@docusaurus/theme-mermaid": "3.6.2", + "@mdx-js/react": "3.1.0", + "asciinema-player": "3.8.1", + "clsx": "2.1.1", + "prism-react-renderer": "2.4.0", + "react": "18.3.1", + "react-dom": "18.3.1" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.6.2", + "@docusaurus/types": "3.6.2" + }, + "engines": { + "node": ">=16.14" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz", + "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", + "@algolia/autocomplete-shared": "1.17.7" + } + }, + "node_modules/@algolia/autocomplete-js": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-js/-/autocomplete-js-1.17.7.tgz", + "integrity": "sha512-4rCCg2B5x6GYzLfDZ3QipWydznbaMjoIwNSEbjpJ9cd/0+4nDpRWuBPxgOSsGmE4BFEor2iwQw4uCY6RrBdpjA==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.7", + "@algolia/autocomplete-preset-algolia": "1.17.7", + "@algolia/autocomplete-shared": "1.17.7", + "htm": "^3.1.1", + "preact": "^10.13.2" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.5.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz", + "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz", + "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz", + "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==", + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-theme-classic": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-theme-classic/-/autocomplete-theme-classic-1.17.7.tgz", + "integrity": "sha512-8sxnzRCPxyKZJxbG7EUpV/3AssQOjn+Zq/nvzks+BwbkAcpiLRBsXjvlIIsV4l36bZ+/Ri++ttAflGDPrRfn1A==", + "license": "MIT" + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz", + "integrity": "sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==", + "license": "MIT", + "dependencies": { + "@algolia/cache-common": "4.24.0" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.24.0.tgz", + "integrity": "sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==", + "license": "MIT" + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz", + "integrity": "sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==", + "license": "MIT", + "dependencies": { + "@algolia/cache-common": "4.24.0" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.15.0.tgz", + "integrity": "sha512-FaEM40iuiv1mAipYyiptP4EyxkJ8qHfowCpEeusdHUC4C7spATJYArD2rX3AxkVeREkDIgYEOuXcwKUbDCr7Nw==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-abtesting/node_modules/@algolia/client-common": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.15.0.tgz", + "integrity": "sha512-IofrVh213VLsDkPoSKMeM9Dshrv28jhDlBDLRcVJQvlL8pzue7PEB1EZ4UoJFYS3NSn7JOcJ/V+olRQzXlJj1w==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-abtesting/node_modules/@algolia/requester-browser-xhr": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.15.0.tgz", + "integrity": "sha512-Po/GNib6QKruC3XE+WKP1HwVSfCDaZcXu48kD+gwmtDlqHWKc7Bq9lrS0sNZ456rfCKhXksOmMfUs4wRM/Y96w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-abtesting/node_modules/@algolia/requester-node-http": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.15.0.tgz", + "integrity": "sha512-b1jTpbFf9LnQHEJP5ddDJKE2sAlhYd7EVSOWgzo/27n/SfCoHfqD0VWntnWYD83PnOKvfe8auZ2+xCb0TXotrQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.24.0.tgz", + "integrity": "sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.24.0.tgz", + "integrity": "sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.15.0.tgz", + "integrity": "sha512-bDDEQGfFidDi0UQUCbxXOCdphbVAgbVmxvaV75cypBTQkJ+ABx/Npw7LkFGw1FsoVrttlrrQbwjvUB6mLVKs/w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights/node_modules/@algolia/client-common": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.15.0.tgz", + "integrity": "sha512-IofrVh213VLsDkPoSKMeM9Dshrv28jhDlBDLRcVJQvlL8pzue7PEB1EZ4UoJFYS3NSn7JOcJ/V+olRQzXlJj1w==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights/node_modules/@algolia/requester-browser-xhr": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.15.0.tgz", + "integrity": "sha512-Po/GNib6QKruC3XE+WKP1HwVSfCDaZcXu48kD+gwmtDlqHWKc7Bq9lrS0sNZ456rfCKhXksOmMfUs4wRM/Y96w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights/node_modules/@algolia/requester-node-http": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.15.0.tgz", + "integrity": "sha512-b1jTpbFf9LnQHEJP5ddDJKE2sAlhYd7EVSOWgzo/27n/SfCoHfqD0VWntnWYD83PnOKvfe8auZ2+xCb0TXotrQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.24.0.tgz", + "integrity": "sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.15.0.tgz", + "integrity": "sha512-wu8GVluiZ5+il8WIRsGKu8VxMK9dAlr225h878GGtpTL6VBvwyJvAyLdZsfFIpY0iN++jiNb31q2C1PlPL+n/A==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions/node_modules/@algolia/client-common": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.15.0.tgz", + "integrity": "sha512-IofrVh213VLsDkPoSKMeM9Dshrv28jhDlBDLRcVJQvlL8pzue7PEB1EZ4UoJFYS3NSn7JOcJ/V+olRQzXlJj1w==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions/node_modules/@algolia/requester-browser-xhr": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.15.0.tgz", + "integrity": "sha512-Po/GNib6QKruC3XE+WKP1HwVSfCDaZcXu48kD+gwmtDlqHWKc7Bq9lrS0sNZ456rfCKhXksOmMfUs4wRM/Y96w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions/node_modules/@algolia/requester-node-http": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.15.0.tgz", + "integrity": "sha512-b1jTpbFf9LnQHEJP5ddDJKE2sAlhYd7EVSOWgzo/27n/SfCoHfqD0VWntnWYD83PnOKvfe8auZ2+xCb0TXotrQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==", + "license": "MIT" + }, + "node_modules/@algolia/ingestion": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.15.0.tgz", + "integrity": "sha512-MkqkAxBQxtQ5if/EX2IPqFA7LothghVyvPoRNA/meS2AW2qkHwcxjuiBxv4H6mnAVEPfJlhu9rkdVz9LgCBgJg==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion/node_modules/@algolia/client-common": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.15.0.tgz", + "integrity": "sha512-IofrVh213VLsDkPoSKMeM9Dshrv28jhDlBDLRcVJQvlL8pzue7PEB1EZ4UoJFYS3NSn7JOcJ/V+olRQzXlJj1w==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion/node_modules/@algolia/requester-browser-xhr": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.15.0.tgz", + "integrity": "sha512-Po/GNib6QKruC3XE+WKP1HwVSfCDaZcXu48kD+gwmtDlqHWKc7Bq9lrS0sNZ456rfCKhXksOmMfUs4wRM/Y96w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion/node_modules/@algolia/requester-node-http": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.15.0.tgz", + "integrity": "sha512-b1jTpbFf9LnQHEJP5ddDJKE2sAlhYd7EVSOWgzo/27n/SfCoHfqD0VWntnWYD83PnOKvfe8auZ2+xCb0TXotrQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/logger-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.24.0.tgz", + "integrity": "sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==", + "license": "MIT" + }, + "node_modules/@algolia/logger-console": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.24.0.tgz", + "integrity": "sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==", + "license": "MIT", + "dependencies": { + "@algolia/logger-common": "4.24.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.15.0.tgz", + "integrity": "sha512-QPrFnnGLMMdRa8t/4bs7XilPYnoUXDY8PMQJ1sf9ZFwhUysYYhQNX34/enoO0LBjpoOY6rLpha39YQEFbzgKyQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring/node_modules/@algolia/client-common": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.15.0.tgz", + "integrity": "sha512-IofrVh213VLsDkPoSKMeM9Dshrv28jhDlBDLRcVJQvlL8pzue7PEB1EZ4UoJFYS3NSn7JOcJ/V+olRQzXlJj1w==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring/node_modules/@algolia/requester-browser-xhr": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.15.0.tgz", + "integrity": "sha512-Po/GNib6QKruC3XE+WKP1HwVSfCDaZcXu48kD+gwmtDlqHWKc7Bq9lrS0sNZ456rfCKhXksOmMfUs4wRM/Y96w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring/node_modules/@algolia/requester-node-http": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.15.0.tgz", + "integrity": "sha512-b1jTpbFf9LnQHEJP5ddDJKE2sAlhYd7EVSOWgzo/27n/SfCoHfqD0VWntnWYD83PnOKvfe8auZ2+xCb0TXotrQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.24.0.tgz", + "integrity": "sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==", + "license": "MIT", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", + "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.24.0.tgz", + "integrity": "sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==", + "license": "MIT" + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.15.0.tgz", + "integrity": "sha512-rOZ+c0P7ajmccAvpeeNrUmEKoliYFL8aOR5qGW5pFq3oj3Iept7Y5mEtEsOBYsRt6qLnaXn4zUKf+N8nvJpcIw==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch/node_modules/@algolia/client-common": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.15.0.tgz", + "integrity": "sha512-IofrVh213VLsDkPoSKMeM9Dshrv28jhDlBDLRcVJQvlL8pzue7PEB1EZ4UoJFYS3NSn7JOcJ/V+olRQzXlJj1w==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", + "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.24.0.tgz", + "integrity": "sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==", + "license": "MIT", + "dependencies": { + "@algolia/cache-common": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-0.4.1.tgz", + "integrity": "sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^0.2.0", + "tinyexec": "^0.3.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@antfu/utils": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", + "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz", + "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz", + "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", + "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", + "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", + "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", + "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", + "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", + "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", + "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", + "license": "MIT", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", + "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", + "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", + "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.9.tgz", + "integrity": "sha512-Ncw2JFsJVuvfRsa2lSHiC55kETQVLSnsYGQ1JDDwkUeWGTL/8Tom8aLTnlqgoeuopWrbbGndrc9AlLYrIosrow==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz", + "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", + "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz", + "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz", + "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", + "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", + "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", + "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", + "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz", + "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", + "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.25.9", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.25.9", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.25.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.25.9", + "@babel/plugin-transform-typeof-symbol": "^7.25.9", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.9.tgz", + "integrity": "sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-react-display-name": "^7.25.9", + "@babel/plugin-transform-react-jsx": "^7.25.9", + "@babel/plugin-transform-react-jsx-development": "^7.25.9", + "@babel/plugin-transform-react-pure-annotations": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.0.tgz", + "integrity": "sha512-YXHu5lN8kJCb1LOb9PgV6pvak43X2h4HvRApcN5SdWeaItQOzfn1hgP6jasD6KWQyJDBxrVmA9o9OivlnNJK/w==", + "license": "MIT", + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.0.tgz", + "integrity": "sha512-o+UlMLt49RvtCASlOMW0AkHnabN9wR9rwCCherxO0yG4Npy34GkvrAqdXQvrhNs+jh+gkK8gB8Lf05qL/O7KWg==", + "license": "MIT" + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "license": "Apache-2.0" + }, + "node_modules/@cmfcmf/docusaurus-search-local": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@cmfcmf/docusaurus-search-local/-/docusaurus-search-local-1.2.0.tgz", + "integrity": "sha512-Tc0GhRBsfZAiB+f6BoPB8YCQap6JzzcDyJ0dLSCSzWQ6wdWvDlTBrHc1YqR8q8AZ+STRszL5eZpZFi5dbTCdYg==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-js": "^1.8.2", + "@algolia/autocomplete-theme-classic": "^1.8.2", + "@algolia/client-search": "^4.12.0", + "algoliasearch": "^4.12.0", + "cheerio": "^1.0.0-rc.9", + "clsx": "^1.1.1", + "lunr-languages": "^1.4.0", + "mark.js": "^8.11.1", + "tslib": "^2.6.3" + }, + "peerDependencies": { + "@docusaurus/core": "^2.0.0", + "nodejieba": "^2.5.0" + }, + "peerDependenciesMeta": { + "nodejieba": { + "optional": true + } + } + }, + "node_modules/@cmfcmf/docusaurus-search-local/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@csstools/cascade-layer-name-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.4.tgz", + "integrity": "sha512-7DFHlPuIxviKYZrOiwVU/PiHLm3lLUR23OMuEEtfEOQTOp9hzQ2JjdY6X5H18RVuUPJqSCI+qNnD5iOLMVE0bA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.1.tgz", + "integrity": "sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.0.tgz", + "integrity": "sha512-X69PmFOrjTZfN5ijxtI8hZ9kRADFSLrmmQ6hgDJ272Il049WGKpDY64KhrFm/7rbWve0z81QepawzjkKlqkNGw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.6.tgz", + "integrity": "sha512-S/IjXqTHdpI4EtzGoNCHfqraXF37x12ZZHA1Lk7zoT5pm2lMjFuqhX/89L7dqX4CcMacKK+6ZCs5TmEGb/+wKw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.1", + "@csstools/css-calc": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", + "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-5.0.1.tgz", + "integrity": "sha512-XOfhI7GShVcKiKwmPAnWSqd2tBR0uxt+runAxttbSp/LY2U16yAVPmAf7e9q4JJ0d+xMNmpwNDLBXnmRCl3HMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-cascade-layers/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@csstools/postcss-cascade-layers/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-4.0.6.tgz", + "integrity": "sha512-EcvXfC60cTIumzpsxWuvVjb7rsJEHPvqn3jeMEBUaE3JSc4FRuP7mEQ+1eicxWmIrs3FtzMH9gR3sgA5TH+ebQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.6", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-mix-function": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.6.tgz", + "integrity": "sha512-jVKdJn4+JkASYGhyPO+Wa5WXSx1+oUgaXb3JsjJn/BlrtFh5zjocCY7pwWi0nuP24V1fY7glQsxEYcYNy0dMFg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.6", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-content-alt-text": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.4.tgz", + "integrity": "sha512-YItlZUOuZJCBlRaCf8Aucc1lgN41qYGALMly0qQllrxYJhiyzlI6RxOTMUvtWk+KhS8GphMDsDhKQ7KTPfEMSw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-exponential-functions": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.5.tgz", + "integrity": "sha512-mi8R6dVfA2nDoKM3wcEi64I8vOYEgQVtVKCfmLHXupeLpACfGAided5ddMt5f+CnEodNu4DifuVwb0I6fQDGGQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.0", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-4.0.0.tgz", + "integrity": "sha512-usBzw9aCRDvchpok6C+4TXC57btc4bJtmKQWOHQxOVKen1ZfVqBUuCZ/wuqdX5GHsD0NRSr9XTP+5ID1ZZQBXw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-gamut-mapping": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.6.tgz", + "integrity": "sha512-0ke7fmXfc8H+kysZz246yjirAH6JFhyX9GTlyRnM0exHO80XcA9zeJpy5pOp5zo/AZiC/q5Pf+Hw7Pd6/uAoYA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.6", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-gradients-interpolation-method": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.6.tgz", + "integrity": "sha512-Itrbx6SLUzsZ6Mz3VuOlxhbfuyLTogG5DwEF1V8dAi24iMuvQPIHd7Ti+pNDp7j6WixndJGZaoNR0f9VSzwuTg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.6", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.6.tgz", + "integrity": "sha512-927Pqy3a1uBP7U8sTfaNdZVB0mNXzIrJO/GZ8us9219q9n06gOqCdfZ0E6d1P66Fm0fYHvxfDbfcUuwAn5UwhQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.6", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.0.tgz", + "integrity": "sha512-9QT5TDGgx7wD3EEMN3BSUG6ckb6Eh5gSPT5kZoVtUuAonfPmLDJyPhqR4ntPpMYhUKAMVKAg3I/AgzqHMSeLhA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-initial": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-initial/-/postcss-initial-2.0.0.tgz", + "integrity": "sha512-dv2lNUKR+JV+OOhZm9paWzYBXOCi+rJPqJ2cJuhh9xd8USVrd0cBEPczla81HNOyThMQWeCcdln3gZkQV2kYxA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.1.tgz", + "integrity": "sha512-JLp3POui4S1auhDR0n8wHd/zTOWmMsmK3nQd3hhL6FhWPaox5W7j1se6zXOG/aP07wV2ww0lxbKYGwbBszOtfQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-light-dark-function": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.7.tgz", + "integrity": "sha512-ZZ0rwlanYKOHekyIPaU+sVm3BEHCe+Ha0/px+bmHe62n0Uc1lL34vbwrLYn6ote8PHlsqzKeTQdIejQCJ05tfw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-float-and-clear": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-3.0.0.tgz", + "integrity": "sha512-SEmaHMszwakI2rqKRJgE+8rpotFfne1ZS6bZqBoQIicFyV+xT1UF42eORPxJkVJVrH9C0ctUgwMSn3BLOIZldQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-overflow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overflow/-/postcss-logical-overflow-2.0.0.tgz", + "integrity": "sha512-spzR1MInxPuXKEX2csMamshR4LRaSZ3UXVaRGjeQxl70ySxOhMpP2252RAFsg8QyyBXBzuVOOdx1+bVO5bPIzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-overscroll-behavior": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overscroll-behavior/-/postcss-logical-overscroll-behavior-2.0.0.tgz", + "integrity": "sha512-e/webMjoGOSYfqLunyzByZj5KKe5oyVg/YSbie99VEaSDE2kimFm0q1f6t/6Jo+VVCQ/jbe2Xy+uX+C4xzWs4w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-resize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-3.0.0.tgz", + "integrity": "sha512-DFbHQOFW/+I+MY4Ycd/QN6Dg4Hcbb50elIJCfnwkRTCX05G11SwViI5BbBlg9iHRl4ytB7pmY5ieAFk3ws7yyg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-viewport-units": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-3.0.3.tgz", + "integrity": "sha512-OC1IlG/yoGJdi0Y+7duz/kU/beCwO+Gua01sD6GtOtLi7ByQUpcIqs7UE/xuRPay4cHgOMatWdnDdsIDjnWpPw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-minmax": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.5.tgz", + "integrity": "sha512-sdh5i5GToZOIAiwhdntRWv77QDtsxP2r2gXW/WbLSCoLr00KTq/yiF1qlQ5XX2+lmiFa8rATKMcbwl3oXDMNew==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.0", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-3.0.4.tgz", + "integrity": "sha512-AnGjVslHMm5xw9keusQYvjVWvuS7KWK+OJagaG0+m9QnIjZsrysD2kJP/tr/UJIyYtMCtu8OkUd+Rajb4DqtIQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-4.0.0.tgz", + "integrity": "sha512-jMYDdqrQQxE7k9+KjstC3NbsmC063n1FTPLCgCRS2/qHUbHM0mNy9pIn4QIiQGs9I/Bg98vMqw7mJXBxa0N88A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.0.tgz", + "integrity": "sha512-HlEoG0IDRoHXzXnkV4in47dzsxdsjdz6+j7MLjaACABX2NfvjFS6XVAnpaDyGesz9gK2SC7MbNwdCHusObKJ9Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.6.tgz", + "integrity": "sha512-Hptoa0uX+XsNacFBCIQKTUBrFKDiplHan42X73EklG6XmQLG7/aIvxoNhvZ7PvOWMt67Pw3bIlUY2nD6p5vL8A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.6", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.0.0.tgz", + "integrity": "sha512-XQPtROaQjomnvLUSy/bALTR5VCtTVUFwYs1SblvYgLSeTo2a/bMNwUwo2piXw5rTv/FEYiy5yPSXBqg9OKUx7Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-random-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-random-function/-/postcss-random-function-1.0.1.tgz", + "integrity": "sha512-Ab/tF8/RXktQlFwVhiC70UNfpFQRhtE5fQQoP2pO+KCPGLsLdWFiOuHgSRtBOqEshCVAzR4H6o38nhvRZq8deA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.0", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-relative-color-syntax": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.6.tgz", + "integrity": "sha512-yxP618Xb+ji1I624jILaYM62uEmZcmbdmFoZHoaThw896sq0vU39kqTTF+ZNic9XyPtPMvq0vyvbgmHaszq8xg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.6", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-scope-pseudo-class": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-4.0.1.tgz", + "integrity": "sha512-IMi9FwtH6LMNuLea1bjVMQAsUhFxJnyLSgOp/cpv5hrzWmrUYU5fm0EguNDIIOHUqzXode8F/1qkC/tEo/qN8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-scope-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/postcss-sign-functions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.0.tgz", + "integrity": "sha512-SLcc20Nujx/kqbSwDmj6oaXgpy3UjFhBy1sfcqPgDkHfOIfUtUVH7OXO+j7BU4v/At5s61N5ZX6shvgPwluhsA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.0", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.5.tgz", + "integrity": "sha512-G6SJ6hZJkhxo6UZojVlLo14MohH4J5J7z8CRBrxxUYy9JuZiIqUo5TBYyDGcE0PLdzpg63a7mHSJz3VD+gMwqw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.0", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.1.tgz", + "integrity": "sha512-xPZIikbx6jyzWvhms27uugIc0I4ykH4keRvoa3rxX5K7lEhkbd54rjj/dv60qOCTisoS+3bmwJTeyV1VNBrXaw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/color-helpers": "^5.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.5.tgz", + "integrity": "sha512-/YQThYkt5MLvAmVu7zxjhceCYlKrYddK6LEmK5I4ojlS6BmO9u2yO4+xjXzu2+NPYmHSTtP4NFSamBCMmJ1NJA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-calc": "^2.1.0", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-4.0.0.tgz", + "integrity": "sha512-cBz3tOCI5Fw6NIFEwU3RiwK6mn3nKegjpJuzCndoGq3BZPkUjnsq7uQmIeMNeMbMk7YD2MfKcgCpZwX5jyXqCA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/utilities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-2.0.0.tgz", + "integrity": "sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.0.tgz", + "integrity": "sha512-pieeipSOW4sQ0+bE5UFC51AOZp9NGxg89wAlZ1BAQFaiRAGK1IKUaPQ0UGZeNctJXyqZ1UvBtOQh2HH+U5GtmA==", + "license": "MIT" + }, + "node_modules/@docsearch/react": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.0.tgz", + "integrity": "sha512-WnFK720+iwTVt94CxY3u+FgX6exb3BfN5kE9xUY6uuAH/9W/UFboBZFLlrw/zxFRHoHZCOXRtOylsXF+6LHI+Q==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.7", + "@algolia/autocomplete-preset-algolia": "1.17.7", + "@docsearch/css": "3.8.0", + "algoliasearch": "^5.12.0" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/client-analytics": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.15.0.tgz", + "integrity": "sha512-lho0gTFsQDIdCwyUKTtMuf9nCLwq9jOGlLGIeQGKDxXF7HbiAysFIu5QW/iQr1LzMgDyM9NH7K98KY+BiIFriQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/client-common": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.15.0.tgz", + "integrity": "sha512-IofrVh213VLsDkPoSKMeM9Dshrv28jhDlBDLRcVJQvlL8pzue7PEB1EZ4UoJFYS3NSn7JOcJ/V+olRQzXlJj1w==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/client-personalization": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.15.0.tgz", + "integrity": "sha512-LfaZqLUWxdYFq44QrasCDED5bSYOswpQjSiIL7Q5fYlefAAUO95PzBPKCfUhSwhb4rKxigHfDkd81AvEicIEoA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/client-search": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.15.0.tgz", + "integrity": "sha512-Z32gEMrRRpEta5UqVQA612sLdoqY3AovvUPClDfMxYrbdDAebmGDVPtSogUba1FZ4pP5dx20D3OV3reogLKsRA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/recommend": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.15.0.tgz", + "integrity": "sha512-5eupMwSqMLDObgSMF0XG958zR6GJP3f7jHDQ3/WlzCM9/YIJiWIUoJFGsko9GYsA5xbLDHE/PhWtq4chcCdaGQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/requester-browser-xhr": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.15.0.tgz", + "integrity": "sha512-Po/GNib6QKruC3XE+WKP1HwVSfCDaZcXu48kD+gwmtDlqHWKc7Bq9lrS0sNZ456rfCKhXksOmMfUs4wRM/Y96w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/requester-node-http": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.15.0.tgz", + "integrity": "sha512-b1jTpbFf9LnQHEJP5ddDJKE2sAlhYd7EVSOWgzo/27n/SfCoHfqD0VWntnWYD83PnOKvfe8auZ2+xCb0TXotrQ==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@docsearch/react/node_modules/algoliasearch": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.15.0.tgz", + "integrity": "sha512-Yf3Swz1s63hjvBVZ/9f2P1Uu48GjmjCN+Esxb6MAONMGtZB1fRX8/S1AhUTtsuTlcGovbYLxpHgc7wEzstDZBw==", + "license": "MIT", + "dependencies": { + "@algolia/client-abtesting": "5.15.0", + "@algolia/client-analytics": "5.15.0", + "@algolia/client-common": "5.15.0", + "@algolia/client-insights": "5.15.0", + "@algolia/client-personalization": "5.15.0", + "@algolia/client-query-suggestions": "5.15.0", + "@algolia/client-search": "5.15.0", + "@algolia/ingestion": "1.15.0", + "@algolia/monitoring": "1.15.0", + "@algolia/recommend": "5.15.0", + "@algolia/requester-browser-xhr": "5.15.0", + "@algolia/requester-fetch": "5.15.0", + "@algolia/requester-node-http": "5.15.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@docusaurus/babel": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.6.2.tgz", + "integrity": "sha512-v8N8TWGXDsb5sxQC3Rcqb1CZr0LlU1OgqqVBUchN6cpIUr7EJuVJs5eHcIu5Ag8mwO/hWN3f7FE9uaHTMapAbg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.25.9", + "@babel/preset-env": "^7.25.9", + "@babel/preset-react": "^7.25.9", + "@babel/preset-typescript": "^7.25.9", + "@babel/runtime": "^7.25.9", + "@babel/runtime-corejs3": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@docusaurus/logger": "3.6.2", + "@docusaurus/utils": "3.6.2", + "babel-plugin-dynamic-import-node": "^2.3.3", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/bundler": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.6.2.tgz", + "integrity": "sha512-YkEifEVs4lV931SrHBB4n6WqRowMw+aM/QPH3z8aU+5t1dWa+1p2OPqARS+tSbh3la9ns+L1zIfSbd8RHi2/PQ==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.9", + "@docusaurus/babel": "3.6.2", + "@docusaurus/cssnano-preset": "3.6.2", + "@docusaurus/logger": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils": "3.6.2", + "babel-loader": "^9.2.1", + "clean-css": "^5.3.2", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.8.1", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "file-loader": "^6.2.0", + "html-minifier-terser": "^7.2.0", + "mini-css-extract-plugin": "^2.9.1", + "null-loader": "^4.0.1", + "postcss": "^8.4.26", + "postcss-loader": "^7.3.3", + "postcss-preset-env": "^10.1.0", + "react-dev-utils": "^12.0.1", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.95.0", + "webpackbar": "^6.0.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/faster": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } + } + }, + "node_modules/@docusaurus/core": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.6.2.tgz", + "integrity": "sha512-irMts/mGLZv8dWcy0WUtbY/U6b5qIfHgQd1/kXMyAxUJo99fL0wFSqhMI+tcxjk0HYy427MXerLMqFJj+Arg1w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.6.2", + "@docusaurus/bundler": "3.6.2", + "@docusaurus/logger": "3.6.2", + "@docusaurus/mdx-loader": "3.6.2", + "@docusaurus/utils": "3.6.2", + "@docusaurus/utils-common": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "core-js": "^3.31.1", + "del": "^6.1.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "fs-extra": "^11.1.1", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.6.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "p-map": "^4.0.0", + "prompts": "^2.4.2", + "react-dev-utils": "^12.0.1", + "react-helmet-async": "^1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "rtl-detect": "^1.0.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.6", + "shelljs": "^0.8.5", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "^4.15.2", + "webpack-merge": "^6.0.1" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/cssnano-preset": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.6.2.tgz", + "integrity": "sha512-mBkVa4QMHRwCFCVLYdBlOZuAT1iVVsS7GGSgliSVAeTOagP/AbtlBsCVrBs+keEuDuRF1w/6QEcqDoZe9fa5pw==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.4.38", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/logger": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.6.2.tgz", + "integrity": "sha512-1p4IQhhgLyIfsey4UAdAIW69aUE1Ei6O91Nsw30ryZeDWSG5dh4o3zaRGOLxfAX69Ac/yDm6YCwJOafUxL6Vxg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/mdx-loader": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.6.2.tgz", + "integrity": "sha512-7fbRmNgF3CR96Ja82Ya0/Cdu1OL9UJ/22llNMY8lr5gAbw718Y5ryXMVRIYn0JNLTiSxzgtvW4DIsUWEB8NMpw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.6.2", + "@docusaurus/utils": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^1.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/module-type-aliases": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.6.2.tgz", + "integrity": "sha512-NrJkL2rLTCjHtWOqUvWzwqvJrsKLj0gVJeV6q5yeKdKKgItietcTf2fTRkM9LHKSUN8CBDXxwHABeQvTahvmXQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.6.2", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "*", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@docusaurus/plugin-content-blog": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.6.2.tgz", + "integrity": "sha512-6bJxr6Or4NslEVH3BJuPH30kUWiqUjDRdGPhvxpHmt9W/RY2/6u72WICG3bW3dLFxJ/2uDLBU92lHnatpvo7Ew==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/logger": "3.6.2", + "@docusaurus/mdx-loader": "3.6.2", + "@docusaurus/theme-common": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils": "3.6.2", + "@docusaurus/utils-common": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "cheerio": "1.0.0-rc.12", + "feed": "^4.2.2", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "reading-time": "^1.5.0", + "srcset": "^4.0.0", + "tslib": "^2.6.0", + "unist-util-visit": "^5.0.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.6.2.tgz", + "integrity": "sha512-e6WW1g10RIXXLN/rrtqTi/FyJ1Hj3X9Mmgz4V11/0pDCxIGGI8m4ocbAglUlLtgvbLD5viNLefl/NwbOW3JXiQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/logger": "3.6.2", + "@docusaurus/mdx-loader": "3.6.2", + "@docusaurus/module-type-aliases": "3.6.2", + "@docusaurus/theme-common": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils": "3.6.2", + "@docusaurus/utils-common": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", + "fs-extra": "^11.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.6.2.tgz", + "integrity": "sha512-fo4NyGkw10lYHyHaTxE6TZLYnxNtCfRHeZkNK1N9pBYqe7TT2dBUNAEeVW2U3ed9m6YuB7JKSQsa++GGmcP+6g==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/mdx-loader": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.6.2.tgz", + "integrity": "sha512-T/eS3VvHElpeV5S8uwp7Si4ujEynmgFtJLvA2CSa5pzQuOF1EEghF9nekAIj0cWtDHsqNUDZNr8hK1brivFXSg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils": "3.6.2", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^1.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.6.2.tgz", + "integrity": "sha512-B7ihrr3wz8e4XqW+dIAtq844u3Z83u5CeiL1xrCqzFH+vDCjUZHTamS3zKXNcgi6YVVe6hUQXPG15ltaqQaVPQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.6.2.tgz", + "integrity": "sha512-V8ijI6qddAAkJ0vd8sjZ7S/apRTLJn9dAwvj/rSMd93witGdKINemL+9TyfLkhcXKTxyqRT8zKdu8ewjPXqKHg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "@types/gtag.js": "^0.0.12", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.6.2.tgz", + "integrity": "sha512-fnWQ5FdN9f8c8VTgjaQ98208Y+d/JjHhD506rWIIL9rt1cJOf29XElxvOeKpMJadfkgY5KLZSAiHkGt+4qgN4g==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.6.2.tgz", + "integrity": "sha512-qcAQAP1Ot0dZpeRoJ0L/Zck5FVDkll2IleVZQLzxeRVDZIw1P9/TK7/Aw1w2pmH7dmw/Cwk/cLSVRvLAmp9k7A==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/logger": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils": "3.6.2", + "@docusaurus/utils-common": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/preset-classic": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.6.2.tgz", + "integrity": "sha512-r2n5eHdhiNSrJGsrrYcw+WsyStmXxe0ZG3RdA9LVyK5+jBHM8blrUWJEDugnzCNbyhUzhdtcmgCC9fhdAvKuQw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/plugin-content-blog": "3.6.2", + "@docusaurus/plugin-content-docs": "3.6.2", + "@docusaurus/plugin-content-pages": "3.6.2", + "@docusaurus/plugin-debug": "3.6.2", + "@docusaurus/plugin-google-analytics": "3.6.2", + "@docusaurus/plugin-google-gtag": "3.6.2", + "@docusaurus/plugin-google-tag-manager": "3.6.2", + "@docusaurus/plugin-sitemap": "3.6.2", + "@docusaurus/theme-classic": "3.6.2", + "@docusaurus/theme-common": "3.6.2", + "@docusaurus/theme-search-algolia": "3.6.2", + "@docusaurus/types": "3.6.2" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-classic": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.6.2.tgz", + "integrity": "sha512-bCdOPqPNezhLx+hgNVO2Cf+8/1AHa9uHDOqTx/CKAx2I0J/jV9G+6JiMtpSRKGNfBoLT1O+56/7+WtkOf54xTw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/logger": "3.6.2", + "@docusaurus/mdx-loader": "3.6.2", + "@docusaurus/module-type-aliases": "3.6.2", + "@docusaurus/plugin-content-blog": "3.6.2", + "@docusaurus/plugin-content-docs": "3.6.2", + "@docusaurus/plugin-content-pages": "3.6.2", + "@docusaurus/theme-common": "3.6.2", + "@docusaurus/theme-translations": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils": "3.6.2", + "@docusaurus/utils-common": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.45", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.4.26", + "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-common": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.6.2.tgz", + "integrity": "sha512-lfgsL064KEHpCkgGUc0OYoUPCpYfzggp6Hof8sz59UuKiLvb/Z7raewE9/NfocrJ2HZI17rLgMX3SQlRDh/5gg==", + "license": "MIT", + "dependencies": { + "@docusaurus/mdx-loader": "3.6.2", + "@docusaurus/module-type-aliases": "3.6.2", + "@docusaurus/utils": "3.6.2", + "@docusaurus/utils-common": "3.6.2", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^2.0.0", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^2.3.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-mermaid": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.6.2.tgz", + "integrity": "sha512-Ui+rBtqMPKj3RCOxNlY04i1tEjNg+fZg4URTvkHmYR07hcKaJw+vkw+wlaYjd0HFZk+3Er9vUAcwsCWuea4cVQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.2", + "@docusaurus/module-type-aliases": "3.6.2", + "@docusaurus/theme-common": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "mermaid": ">=10.4", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.6.2.tgz", + "integrity": "sha512-SFLS+Rq8Cg2yepnHucA9sRpIR97yHvZWlCgMzBLunV3KHbB6hD2h5HPhFV39wYHYCjJUAOH1lX9poJ1qKYuSvg==", + "license": "MIT", + "dependencies": { + "@docsearch/react": "^3.5.2", + "@docusaurus/core": "3.6.2", + "@docusaurus/logger": "3.6.2", + "@docusaurus/plugin-content-docs": "3.6.2", + "@docusaurus/theme-common": "3.6.2", + "@docusaurus/theme-translations": "3.6.2", + "@docusaurus/utils": "3.6.2", + "@docusaurus/utils-validation": "3.6.2", + "algoliasearch": "^4.18.0", + "algoliasearch-helper": "^3.13.3", + "clsx": "^2.0.0", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-translations": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.6.2.tgz", + "integrity": "sha512-LIWrYoDUsOTKmb0c7IQzawiPUTAaczBs5IOx6srxOWoTHVUMLzJCkl5Y6whfuRrnul8G05qv2vk238bN5Ko62g==", + "license": "MIT", + "dependencies": { + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/types": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.6.2.tgz", + "integrity": "sha512-117Wsk6xXrWEAsCYCXS3TGJv5tkdIZDcd7T/V0UJvKYmY0gyVPPcEQChy8yTdjbIkbB2q4fa7Jpox72Qv86mqQ==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.95.0", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/types/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docusaurus/utils": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.6.2.tgz", + "integrity": "sha512-oxnpUcFZGE3uPCDoXr8GJriB3VWM9sFjPedFidX3Fsz87l1NZNc1wtbKPfQ7GYFDMYo2IGlAv5+47Me9RkM6lg==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.6.2", + "@docusaurus/types": "3.6.2", + "@docusaurus/utils-common": "3.6.2", + "@svgr/webpack": "^8.1.0", + "escape-string-regexp": "^4.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/utils-common": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.6.2.tgz", + "integrity": "sha512-dr5wK+OyU2QAWxG7S5siD2bPgS7+ZeqWHfgLNHZ5yalaZf8TbeNNLqydfngukAY56BGZN0NbMkX6jGIr7ZF0sA==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.6.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/utils-validation": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.6.2.tgz", + "integrity": "sha512-Y3EwblDz72KOcobb5t2zlhHSmrfE8EaHusPJ96Kx2JYtNXL2omqCoOb6FpaXWhES75wvjUpkFLYfiNqAqEov8g==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.6.2", + "@docusaurus/utils": "3.6.2", + "@docusaurus/utils-common": "3.6.2", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "2.1.33", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.1.33.tgz", + "integrity": "sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^0.4.0", + "@antfu/utils": "^0.7.10", + "@iconify/types": "^2.0.0", + "debug": "^4.3.6", + "kolorist": "^1.8.0", + "local-pkg": "^0.5.0", + "mlly": "^1.7.1" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "license": "MIT" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", + "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", + "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "license": "MIT", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@mermaid-js/parser": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.3.0.tgz", + "integrity": "sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA==", + "license": "MIT", + "dependencies": { + "langium": "3.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "license": "ISC" + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", + "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.28", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", + "license": "MIT" + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@slorber/remark-comment": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", + "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.1.0", + "micromark-util-symbol": "^1.0.1" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "license": "MIT", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", + "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==", + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==", + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz", + "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==", + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==", + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "license": "MIT", + "dependencies": { + "@types/trusted-types": "*" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", + "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==", + "license": "MIT" + }, + "node_modules/@types/gtag.js": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", + "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==", + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "license": "MIT" + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "license": "MIT" + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.15", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", + "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.1.tgz", + "integrity": "sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prismjs": { + "version": "1.26.5", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.5.tgz", + "integrity": "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.9.17", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", + "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-config": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", + "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "^5.1.0" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "license": "ISC" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "license": "Apache-2.0" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/algoliasearch": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", + "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", + "license": "MIT", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-account": "4.24.0", + "@algolia/client-analytics": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-personalization": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/recommend": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/algoliasearch-helper": { + "version": "3.22.5", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.5.tgz", + "integrity": "sha512-lWvhdnc+aKOKx8jyA3bsdEgHzm/sglC4cYdMG4xSQyRiPLJVJtH/IVYZG3Hp6PkTEhQqhyVYkeP9z2IlcHJsWw==", + "license": "MIT", + "dependencies": { + "@algolia/events": "^4.0.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asciinema-player": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.8.1.tgz", + "integrity": "sha512-NkpbFg81Y6iJFpDRndakLCQ0G26XSpvuT3vJTFjMRgHb26lqHgRNY9gun54e5MehZ4fEDNYkMZv+z6MfZ8c2aA==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.21.0", + "solid-js": "^1.3.0" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/babel-loader": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "license": "MIT", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "license": "MIT", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", + "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.3", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", + "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "license": "MIT" + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/bonjour-service": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/boxen": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", + "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^6.2.0", + "chalk": "^4.1.2", + "cli-boxes": "^3.0.0", + "string-width": "^5.0.1", + "type-fest": "^2.5.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001680", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", + "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/combine-promises": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.2.0.tgz", + "integrity": "sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "license": "ISC" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compressible/node_modules/mime-db": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", + "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.0.2", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/configstore": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", + "license": "BSD-2-Clause", + "dependencies": { + "dot-prop": "^6.0.1", + "graceful-fs": "^4.2.6", + "unique-string": "^3.0.0", + "write-file-atomic": "^3.0.3", + "xdg-basedir": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/yeoman/configstore?sponsor=1" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/copy-text-to-clipboard": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz", + "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz", + "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.39.0.tgz", + "integrity": "sha512-7fEcWwKI4rJinnK+wLTezeg2smbFFdSBP6E2kQZNbnzM2s1rpKQ6aaRteZSSg7FLU3P0HGGVo/gbpfanU36urg==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "license": "MIT", + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-blank-pseudo": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-7.0.1.tgz", + "integrity": "sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-blank-pseudo/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-declaration-sorter": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", + "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", + "license": "ISC", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-7.0.1.tgz", + "integrity": "sha512-EOcoyJt+OsuKfCADgLT7gADZI5jMzIe/AeI6MeAYKiFBDmNmM7kk46DtSfMj5AohUJisqVzopBpnQTlvbyaBWg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-has-pseudo/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/css-has-pseudo/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz", + "integrity": "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "cssnano": "^6.0.1", + "jest-worker": "^29.4.3", + "postcss": "^8.4.24", + "schema-utils": "^4.0.1", + "serialize-javascript": "^6.0.1" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "lightningcss": { + "optional": true + } + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-10.0.0.tgz", + "integrity": "sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssdb": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.2.1.tgz", + "integrity": "sha512-KwEPys7lNsC8OjASI8RrmwOYYDcm0JOW9zQhcV83ejYcQkirTEyeAGui8aO2F5PiS6SLpxuTzl6qlMElIdsgIg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ], + "license": "MIT-0" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", + "integrity": "sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==", + "license": "MIT", + "dependencies": { + "cssnano-preset-default": "^6.1.2", + "lilconfig": "^3.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-advanced": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz", + "integrity": "sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==", + "license": "MIT", + "dependencies": { + "autoprefixer": "^10.4.19", + "browserslist": "^4.23.0", + "cssnano-preset-default": "^6.1.2", + "postcss-discard-unused": "^6.0.5", + "postcss-merge-idents": "^6.0.3", + "postcss-reduce-idents": "^6.0.3", + "postcss-zindex": "^6.0.2" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-default": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", + "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^4.0.2", + "postcss-calc": "^9.0.1", + "postcss-colormin": "^6.1.0", + "postcss-convert-values": "^6.1.0", + "postcss-discard-comments": "^6.0.2", + "postcss-discard-duplicates": "^6.0.3", + "postcss-discard-empty": "^6.0.3", + "postcss-discard-overridden": "^6.0.2", + "postcss-merge-longhand": "^6.0.5", + "postcss-merge-rules": "^6.1.1", + "postcss-minify-font-values": "^6.1.0", + "postcss-minify-gradients": "^6.0.3", + "postcss-minify-params": "^6.1.0", + "postcss-minify-selectors": "^6.0.4", + "postcss-normalize-charset": "^6.0.2", + "postcss-normalize-display-values": "^6.0.2", + "postcss-normalize-positions": "^6.0.2", + "postcss-normalize-repeat-style": "^6.0.2", + "postcss-normalize-string": "^6.0.2", + "postcss-normalize-timing-functions": "^6.0.2", + "postcss-normalize-unicode": "^6.1.0", + "postcss-normalize-url": "^6.0.2", + "postcss-normalize-whitespace": "^6.0.2", + "postcss-ordered-values": "^6.0.2", + "postcss-reduce-initial": "^6.1.0", + "postcss-reduce-transforms": "^6.0.2", + "postcss-svgo": "^6.0.3", + "postcss-unique-selectors": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-utils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", + "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/cytoscape": { + "version": "3.30.3", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.3.tgz", + "integrity": "sha512-HncJ9gGJbVtw7YXtIs3+6YAFSSiKsom0amWc33Z7QbylbY2JGMrA0yz4EwrdTScZxnwclXeEZHzO5pxoy0ZE4g==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz", + "integrity": "sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "license": "BSD-2-Clause", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "license": "MIT", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT" + }, + "node_modules/detect-port": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "license": "MIT", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz", + "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==", + "license": "(MPL-2.0 OR Apache-2.0)" + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.63", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.63.tgz", + "integrity": "sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/emoticon": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-4.1.0.tgz", + "integrity": "sha512-VWZfnxqwNcc51hIy/sbOdEem6D+cVtpPzEEtVAFdaas30+1dgkyaOQ4sQ6Bp0tOMqWO1v+HQfYaoodOkdhK6SQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "license": "MIT" + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-value-to-estree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.2.1.tgz", + "integrity": "sha512-Vt2UOjyPbNQQgT5eJh+K5aATti0OjCIAGc9SgMdOFYbohuifsWclR74l0iZTJwePMgWYdX1hlVS+dedH9XV8kw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eta": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-2.2.0.tgz", + "integrity": "sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", + "dependencies": { + "@types/node": "*", + "require-like": ">= 0.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" + }, + "node_modules/express/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "license": "MIT", + "dependencies": { + "xml-js": "^1.6.11" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/file-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/file-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "license": "MIT", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "license": "MIT", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "license": "MIT", + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "license": "Unlicense" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "license": "ISC" + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", + "license": "ISC" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "license": "MIT", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/got/node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT" + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-yarn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", + "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.2.tgz", + "integrity": "sha512-SfMzfdAi/zAoZ1KkFEyyeXBn7u/ShQrfd675ZEE9M3qj+PMFX05xubzRyF76CCSJu8au9jgVxDV1+okFvgZU4A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^6.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz", + "integrity": "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^0.4.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree/node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", + "license": "MIT" + }, + "node_modules/hast-util-to-estree/node_modules/style-to-object": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", + "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.2.tgz", + "integrity": "sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.0.tgz", + "integrity": "sha512-jzaLBGavEDKHrc5EfFImKN7nZKKBdSLIdGvCwDZ9TfzbF2ffXiov8CKE445L2Z1Ek2t/m4SKQ2j6Ipv7NyUolw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/htm": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz", + "integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==", + "license": "Apache-2.0" + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "license": "MIT" + }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", + "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==", + "license": "MIT", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/html-webpack-plugin/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "license": "MIT" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", + "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "license": "MIT", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/infima": { + "version": "0.2.0-alpha.45", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.45.tgz", + "integrity": "sha512-uyH0zfr1erU1OohLk0fT4Rrb94AOhguWNOcD9uGrSpRvNB+6gZXUoJX5J0NtvzBO10YZ9PgvA4NFgt+fYg8ojw==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "license": "MIT" + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "license": "MIT", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", + "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", + "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/katex": { + "version": "0.16.11", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz", + "integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "license": "MIT" + }, + "node_modules/langium": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.0.0.tgz", + "integrity": "sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg==", + "license": "MIT", + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/latest-version": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", + "license": "MIT", + "dependencies": { + "package-json": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/launch-editor": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", + "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/local-pkg": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", + "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", + "license": "MIT", + "dependencies": { + "mlly": "^1.7.3", + "pkg-types": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "license": "MIT" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lunr-languages": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/lunr-languages/-/lunr-languages-1.14.0.tgz", + "integrity": "sha512-hWUAb2KqM3L7J5bcrngszzISY4BxrXn/Xhbb9TTCJYEGqlR1nG67/M14sp09+PTIRklobrn57IAxcdcO/ZFyNA==", + "license": "MPL-1.1" + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "license": "MIT" + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/marked": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", + "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mdast-util-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", + "integrity": "sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mdast-util-frontmatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", + "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "escape-string-regexp": "^5.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", + "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "license": "CC0-1.0" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "license": "Unlicense", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/mermaid": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.4.0.tgz", + "integrity": "sha512-mxCfEYvADJqOiHfGpJXLs4/fAjHz448rH0pfY5fAoxiz70rQiDSzUUy4dNET2T08i46IVpjohPd6WWbzmRHiPA==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.0.1", + "@iconify/utils": "^2.1.32", + "@mermaid-js/parser": "^0.3.0", + "@types/d3": "^7.4.3", + "@types/dompurify": "^3.0.5", + "cytoscape": "^3.29.2", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.11", + "dayjs": "^1.11.10", + "dompurify": "^3.0.11 <3.1.7", + "katex": "^0.16.9", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^13.0.2", + "roughjs": "^4.6.6", + "stylis": "^4.3.1", + "ts-dedent": "^2.2.0", + "uuid": "^9.0.1" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.1.tgz", + "integrity": "sha512-eBPdkcoCNvYcxQOAKAlceo5SNdzZWfF+FcSupREAzdAh9rRmE239CEQAiTwIgblwnoM8zzj35sZ5ZwvSEOF6Kw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.2.tgz", + "integrity": "sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-directive": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", + "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", + "license": "MIT", + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz", + "integrity": "sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.1.tgz", + "integrity": "sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg==", + "license": "MIT", + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.2.tgz", + "integrity": "sha512-5E5I2pFzJyg2CtemqAbcyCktpHXuJbABnsb32wX2U8IQKhhVFBqkcZR5LRm1WVoFqa4kTueZK4abep7wdo9nrw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-space/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-character/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz", + "integrity": "sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-events-to-acorn/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-normalize-identifier/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.3.tgz", + "integrity": "sha512-VXJJuNxYWSoYL6AJ6OQECCFGhIU2GGHMw8tahogePBrjkG8aCCas3ibkp7RnVOSTClg2is05/R7maAhF1XyQMg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.1.tgz", + "integrity": "sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "license": "MIT", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", + "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", + "license": "MIT", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mlly": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz", + "integrity": "sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==", + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^1.1.2", + "pkg-types": "^1.2.1", + "ufo": "^1.5.4" + } + }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-emoji": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", + "integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==", + "license": "MIT" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/null-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/null-loader/-/null-loader-4.0.1.tgz", + "integrity": "sha512-pxqVbi4U6N26lq+LmgIbB5XATP0VdZKOG25DhHi8btMmJJefGArFyDg1yc4U3hWCJbMqSrw0qyrz1UQX+qYXqg==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/null-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/null-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/null-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/null-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "license": "MIT", + "dependencies": { + "got": "^12.1.0", + "registry-auth-token": "^5.0.1", + "registry-url": "^6.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.4.tgz", + "integrity": "sha512-H/OUu9/zUfP89z1APcBf2X8Us0tt8dUK4lUmKqz12QNXif3DxAs1/YqjGtcutZi1zQqeNQRWr9C+EbQnnvSSFA==", + "license": "MIT" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==", + "license": "ISC" + }, + "node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "license": "MIT", + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "license": "(WTFPL OR MIT)" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "license": "MIT", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "license": "MIT", + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-types": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz", + "integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.2", + "pathe": "^1.1.2" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-7.0.1.tgz", + "integrity": "sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-attribute-case-insensitive/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-calc": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", + "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.6.tgz", + "integrity": "sha512-wLXvm8RmLs14Z2nVpB4CWlnvaWPRcOZFltJSlcbYwSJ1EDZKsKDhPKIMecCnuU054KSmlmubkqczmm6qBPCBhA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.6", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-10.0.0.tgz", + "integrity": "sha512-1kervM2cnlgPs2a8Vt/Qbe5cQ++N7rkYo/2rz2BkqJZIHQwaVuJgQH38REHrAi4uM0b1fqxMkWYmese94iMp3w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-10.0.0.tgz", + "integrity": "sha512-JFta737jSP+hdAIEhk1Vs0q0YF5P8fFcj+09pweS8ktuGuZ8pPlykHsk6mPxZ8awDl4TrcxUqJo9l1IhVr/OjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-colormin": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz", + "integrity": "sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "colord": "^2.9.3", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-convert-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz", + "integrity": "sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-custom-media": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-11.0.5.tgz", + "integrity": "sha512-SQHhayVNgDvSAdX9NQ/ygcDQGEY+aSF4b/96z7QUX6mqL5yl/JgG/DywcF6fW9XbnCRE+aVYk+9/nqGuzOPWeQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/cascade-layer-name-parser": "^2.0.4", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-properties": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.4.tgz", + "integrity": "sha512-QnW8FCCK6q+4ierwjnmXF9Y9KF8q0JkbgVfvQEMa93x1GT8FvOiUevWCN2YLaOWyByeDX8S6VFbZEeWoAoXs2A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/cascade-layer-name-parser": "^2.0.4", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-8.0.4.tgz", + "integrity": "sha512-ASOXqNvDCE0dAJ/5qixxPeL1aOVGHGW2JwSy7HyjWNbnWTQCl+fDc968HY1jCmZI0+BaYT5CxsOiUhavpG/7eg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/cascade-layer-name-parser": "^2.0.4", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-selectors/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-9.0.1.tgz", + "integrity": "sha512-tRBEK0MHYvcMUrAuYMEOa0zg9APqirBcgzi6P21OhxtJyJADo/SWBwY1CAwEohQ/6HDaa9jCjLRG7K3PVQYHEA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-dir-pseudo-class/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-discard-comments": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz", + "integrity": "sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz", + "integrity": "sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-empty": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz", + "integrity": "sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz", + "integrity": "sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-unused": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz", + "integrity": "sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.0.tgz", + "integrity": "sha512-JkIGah3RVbdSEIrcobqj4Gzq0h53GG4uqDPsho88SgY84WnpkTpI0k50MFK/sX7XqVisZ6OqUfFnoUO6m1WWdg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-10.0.1.tgz", + "integrity": "sha512-U58wyjS/I1GZgjRok33aE8juW9qQgQUNwTSdxQGuShHzwuYdcklnvK/+qOWX1Q9kr7ysbraQ6ht6r+udansalA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-focus-within": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-9.0.1.tgz", + "integrity": "sha512-fzNUyS1yOYa7mOjpci/bR+u+ESvdar6hk8XNK/TRR0fiGTp2QT5N+ducP0n3rfH/m9I7H/EQU6lsa2BrgxkEjw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-6.0.0.tgz", + "integrity": "sha512-Om0WPjEwiM9Ru+VhfEDPZJAKWUd0mV1HmNXqp2C29z80aQ2uP9UVhLc7e3aYMIor/S5cVhoPgYQ7RtfeZpYTRw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-image-set-function": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-7.0.0.tgz", + "integrity": "sha512-QL7W7QNlZuzOwBTeXEmbVckNt1FSmhQtbMRvGGqqU4Nf4xk6KUEQhAoWuMzwbSv5jxiRiSZ5Tv7eiDB9U87znA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/utilities": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-lab-function": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.6.tgz", + "integrity": "sha512-HPwvsoK7C949vBZ+eMyvH2cQeMr3UREoHvbtra76/UhDuiViZH6pir+z71UaJQohd7VDSVUdR6TkWYKExEc9aQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/css-color-parser": "^3.0.6", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/utilities": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-loader": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", + "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^8.3.5", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-logical": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-8.0.0.tgz", + "integrity": "sha512-HpIdsdieClTjXLOyYdUPAX/XQASNIwdKt5hoZW08ZOAiI+tbV0ta1oclkpVkW5ANU+xJvk3KkA0FejkjGLXUkg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-merge-idents": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz", + "integrity": "sha512-1oIoAsODUs6IHQZkLQGO15uGEbK3EAl5wi9SS8hs45VgsxQfMnxvt+L+zIr7ifZFIH14cfAeVe2uCTa+SPRa3g==", + "license": "MIT", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz", + "integrity": "sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^6.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-rules": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz", + "integrity": "sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^4.0.2", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz", + "integrity": "sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz", + "integrity": "sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q==", + "license": "MIT", + "dependencies": { + "colord": "^2.9.3", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-params": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz", + "integrity": "sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz", + "integrity": "sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.1.0.tgz", + "integrity": "sha512-rm0bdSv4jC3BDma3s9H19ZddW0aHX6EoqwDYU2IfZhRN+53QrufTRo2IdkAbRqLx4R2IYbZnbjKKxg4VN5oU9Q==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nesting": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz", + "integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-resolve-nested": "^3.0.0", + "@csstools/selector-specificity": "^5.0.0", + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.0.0.tgz", + "integrity": "sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/postcss-nesting/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/postcss-nesting/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", + "integrity": "sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz", + "integrity": "sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz", + "integrity": "sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz", + "integrity": "sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-string": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz", + "integrity": "sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz", + "integrity": "sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz", + "integrity": "sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-url": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz", + "integrity": "sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz", + "integrity": "sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-3.0.0.tgz", + "integrity": "sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==", + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-ordered-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz", + "integrity": "sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q==", + "license": "MIT", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-6.0.0.tgz", + "integrity": "sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-10.0.0.tgz", + "integrity": "sha512-5EBrMzat2pPAxQNWYavwAfoKfYcTADJ8AXGVPcUZ2UkNloUTWzJQExgrzrDkh3EKzmAx1evfTAzF9I8NGcc+qw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-preset-env": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.1.1.tgz", + "integrity": "sha512-wqqsnBFD6VIwcHHRbhjTOcOi4qRVlB26RwSr0ordPj7OubRRxdWebv/aLjKLRR8zkZrbxZyuus03nOIgC5elMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/postcss-cascade-layers": "^5.0.1", + "@csstools/postcss-color-function": "^4.0.6", + "@csstools/postcss-color-mix-function": "^3.0.6", + "@csstools/postcss-content-alt-text": "^2.0.4", + "@csstools/postcss-exponential-functions": "^2.0.5", + "@csstools/postcss-font-format-keywords": "^4.0.0", + "@csstools/postcss-gamut-mapping": "^2.0.6", + "@csstools/postcss-gradients-interpolation-method": "^5.0.6", + "@csstools/postcss-hwb-function": "^4.0.6", + "@csstools/postcss-ic-unit": "^4.0.0", + "@csstools/postcss-initial": "^2.0.0", + "@csstools/postcss-is-pseudo-class": "^5.0.1", + "@csstools/postcss-light-dark-function": "^2.0.7", + "@csstools/postcss-logical-float-and-clear": "^3.0.0", + "@csstools/postcss-logical-overflow": "^2.0.0", + "@csstools/postcss-logical-overscroll-behavior": "^2.0.0", + "@csstools/postcss-logical-resize": "^3.0.0", + "@csstools/postcss-logical-viewport-units": "^3.0.3", + "@csstools/postcss-media-minmax": "^2.0.5", + "@csstools/postcss-media-queries-aspect-ratio-number-values": "^3.0.4", + "@csstools/postcss-nested-calc": "^4.0.0", + "@csstools/postcss-normalize-display-values": "^4.0.0", + "@csstools/postcss-oklab-function": "^4.0.6", + "@csstools/postcss-progressive-custom-properties": "^4.0.0", + "@csstools/postcss-random-function": "^1.0.1", + "@csstools/postcss-relative-color-syntax": "^3.0.6", + "@csstools/postcss-scope-pseudo-class": "^4.0.1", + "@csstools/postcss-sign-functions": "^1.1.0", + "@csstools/postcss-stepped-value-functions": "^4.0.5", + "@csstools/postcss-text-decoration-shorthand": "^4.0.1", + "@csstools/postcss-trigonometric-functions": "^4.0.5", + "@csstools/postcss-unset-value": "^4.0.0", + "autoprefixer": "^10.4.19", + "browserslist": "^4.23.1", + "css-blank-pseudo": "^7.0.1", + "css-has-pseudo": "^7.0.1", + "css-prefers-color-scheme": "^10.0.0", + "cssdb": "^8.2.1", + "postcss-attribute-case-insensitive": "^7.0.1", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^7.0.6", + "postcss-color-hex-alpha": "^10.0.0", + "postcss-color-rebeccapurple": "^10.0.0", + "postcss-custom-media": "^11.0.5", + "postcss-custom-properties": "^14.0.4", + "postcss-custom-selectors": "^8.0.4", + "postcss-dir-pseudo-class": "^9.0.1", + "postcss-double-position-gradients": "^6.0.0", + "postcss-focus-visible": "^10.0.1", + "postcss-focus-within": "^9.0.1", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^6.0.0", + "postcss-image-set-function": "^7.0.0", + "postcss-lab-function": "^7.0.6", + "postcss-logical": "^8.0.0", + "postcss-nesting": "^13.0.1", + "postcss-opacity-percentage": "^3.0.0", + "postcss-overflow-shorthand": "^6.0.0", + "postcss-page-break": "^3.0.4", + "postcss-place": "^10.0.0", + "postcss-pseudo-class-any-link": "^10.0.1", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^8.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-10.0.1.tgz", + "integrity": "sha512-3el9rXlBOqTFaMFkWDOkHUTQekFIYnaQY55Rsp8As8QQkpiSgIYEcF/6Ond93oHiDsGb4kad8zjt+NPlOC1H0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-reduce-idents": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-6.0.3.tgz", + "integrity": "sha512-G3yCqZDpsNPoQgbDUy3T0E6hqOQ5xigUtBQyrmq3tn2GxlyiL0yyl7H+T8ulQR6kOcHJ9t7/9H4/R2tv8tJbMA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz", + "integrity": "sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz", + "integrity": "sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "license": "MIT", + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-8.0.1.tgz", + "integrity": "sha512-kmVy/5PYVb2UOhy0+LqUYAhKj7DUGDpSWa5LZqlkWJaaAV+dxxsOG3+St0yNLu6vsKD7Dmqx+nWQt0iil89+WA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-selector-not/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-sort-media-queries": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-5.2.0.tgz", + "integrity": "sha512-AZ5fDMLD8SldlAYlvi8NIqo0+Z8xnXU2ia0jxmuhxAU+Lqt9K+AlmLNJ/zWEnE9x+Zx3qL3+1K20ATgNOr3fAA==", + "license": "MIT", + "dependencies": { + "sort-css-media-queries": "2.2.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.4.23" + } + }, + "node_modules/postcss-svgo": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.3.tgz", + "integrity": "sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^3.2.0" + }, + "engines": { + "node": "^14 || ^16 || >= 18" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz", + "integrity": "sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/postcss-zindex": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-6.0.2.tgz", + "integrity": "sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/preact": { + "version": "10.24.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", + "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/prism-react-renderer": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.4.0.tgz", + "integrity": "sha512-327BsVCD/unU4CNLZTWVHyUHKnsqcvj2qbPlQ8MiBE2eq2rgctjigPA1Gp9HLF83kZ20zNN6jgizHJeEsyFYOw==", + "license": "MIT", + "dependencies": { + "@types/prismjs": "^1.26.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.0.0" + } + }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "license": "ISC" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", + "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", + "license": "MIT", + "dependencies": { + "escape-goat": "^4.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/react-dev-utils/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dev-utils/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==", + "license": "MIT" + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" + }, + "node_modules/react-helmet-async": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-json-view-lite": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.5.0.tgz", + "integrity": "sha512-nWqA1E4jKPklL2jvHWs6s+7Na0qNgw9HCP6xehdQJeg6nPBTFZgGwyko9Q0oj+jQWKTTVRS30u0toM5wiuL3iw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-loadable": { + "name": "@docusaurus/react-loadable", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", + "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", + "license": "MIT", + "dependencies": { + "@types/react": "*" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-loadable-ssr-addon-v5-slorber": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", + "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.3" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "react-loadable": "*", + "webpack": ">=4.41.1 || 5.x" + } + }, + "node_modules/react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-config": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", + "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2" + }, + "peerDependencies": { + "react": ">=15", + "react-router": ">=5" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==", + "license": "MIT" + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.0.tgz", + "integrity": "sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", + "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.11.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "license": "MIT", + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "license": "MIT", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.2.tgz", + "integrity": "sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remark-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.0.tgz", + "integrity": "sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-emoji": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-4.0.1.tgz", + "integrity": "sha512-fHdvsTR1dHkWKev9eNyhTo4EFwbUvJ8ka9SgeWkMPYFX4WoI7ViVBms3PjlQYgw5TLvNQso3GUB/b/8t3yo+dg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.2", + "emoticon": "^4.0.1", + "mdast-util-find-and-replace": "^3.0.1", + "node-emoji": "^2.1.0", + "unified": "^11.0.4" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/remark-frontmatter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz", + "integrity": "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-frontmatter": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz", + "integrity": "sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.1.tgz", + "integrity": "sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "license": "MIT", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", + "engines": { + "node": "*" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==", + "license": "MIT" + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense" + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "license": "MIT", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, + "node_modules/rtl-detect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", + "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==", + "license": "BSD-3-Clause" + }, + "node_modules/rtlcss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", + "integrity": "sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==", + "license": "MIT", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0", + "postcss": "^8.4.21", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "rtlcss": "bin/rtlcss.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/search-insights": { + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", + "license": "MIT", + "peer": true + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "license": "MIT" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/seroval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.1.1.tgz", + "integrity": "sha512-rqEO6FZk8mv7Hyv4UCj3FD3b6Waqft605TLfsCe/BiaylRpyyMC0b+uA5TJKawX3KzMrdi3wsLbCaLplrQmBvQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/seroval-plugins": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.1.1.tgz", + "integrity": "sha512-qNSy1+nUj7hsCOon7AO4wdAIo9P0jrzAMp18XhiOzA6/uO5TKtP7ScozVJ8T293oRIvi5wyCHSM4TrJo/c/GJA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "seroval": "^1.0" + } + }, + "node_modules/serve-handler": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", + "integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==", + "license": "MIT", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "3.3.0", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", + "license": "MIT" + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "license": "ISC" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "license": "BSD-3-Clause", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/sitemap": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.2.tgz", + "integrity": "sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw==", + "license": "MIT", + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=5.6.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "license": "MIT" + }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "license": "MIT", + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "license": "MIT", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/solid-js": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.3.tgz", + "integrity": "sha512-5ba3taPoZGt9GY3YlsCB24kCg0Lv/rie/HTD4kG6h4daZZz7+yK02xn8Vx8dLYBc9i6Ps5JwAbEiqjmKaLB3Ag==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.0", + "seroval": "^1.1.0", + "seroval-plugins": "^1.1.0" + } + }, + "node_modules/sort-css-media-queries": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz", + "integrity": "sha512-0xtkGhWCC9MGt/EzgnvbbbKhqWjl1+/rncmhTh5qCpbYguXh6S/qwePfv/JQ8jePXXmqingylxoC49pCkSPIbA==", + "license": "MIT", + "engines": { + "node": ">= 6.3.0" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/srcset": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", + "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "license": "BSD-2-Clause", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-to-object": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", + "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, + "node_modules/stylehacks": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.1.1.tgz", + "integrity": "sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/stylis": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz", + "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "license": "MIT" + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "license": "MIT", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "license": "MIT" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "license": "MIT" + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "license": "MIT", + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", + "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", + "license": "BSD-2-Clause", + "dependencies": { + "boxen": "^7.0.0", + "chalk": "^5.0.1", + "configstore": "^6.0.0", + "has-yarn": "^3.0.0", + "import-lazy": "^4.0.0", + "is-ci": "^3.0.1", + "is-installed-globally": "^0.4.0", + "is-npm": "^6.0.0", + "is-yarn-global": "^0.4.0", + "latest-version": "^7.0.0", + "pupa": "^3.1.0", + "semver": "^7.3.7", + "semver-diff": "^4.0.0", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/boxen": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", + "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.1", + "chalk": "^5.2.0", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, + "node_modules/url-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/url-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/url-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/url-loader/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "license": "MIT" + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "license": "MIT" + }, + "node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "license": "MIT", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webpack": { + "version": "5.96.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", + "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", + "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "license": "MIT", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpackbar": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-6.0.1.tgz", + "integrity": "sha512-TnErZpmuKdwWBdMoexjio3KKX6ZtoKHRVvLIU0A47R0VVBDtx3ZyOJDktgYixhoJokZTYTt1Z37OkO9pnGJa9Q==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "consola": "^3.2.3", + "figures": "^3.2.0", + "markdown-table": "^2.0.0", + "pretty-time": "^1.1.0", + "std-env": "^3.7.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "webpack": "3 || 4 || 5" + } + }, + "node_modules/webpackbar/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/webpackbar/node_modules/markdown-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", + "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", + "license": "MIT", + "dependencies": { + "repeat-string": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webpackbar/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpackbar/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "license": "MIT", + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/docs/package.json b/docs/package.json index 1e4020dd4..5ee770b61 100644 --- a/docs/package.json +++ b/docs/package.json @@ -14,18 +14,26 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@cmfcmf/docusaurus-search-local": "^1.1.0", - "@docusaurus/core": "^2.2.0", - "@docusaurus/module-type-aliases": "^2.2.0", - "@docusaurus/plugin-google-gtag": "^2.4.1", - "@docusaurus/preset-classic": "^2.4.1", - "@docusaurus/theme-mermaid": "^2.4.1", - "@mdx-js/react": "^1.6.22", - "asciinema-player": "^3.5.0", - "clsx": "^1.2.1", - "prism-react-renderer": "^2.0.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "@cmfcmf/docusaurus-search-local": "1.2.0", + "@docusaurus/core": "3.6.2", + "@docusaurus/preset-classic": "3.6.2", + "@docusaurus/theme-mermaid": "3.6.2", + "@mdx-js/react": "3.1.0", + "asciinema-player": "3.8.1", + "clsx": "2.1.1", + "prism-react-renderer": "2.4.0", + "react": "18.3.1", + "react-dom": "18.3.1" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.6.2", + "@docusaurus/types": "3.6.2" + }, + "overrides": { + "@cmfcmf/docusaurus-search-local": { + "@docusaurus/core": "3.6.2", + "cheerio": "1.0.0-rc.12" + } }, "browserslist": { "production": [ diff --git a/docs/screencasts/docker/Dockerfile b/docs/screencasts/docker/Dockerfile index da28a4d7a..0b965f876 100644 --- a/docs/screencasts/docker/Dockerfile +++ b/docs/screencasts/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04@sha256:a6d2b38300ce017add71440577d5b0a90460d0e57fd7aec21dd0d1b0761bbfb2 +FROM ubuntu:22.04@sha256:0e5e4a57c2499249aafc3b40fcd541e9a456aab7296681a3994d631587203f97 # Install requirements RUN apt-get update && apt-get install -y software-properties-common &&\ diff --git a/docs/sidebars.js b/docs/sidebars.js index 67f3de87b..21d4ef42e 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -55,6 +55,11 @@ const sidebars = { label: 'Performance', link: { type: 'doc', id: 'overview/performance/performance' }, items: [ + { + type: 'doc', + label: 'Compute benchmarks', + id: 'overview/performance/compute', + }, { type: 'doc', label: 'I/O benchmarks', @@ -215,6 +220,11 @@ const sidebars = { label: 'Consume SBOMs', id: 'workflows/sbom', }, + { + type: 'doc', + label: 'Reproduce release artifacts', + id: 'workflows/reproducible-builds', + }, { type: 'doc', label: 'Troubleshooting', diff --git a/docs/src/theme/MDXComponents.js b/docs/src/theme/MDXComponents.js index a0852811a..2a1413d73 100644 --- a/docs/src/theme/MDXComponents.js +++ b/docs/src/theme/MDXComponents.js @@ -10,7 +10,7 @@ export default { ...MDXComponents, // Map the "highlight" tag to our component! // `Highlight` will receive all props that were passed to `highlight` in MDX - tabs: Tabs, - tabItem: TabItem, - asciinemaWidget: AsciinemaWidget, + Tabs, + TabItem, + AsciinemaWidget, }; diff --git a/docs/static/gtagman.js b/docs/static/gtagman.js new file mode 100644 index 000000000..57bf6717a --- /dev/null +++ b/docs/static/gtagman.js @@ -0,0 +1,5 @@ +(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': +new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], +j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= +'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); +})(window,document,'script','dataLayer','GTM-NF9NM7V'); diff --git a/docs/static/img/BannerConstellationanimated.svg b/docs/static/img/BannerConstellationanimated.svg new file mode 100644 index 000000000..f937f69a0 --- /dev/null +++ b/docs/static/img/BannerConstellationanimated.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/static/img/banner.svg b/docs/static/img/banner.svg deleted file mode 100644 index cb19bc6e9..000000000 --- a/docs/static/img/banner.svg +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/static/img/concept.svg b/docs/static/img/concept.svg index eb248bf78..2286ff308 100644 --- a/docs/static/img/concept.svg +++ b/docs/static/img/concept.svg @@ -1,119 +1,200 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - + - - + + - + - - + + - + + + + + + + + + + + + + + + diff --git a/docs/styles/config/vocabularies/edgeless/accept.txt b/docs/styles/config/vocabularies/edgeless/accept.txt index 26fa0d0c9..1676e071f 100644 --- a/docs/styles/config/vocabularies/edgeless/accept.txt +++ b/docs/styles/config/vocabularies/edgeless/accept.txt @@ -11,6 +11,7 @@ backend Bazel bootloader Bootstrapper +CLI cloud config CPU @@ -52,6 +53,7 @@ Mbps MicroK8s namespace Nginx +paravisor PCR plaintext proxied diff --git a/docs/versioned_docs/version-2.0/architecture/attestation.md b/docs/versioned_docs/version-2.0/architecture/attestation.md index 443c19639..92ee2e9a2 100644 --- a/docs/versioned_docs/version-2.0/architecture/attestation.md +++ b/docs/versioned_docs/version-2.0/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -149,8 +149,8 @@ The latter means that the value can be generated offline and compared to the one | 12 | ClusterID | Constellation Bootstrapper | Yes | | 13–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -179,8 +179,8 @@ The latter means that the value can be generated offline and compared to the one | 12 | ClusterID | Constellation Bootstrapper | Yes | | 13–23 | Unused |- | - | - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.0/getting-started/first-steps.md b/docs/versioned_docs/version-2.0/getting-started/first-steps.md index 9be306396..08adfbd12 100644 --- a/docs/versioned_docs/version-2.0/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.0/getting-started/first-steps.md @@ -6,29 +6,29 @@ The following steps guide you through the process of creating a cluster and depl 1. Create the configuration file for your selected cloud provider. - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + This creates the file `constellation-conf.yaml` in your current working directory. 2. Fill in your cloud provider specific information. - - + + You need several resources for the cluster. You can use the following `az` script to create them: @@ -59,8 +59,8 @@ The following steps guide you through the process of creating a cluster and depl Run `constellation config instance-types` to get the list of all supported options. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -106,8 +106,8 @@ The following steps guide you through the process of creating a cluster and depl Run `constellation config instance-types` to get the list of all supported options. - - + + You need a service account for the cluster. You can use the following `gcloud` script to create it: @@ -130,8 +130,8 @@ The following steps guide you through the process of creating a cluster and depl By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines from the N2D family. Refer to [N2D machine series](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) or run `constellation config instance-types` to get the list of all supported options. - - + + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -159,8 +159,8 @@ The following steps guide you through the process of creating a cluster and depl Supported are all machines from the N2D family with a minimum of 4 vCPUs. It defaults to `n2d-standard-4` (4 vCPUs, 16 GB RAM), but you can use any other VMs from the same family. Refer to [N2D machine series](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) or run `constellation config instance-types` to get the list of all supported options. - - + + :::info diff --git a/docs/versioned_docs/version-2.0/getting-started/install.md b/docs/versioned_docs/version-2.0/getting-started/install.md index 8e3545c1a..5945f0405 100644 --- a/docs/versioned_docs/version-2.0/getting-started/install.md +++ b/docs/versioned_docs/version-2.0/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,10 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` + - - - + 1. Download the CLI: @@ -71,11 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` + - - - - + 1. Download the CLI: @@ -91,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -104,8 +101,8 @@ The CLI makes authenticated calls to the CSP API. Therefore, you need to set up ### Required permissions - - + + You need the following permissions for your user account: @@ -115,8 +112,8 @@ You need the following permissions for your user account: If you don't have these permissions with scope *subscription*, ask your administrator to [create the service account and a resource group for your Constellation cluster](first-steps.md). Your user account needs the `Contributor` permission scoped to this resource group. - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -128,8 +125,8 @@ You need the following permissions on this project: Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + ### Authentication @@ -139,8 +136,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -156,8 +153,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -180,8 +177,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + ## Next steps diff --git a/docs/versioned_docs/version-2.0/overview/clouds.md b/docs/versioned_docs/version-2.0/overview/clouds.md index 2fd864945..0fa4b79f7 100644 --- a/docs/versioned_docs/version-2.0/overview/clouds.md +++ b/docs/versioned_docs/version-2.0/overview/clouds.md @@ -24,7 +24,7 @@ The following table summarizes the state of features for different infrastructur With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. Regarding (3), Azure provides direct access to remote-attestation statements. However, regarding (4), the standard CVMs still include closed-source firmware running in VM Privilege Level (VMPL) 0. This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.0/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.0/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.0/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.0/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.0/workflows/create.md b/docs/versioned_docs/version-2.0/workflows/create.md index 357ab6703..a426202e5 100644 --- a/docs/versioned_docs/version-2.0/workflows/create.md +++ b/docs/versioned_docs/version-2.0/workflows/create.md @@ -15,22 +15,22 @@ This step creates the necessary resources for your cluster in your cloud environ Generate a configuration file for your cloud service provider (CSP): - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. [Fill in your CSP-specific information](../getting-started/first-steps.md#create-a-cluster) before you continue. @@ -53,7 +53,7 @@ constellation create --control-plane-nodes 1 --worker-nodes 2 For details on the flags, consult the command help via `constellation create -h`. -*create* stores your cluster's configuration to a file named [`constellation-state.json`](../architecture/orchestration.md#installation-process) in your current directory. +*create* stores your cluster's configuration to a file named [`constellation-state.json`](../architecture/orchestration.md#cluster-creation-process) in your current directory. ## The *init* step diff --git a/docs/versioned_docs/version-2.0/workflows/recovery.md b/docs/versioned_docs/version-2.0/workflows/recovery.md index 4c6010d98..ca37ca839 100644 --- a/docs/versioned_docs/version-2.0/workflows/recovery.md +++ b/docs/versioned_docs/version-2.0/workflows/recovery.md @@ -17,8 +17,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -52,8 +52,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. For this, you need its IP address, which you can obtain from the *Overview* page under *Private IP address*. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -88,8 +88,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. For this, you need its IP address, which you can obtain from the **VM Instance** > **network interfaces** table under *Primary internal IP address*. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.0/workflows/scale.md b/docs/versioned_docs/version-2.0/workflows/scale.md index 3318d8aee..84773b80c 100644 --- a/docs/versioned_docs/version-2.0/workflows/scale.md +++ b/docs/versioned_docs/version-2.0/workflows/scale.md @@ -6,23 +6,23 @@ Constellation provides all features of a Kubernetes cluster including scaling an [During cluster initialization](create.md#the-init-step) you can choose to deploy the [cluster autoscaler](https://github.com/kubernetes/autoscaler). It automatically provisions additional worker nodes so that all pods have a place to run. Alternatively, you can choose to manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + ## Control-plane node scaling @@ -30,23 +30,23 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.0/workflows/storage.md b/docs/versioned_docs/version-2.0/workflows/storage.md index 958c73261..38d77c694 100644 --- a/docs/versioned_docs/version-2.0/workflows/storage.md +++ b/docs/versioned_docs/version-2.0/workflows/storage.md @@ -21,14 +21,14 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as ReadWriteOnce, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. @@ -36,8 +36,8 @@ This includes support for [volume snapshots](https://cloud.google.com/kubernetes You can use them to bring a volume back to a prior state or provision new volumes. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for information about the configuration. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction) or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -45,8 +45,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The following installation guide gives an overview of how to securely use CSI-based cloud storage for persistent volumes in Constellation. - - + + 1. Install the driver: @@ -56,8 +56,8 @@ The following installation guide gives an overview of how to securely use CSI-ba helm install azuredisk-csi-driver charts/edgeless --namespace kube-system ``` - - + + 1. Install the driver: @@ -66,8 +66,8 @@ The following installation guide gives an overview of how to securely use CSI-ba helm install gcp-compute-persistent-disk-csi-driver charts/ --namespace kube-system ``` - - + + :::info @@ -138,8 +138,8 @@ The default storage class is responsible for all persistent volume claims that d The previous instructions create a storage class with encryption enabled and sets this as the default class. In case you wish to change it, follow the steps below: - - + + 1. List the storage classes in your cluster: @@ -185,8 +185,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) azuredisk.csi.confidential.cloud Delete Immediate false 1d ``` - - + + 1. List the storage classes in your cluster: @@ -232,5 +232,5 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) gcp.csi.confidential.cloud Delete Immediate false 1d ``` - - + + diff --git a/docs/versioned_docs/version-2.0/workflows/troubleshooting.md b/docs/versioned_docs/version-2.0/workflows/troubleshooting.md index ba340601b..afc9274c6 100644 --- a/docs/versioned_docs/version-2.0/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.0/workflows/troubleshooting.md @@ -8,8 +8,8 @@ To provide information during early stages of the node's boot process, Constella You can view these information in the follow places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -19,8 +19,8 @@ You can view these information in the follow places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -35,5 +35,5 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + diff --git a/docs/versioned_docs/version-2.0/workflows/verify-cli.md b/docs/versioned_docs/version-2.0/workflows/verify-cli.md index 0a52fedd4..52ed24d95 100644 --- a/docs/versioned_docs/version-2.0/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.0/workflows/verify-cli.md @@ -1,6 +1,6 @@ # Verify the CLI -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -12,7 +12,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -25,7 +25,7 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.1/architecture/attestation.md b/docs/versioned_docs/version-2.1/architecture/attestation.md index 443c19639..92ee2e9a2 100644 --- a/docs/versioned_docs/version-2.1/architecture/attestation.md +++ b/docs/versioned_docs/version-2.1/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -149,8 +149,8 @@ The latter means that the value can be generated offline and compared to the one | 12 | ClusterID | Constellation Bootstrapper | Yes | | 13–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -179,8 +179,8 @@ The latter means that the value can be generated offline and compared to the one | 12 | ClusterID | Constellation Bootstrapper | Yes | | 13–23 | Unused |- | - | - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.1/getting-started/first-steps.md b/docs/versioned_docs/version-2.1/getting-started/first-steps.md index bd9513650..d729fd0cf 100644 --- a/docs/versioned_docs/version-2.1/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.1/getting-started/first-steps.md @@ -11,29 +11,29 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step 1. Create the configuration file for your selected cloud provider. - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + This creates the file `constellation-conf.yaml` in your current working directory. 2. Fill in your cloud provider specific information. - - + + You need several resources for the cluster. You can use the following `az` script to create them: @@ -64,8 +64,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step Run `constellation config instance-types` to get the list of all supported options. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -111,8 +111,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step Run `constellation config instance-types` to get the list of all supported options. - - + + You need a service account for the cluster. You can use the following `gcloud` script to create it: @@ -135,8 +135,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines from the N2D family. Refer to [N2D machine series](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) or run `constellation config instance-types` to get the list of all supported options. - - + + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -164,8 +164,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step Supported are all machines from the N2D family with a minimum of 4 vCPUs. It defaults to `n2d-standard-4` (4 vCPUs, 16 GB RAM), but you can use any other VMs from the same family. Refer to [N2D machine series](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) or run `constellation config instance-types` to get the list of all supported options. - - + + :::info diff --git a/docs/versioned_docs/version-2.1/getting-started/install.md b/docs/versioned_docs/version-2.1/getting-started/install.md index 56029b806..d4cf81ff7 100644 --- a/docs/versioned_docs/version-2.1/getting-started/install.md +++ b/docs/versioned_docs/version-2.1/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,10 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` + - - - + 1. Download the CLI: @@ -71,11 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` + - - - - + 1. Download the CLI: @@ -91,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -108,8 +105,8 @@ If you don't have a cloud subscription, you can try [MiniConstellation](first-st ### Required permissions - - + + You need the following permissions for your user account: @@ -119,8 +116,8 @@ You need the following permissions for your user account: If you don't have these permissions with scope *subscription*, ask your administrator to [create the service account and a resource group for your Constellation cluster](first-steps.md). Your user account needs the `Contributor` permission scoped to this resource group. - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -132,8 +129,8 @@ You need the following permissions on this project: Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + ### Authentication @@ -143,8 +140,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -160,8 +157,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -184,8 +181,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + ## Next steps diff --git a/docs/versioned_docs/version-2.1/overview/clouds.md b/docs/versioned_docs/version-2.1/overview/clouds.md index 2fd864945..0fa4b79f7 100644 --- a/docs/versioned_docs/version-2.1/overview/clouds.md +++ b/docs/versioned_docs/version-2.1/overview/clouds.md @@ -24,7 +24,7 @@ The following table summarizes the state of features for different infrastructur With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. Regarding (3), Azure provides direct access to remote-attestation statements. However, regarding (4), the standard CVMs still include closed-source firmware running in VM Privilege Level (VMPL) 0. This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.1/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.1/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.1/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.1/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.1/workflows/create.md b/docs/versioned_docs/version-2.1/workflows/create.md index a567c5d23..a8956d7e4 100644 --- a/docs/versioned_docs/version-2.1/workflows/create.md +++ b/docs/versioned_docs/version-2.1/workflows/create.md @@ -19,22 +19,22 @@ This step creates the necessary resources for your cluster in your cloud environ Generate a configuration file for your cloud service provider (CSP): - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. [Fill in your CSP-specific information](../getting-started/first-steps.md#create-a-cluster) before you continue. @@ -57,7 +57,7 @@ constellation create --control-plane-nodes 1 --worker-nodes 2 For details on the flags, consult the command help via `constellation create -h`. -*create* stores your cluster's configuration to a file named [`constellation-state.json`](../architecture/orchestration.md#installation-process) in your current directory. +*create* stores your cluster's configuration to a file named [`constellation-state.json`](../architecture/orchestration.md#cluster-creation-process) in your current directory. ## The *init* step diff --git a/docs/versioned_docs/version-2.1/workflows/recovery.md b/docs/versioned_docs/version-2.1/workflows/recovery.md index cde039ea7..c55daf413 100644 --- a/docs/versioned_docs/version-2.1/workflows/recovery.md +++ b/docs/versioned_docs/version-2.1/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.1/workflows/scale.md b/docs/versioned_docs/version-2.1/workflows/scale.md index 1c8757fe8..669856655 100644 --- a/docs/versioned_docs/version-2.1/workflows/scale.md +++ b/docs/versioned_docs/version-2.1/workflows/scale.md @@ -48,23 +48,23 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + ## Control-plane node scaling @@ -72,23 +72,23 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.1/workflows/storage.md b/docs/versioned_docs/version-2.1/workflows/storage.md index 958c73261..38d77c694 100644 --- a/docs/versioned_docs/version-2.1/workflows/storage.md +++ b/docs/versioned_docs/version-2.1/workflows/storage.md @@ -21,14 +21,14 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as ReadWriteOnce, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. @@ -36,8 +36,8 @@ This includes support for [volume snapshots](https://cloud.google.com/kubernetes You can use them to bring a volume back to a prior state or provision new volumes. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for information about the configuration. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction) or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -45,8 +45,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The following installation guide gives an overview of how to securely use CSI-based cloud storage for persistent volumes in Constellation. - - + + 1. Install the driver: @@ -56,8 +56,8 @@ The following installation guide gives an overview of how to securely use CSI-ba helm install azuredisk-csi-driver charts/edgeless --namespace kube-system ``` - - + + 1. Install the driver: @@ -66,8 +66,8 @@ The following installation guide gives an overview of how to securely use CSI-ba helm install gcp-compute-persistent-disk-csi-driver charts/ --namespace kube-system ``` - - + + :::info @@ -138,8 +138,8 @@ The default storage class is responsible for all persistent volume claims that d The previous instructions create a storage class with encryption enabled and sets this as the default class. In case you wish to change it, follow the steps below: - - + + 1. List the storage classes in your cluster: @@ -185,8 +185,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) azuredisk.csi.confidential.cloud Delete Immediate false 1d ``` - - + + 1. List the storage classes in your cluster: @@ -232,5 +232,5 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) gcp.csi.confidential.cloud Delete Immediate false 1d ``` - - + + diff --git a/docs/versioned_docs/version-2.1/workflows/troubleshooting.md b/docs/versioned_docs/version-2.1/workflows/troubleshooting.md index ba340601b..afc9274c6 100644 --- a/docs/versioned_docs/version-2.1/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.1/workflows/troubleshooting.md @@ -8,8 +8,8 @@ To provide information during early stages of the node's boot process, Constella You can view these information in the follow places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -19,8 +19,8 @@ You can view these information in the follow places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -35,5 +35,5 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + diff --git a/docs/versioned_docs/version-2.1/workflows/verify-cli.md b/docs/versioned_docs/version-2.1/workflows/verify-cli.md index 0a52fedd4..52ed24d95 100644 --- a/docs/versioned_docs/version-2.1/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.1/workflows/verify-cli.md @@ -1,6 +1,6 @@ # Verify the CLI -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -12,7 +12,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -25,7 +25,7 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.10/architecture/attestation.md b/docs/versioned_docs/version-2.10/architecture/attestation.md index 07ac3aa72..592063193 100644 --- a/docs/versioned_docs/version-2.10/architecture/attestation.md +++ b/docs/versioned_docs/version-2.10/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,16 +217,16 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ### CVM verification To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. For verification of the CVM technology, Constellation may expose additional options in its config file. - - + + On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. @@ -248,18 +248,18 @@ You may customize certain parameters for verification of the attestation stateme More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. - - + + There is no additional configuration available for GCP. - - + + There is no additional configuration available for AWS. - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.10/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.10/getting-started/first-steps-local.md index de9c66e9b..a6e825906 100644 --- a/docs/versioned_docs/version-2.10/getting-started/first-steps-local.md +++ b/docs/versioned_docs/version-2.10/getting-started/first-steps-local.md @@ -45,8 +45,8 @@ sudo iptables -P FORWARD ACCEPT ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -74,8 +74,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -151,8 +151,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -205,8 +205,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -217,8 +217,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -246,8 +246,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/versioned_docs/version-2.10/getting-started/first-steps.md b/docs/versioned_docs/version-2.10/getting-started/first-steps.md index 0b224e04d..9f6034e6b 100644 --- a/docs/versioned_docs/version-2.10/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.10/getting-started/first-steps.md @@ -15,39 +15,39 @@ If you encounter any problem with the following steps, make sure to use the [lat 1. Create the [configuration file](../workflows/config.md) for your cloud provider. - + - + ```bash constellation config generate azure ``` - + - + ```bash constellation config generate gcp ``` - + - + ```bash constellation config generate aws ``` - + - + 2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config @@ -62,9 +62,9 @@ If you encounter any problem with the following steps, make sure to use the [lat * `westeurope` * `southeastasia` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config @@ -74,9 +74,9 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - + - + ```bash constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config @@ -103,8 +103,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.10/getting-started/install.md b/docs/versioned_docs/version-2.10/getting-started/install.md index da0c0a14b..c21ad259c 100644 --- a/docs/versioned_docs/version-2.10/getting-started/install.md +++ b/docs/versioned_docs/version-2.10/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,39 +105,42 @@ If you don't have a cloud subscription, you can also set up a [local Constellati ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] -* `Microsoft.Compute` -* `Microsoft.Insights` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` + +- `Microsoft.Attestation` +- `Microsoft.Compute` +- `Microsoft.Insights` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` By default, Constellation tries to register these automatically if they haven't been registered before. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `*/register/action` \[1] -* `Microsoft.Authorization/roleAssignments/*` -* `Microsoft.Authorization/roleDefinitions/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Resources/subscriptions/resourcegroups/*` + +- `*/register/action` \[1] +- `Microsoft.Authorization/roleAssignments/*` +- `Microsoft.Authorization/roleDefinitions/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Resources/subscriptions/resourcegroups/*` The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] -* `Microsoft.Compute/virtualMachineScaleSets/*` -* `Microsoft.Insights/components/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Network/loadBalancers/*` -* `Microsoft.Network/loadBalancers/backendAddressPools/*` -* `Microsoft.Network/networkSecurityGroups/*` -* `Microsoft.Network/publicIPAddresses/*` -* `Microsoft.Network/virtualNetworks/*` -* `Microsoft.Network/virtualNetworks/subnets/*` -* `Microsoft.Network/natGateways/*` + +- `Microsoft.Attestation/attestationProviders/*` +- `Microsoft.Compute/virtualMachineScaleSets/*` +- `Microsoft.Insights/components/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Network/loadBalancers/*` +- `Microsoft.Network/loadBalancers/backendAddressPools/*` +- `Microsoft.Network/networkSecurityGroups/*` +- `Microsoft.Network/publicIPAddresses/*` +- `Microsoft.Network/virtualNetworks/*` +- `Microsoft.Network/virtualNetworks/subnets/*` +- `Microsoft.Network/natGateways/*` The built-in `Contributor` role is a superset of these permissions. @@ -145,91 +148,91 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `iam.serviceAccountKeys.create` -* `iam.serviceAccountKeys.delete` -* `iam.serviceAccountKeys.get` -* `iam.serviceAccounts.create` -* `iam.serviceAccounts.delete` -* `iam.serviceAccounts.get` -* `resourcemanager.projects.getIamPolicy` -* `resourcemanager.projects.setIamPolicy` + +- `iam.serviceAccountKeys.create` +- `iam.serviceAccountKeys.delete` +- `iam.serviceAccountKeys.get` +- `iam.serviceAccounts.create` +- `iam.serviceAccounts.delete` +- `iam.serviceAccounts.get` +- `resourcemanager.projects.getIamPolicy` +- `resourcemanager.projects.setIamPolicy` Together, the built-in roles `roles/editor` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `compute.addresses.createInternal` -* `compute.addresses.deleteInternal` -* `compute.addresses.get` -* `compute.addresses.useInternal` -* `compute.backendServices.create` -* `compute.backendServices.delete` -* `compute.backendServices.get` -* `compute.backendServices.use` -* `compute.disks.create` -* `compute.firewalls.create` -* `compute.firewalls.delete` -* `compute.firewalls.get` -* `compute.globalAddresses.create` -* `compute.globalAddresses.delete` -* `compute.globalAddresses.get` -* `compute.globalAddresses.use` -* `compute.globalForwardingRules.create` -* `compute.globalForwardingRules.delete` -* `compute.globalForwardingRules.get` -* `compute.globalForwardingRules.setLabels` -* `compute.globalOperations.get` -* `compute.healthChecks.create` -* `compute.healthChecks.delete` -* `compute.healthChecks.get` -* `compute.healthChecks.useReadOnly` -* `compute.instanceGroupManagers.create` -* `compute.instanceGroupManagers.delete` -* `compute.instanceGroupManagers.get` -* `compute.instanceGroups.create` -* `compute.instanceGroups.delete` -* `compute.instanceGroups.get` -* `compute.instanceGroups.use` -* `compute.instances.create` -* `compute.instances.setLabels` -* `compute.instances.setMetadata` -* `compute.instances.setTags` -* `compute.instanceTemplates.create` -* `compute.instanceTemplates.delete` -* `compute.instanceTemplates.get` -* `compute.instanceTemplates.useReadOnly` -* `compute.networks.create` -* `compute.networks.delete` -* `compute.networks.get` -* `compute.networks.updatePolicy` -* `compute.routers.create` -* `compute.routers.delete` -* `compute.routers.get` -* `compute.routers.update` -* `compute.subnetworks.create` -* `compute.subnetworks.delete` -* `compute.subnetworks.get` -* `compute.subnetworks.use` -* `compute.targetTcpProxies.create` -* `compute.targetTcpProxies.delete` -* `compute.targetTcpProxies.get` -* `compute.targetTcpProxies.use` -* `iam.serviceAccounts.actAs` + +- `compute.addresses.createInternal` +- `compute.addresses.deleteInternal` +- `compute.addresses.get` +- `compute.addresses.useInternal` +- `compute.backendServices.create` +- `compute.backendServices.delete` +- `compute.backendServices.get` +- `compute.backendServices.use` +- `compute.disks.create` +- `compute.firewalls.create` +- `compute.firewalls.delete` +- `compute.firewalls.get` +- `compute.globalAddresses.create` +- `compute.globalAddresses.delete` +- `compute.globalAddresses.get` +- `compute.globalAddresses.use` +- `compute.globalForwardingRules.create` +- `compute.globalForwardingRules.delete` +- `compute.globalForwardingRules.get` +- `compute.globalForwardingRules.setLabels` +- `compute.globalOperations.get` +- `compute.healthChecks.create` +- `compute.healthChecks.delete` +- `compute.healthChecks.get` +- `compute.healthChecks.useReadOnly` +- `compute.instanceGroupManagers.create` +- `compute.instanceGroupManagers.delete` +- `compute.instanceGroupManagers.get` +- `compute.instanceGroups.create` +- `compute.instanceGroups.delete` +- `compute.instanceGroups.get` +- `compute.instanceGroups.use` +- `compute.instances.create` +- `compute.instances.setLabels` +- `compute.instances.setMetadata` +- `compute.instances.setTags` +- `compute.instanceTemplates.create` +- `compute.instanceTemplates.delete` +- `compute.instanceTemplates.get` +- `compute.instanceTemplates.useReadOnly` +- `compute.networks.create` +- `compute.networks.delete` +- `compute.networks.get` +- `compute.networks.updatePolicy` +- `compute.routers.create` +- `compute.routers.delete` +- `compute.routers.get` +- `compute.routers.update` +- `compute.subnetworks.create` +- `compute.subnetworks.delete` +- `compute.subnetworks.get` +- `compute.subnetworks.use` +- `compute.targetTcpProxies.create` +- `compute.targetTcpProxies.delete` +- `compute.targetTcpProxies.get` +- `compute.targetTcpProxies.use` +- `iam.serviceAccounts.actAs` Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -279,8 +282,8 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -290,8 +293,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -307,8 +310,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -331,8 +334,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -348,9 +351,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.10/overview/clouds.md b/docs/versioned_docs/version-2.10/overview/clouds.md index c56a623b1..dfc3d5307 100644 --- a/docs/versioned_docs/version-2.10/overview/clouds.md +++ b/docs/versioned_docs/version-2.10/overview/clouds.md @@ -31,7 +31,7 @@ This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -\* Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.10/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.10/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.10/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.10/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.10/overview/performance/compute.md b/docs/versioned_docs/version-2.10/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/versioned_docs/version-2.10/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/versioned_docs/version-2.10/overview/performance/performance.md b/docs/versioned_docs/version-2.10/overview/performance/performance.md index 7f22a693e..59bf86602 100644 --- a/docs/versioned_docs/version-2.10/overview/performance/performance.md +++ b/docs/versioned_docs/version-2.10/overview/performance/performance.md @@ -1,18 +1,10 @@ # Performance analysis of Constellation -This section provides a comprehensive examination of the performance characteristics of Constellation, encompassing various aspects, including runtime encryption, I/O benchmarks, and real-world applications. +This section provides a comprehensive examination of the performance characteristics of Constellation. -## Impact of runtime encryption on performance +## Runtime encryption -All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. - -### AMD and Azure benchmarking - -AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. - -### AMD and Google benchmarking - -Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. ## I/O performance benchmarks diff --git a/docs/versioned_docs/version-2.10/workflows/config.md b/docs/versioned_docs/version-2.10/workflows/config.md index 95f95aeec..4dab6bd50 100644 --- a/docs/versioned_docs/version-2.10/workflows/config.md +++ b/docs/versioned_docs/version-2.10/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,49 +14,49 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. @@ -75,8 +75,8 @@ AWS is currently investigating the issue. SNP-based attestation will be enabled as soon as a fix is verified. ::: - - + + Fill the desired VM type into the **instanceType** fields in the `constellation-conf.yml` file. @@ -86,7 +86,6 @@ By default, Constellation creates the node groups `control_plane_default` and `w If you require additional control-plane or worker groups with different instance types, zone placements, or disk sizes, you can add additional node groups to the `constellation-conf.yml` file. Each node group can be scaled individually. - Consider the following example for AWS: ```yaml @@ -120,9 +119,9 @@ You can use the field `zone` to specify what availability zone nodes of the grou On Azure, this field is empty by default and nodes are automatically spread across availability zones. Consult the documentation of your cloud provider for more information: -- [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) -- [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) -- [GCP](https://cloud.google.com/compute/docs/regions-zones) +* [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) +* [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) +* [GCP](https://cloud.google.com/compute/docs/regions-zones) ## Choosing a Kubernetes version @@ -134,8 +133,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -155,8 +154,8 @@ Note that CVMs are currently only supported in a few regions, check [Azure's pro Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -170,8 +169,8 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -195,16 +194,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -233,9 +232,9 @@ The following describes the configuration fields and how you obtain the required The user-assigned identity is used by instances of the cluster to access other cloud resources. For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -259,9 +258,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -292,9 +291,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.10/workflows/create.md b/docs/versioned_docs/version-2.10/workflows/create.md index c0e0cd23d..dd56bc8b7 100644 --- a/docs/versioned_docs/version-2.10/workflows/create.md +++ b/docs/versioned_docs/version-2.10/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -26,8 +26,8 @@ Before you create the cluster, make sure to have a [valid configuration file](./ ### Create - - + + ```bash constellation create @@ -35,8 +35,8 @@ constellation create *create* stores your cluster's state in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Terraform allows for an easier GitOps integration as well as meeting regulatory requirements. Since the Constellation CLI also uses Terraform under the hood, you can reuse the same Terraform files. @@ -75,8 +75,8 @@ CONSTELL_CSP=$(cat constellation-conf.yaml | yq ".provider | keys | .[0]") jq --null-input --arg cloudprovider "$CONSTELL_CSP" --arg ip "$CONSTELL_IP" --arg initsecret "$CONSTELL_INIT_SECRET" '{"cloudprovider":$cloudprovider,"ip":$ip,"initsecret":$initsecret}' > constellation-id.json ``` - - + + ## The *init* step diff --git a/docs/versioned_docs/version-2.10/workflows/recovery.md b/docs/versioned_docs/version-2.10/workflows/recovery.md index c26fb32eb..35596b8c9 100644 --- a/docs/versioned_docs/version-2.10/workflows/recovery.md +++ b/docs/versioned_docs/version-2.10/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.10/workflows/sbom.md b/docs/versioned_docs/version-2.10/workflows/sbom.md index 9ef6eb65c..6c1702dee 100644 --- a/docs/versioned_docs/version-2.10/workflows/sbom.md +++ b/docs/versioned_docs/version-2.10/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -11,13 +11,15 @@ SBOMs for Constellation are generated using [Syft](https://github.com/anchore/sy :::note The public key for Edgeless Systems' long-term code-signing key is: + ``` -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at https://edgeless.systems/es.pub and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -38,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.10/workflows/scale.md b/docs/versioned_docs/version-2.10/workflows/scale.md index 06898ad0c..63b727c7d 100644 --- a/docs/versioned_docs/version-2.10/workflows/scale.md +++ b/docs/versioned_docs/version-2.10/workflows/scale.md @@ -51,30 +51,30 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the worker ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + ## Control-plane node scaling @@ -82,30 +82,30 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.10/workflows/storage.md b/docs/versioned_docs/version-2.10/workflows/storage.md index 9e3d96346..06fbc4de6 100644 --- a/docs/versioned_docs/version-2.10/workflows/storage.md +++ b/docs/versioned_docs/version-2.10/workflows/storage.md @@ -21,30 +21,30 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. - - + + **Constellation CSI driver for AWS Elastic Block Store** Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -53,8 +53,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -82,8 +82,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -111,8 +111,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + AWS comes with two storage classes by default. @@ -140,8 +140,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) diff --git a/docs/versioned_docs/version-2.10/workflows/terminate.md b/docs/versioned_docs/version-2.10/workflows/terminate.md index 647eadb42..f33489ca5 100644 --- a/docs/versioned_docs/version-2.10/workflows/terminate.md +++ b/docs/versioned_docs/version-2.10/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-id.json constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.10/workflows/troubleshooting.md b/docs/versioned_docs/version-2.10/workflows/troubleshooting.md index 781cae8c5..38c0d87e9 100644 --- a/docs/versioned_docs/version-2.10/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.10/workflows/troubleshooting.md @@ -55,14 +55,12 @@ When in doubt, check if the encountered [issue is known](https://github.com/edge ::: - :::tip During an upgrade with modified attestation config, a backup of the current configuration is stored in the `join-config-backup` config map in the `kube-system` namespace. To restore the old attestation config after a failed upgrade, you can copy the attestation config from this resource, put it in your configuration file and retry the upgrade. ::: - You can use the `upgrade apply` command to change measurements of a running cluster: 1. Modify the `measurements` key in your local `constellation-conf.yaml` to the expected values. @@ -84,8 +82,8 @@ To provide information during early stages of a node's boot process, Constellati You can view this information in the following places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -95,8 +93,8 @@ You can view this information in the following places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -111,16 +109,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ### Node shell access diff --git a/docs/versioned_docs/version-2.10/workflows/trusted-launch.md b/docs/versioned_docs/version-2.10/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.10/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.10/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.10/workflows/verify-cli.md b/docs/versioned_docs/version-2.10/workflows/verify-cli.md index 1280c51b0..e33569d37 100644 --- a/docs/versioned_docs/version-2.10/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.10/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -33,7 +33,11 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +:::info +This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. +::: + +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.11/architecture/attestation.md b/docs/versioned_docs/version-2.11/architecture/attestation.md index 07ac3aa72..592063193 100644 --- a/docs/versioned_docs/version-2.11/architecture/attestation.md +++ b/docs/versioned_docs/version-2.11/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,16 +217,16 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ### CVM verification To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. For verification of the CVM technology, Constellation may expose additional options in its config file. - - + + On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. @@ -248,18 +248,18 @@ You may customize certain parameters for verification of the attestation stateme More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. - - + + There is no additional configuration available for GCP. - - + + There is no additional configuration available for AWS. - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.11/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.11/getting-started/first-steps-local.md index de9c66e9b..a6e825906 100644 --- a/docs/versioned_docs/version-2.11/getting-started/first-steps-local.md +++ b/docs/versioned_docs/version-2.11/getting-started/first-steps-local.md @@ -45,8 +45,8 @@ sudo iptables -P FORWARD ACCEPT ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -74,8 +74,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -151,8 +151,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -205,8 +205,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -217,8 +217,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -246,8 +246,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/versioned_docs/version-2.11/getting-started/first-steps.md b/docs/versioned_docs/version-2.11/getting-started/first-steps.md index 07b7f8410..9811597e6 100644 --- a/docs/versioned_docs/version-2.11/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.11/getting-started/first-steps.md @@ -15,39 +15,39 @@ If you encounter any problem with the following steps, make sure to use the [lat 1. Create the [configuration file](../workflows/config.md) for your cloud provider. - + - + ```bash constellation config generate azure ``` - + - + ```bash constellation config generate gcp ``` - + - + ```bash constellation config generate aws ``` - + - + 2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config @@ -62,9 +62,9 @@ If you encounter any problem with the following steps, make sure to use the [lat * `westeurope` * `southeastasia` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config @@ -74,9 +74,9 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - + - + ```bash constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config @@ -103,8 +103,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.11/getting-started/install.md b/docs/versioned_docs/version-2.11/getting-started/install.md index da0c0a14b..f134ca3c2 100644 --- a/docs/versioned_docs/version-2.11/getting-started/install.md +++ b/docs/versioned_docs/version-2.11/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,39 +105,42 @@ If you don't have a cloud subscription, you can also set up a [local Constellati ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] -* `Microsoft.Compute` -* `Microsoft.Insights` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` + +- `Microsoft.Attestation` \[2] +- `Microsoft.Compute` +- `Microsoft.Insights` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` By default, Constellation tries to register these automatically if they haven't been registered before. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `*/register/action` \[1] -* `Microsoft.Authorization/roleAssignments/*` -* `Microsoft.Authorization/roleDefinitions/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Resources/subscriptions/resourcegroups/*` + +- `*/register/action` \[1] +- `Microsoft.Authorization/roleAssignments/*` +- `Microsoft.Authorization/roleDefinitions/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Resources/subscriptions/resourcegroups/*` The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] -* `Microsoft.Compute/virtualMachineScaleSets/*` -* `Microsoft.Insights/components/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Network/loadBalancers/*` -* `Microsoft.Network/loadBalancers/backendAddressPools/*` -* `Microsoft.Network/networkSecurityGroups/*` -* `Microsoft.Network/publicIPAddresses/*` -* `Microsoft.Network/virtualNetworks/*` -* `Microsoft.Network/virtualNetworks/subnets/*` -* `Microsoft.Network/natGateways/*` + +- `Microsoft.Attestation/attestationProviders/*` +- `Microsoft.Compute/virtualMachineScaleSets/*` +- `Microsoft.Insights/components/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Network/loadBalancers/*` +- `Microsoft.Network/loadBalancers/backendAddressPools/*` +- `Microsoft.Network/networkSecurityGroups/*` +- `Microsoft.Network/publicIPAddresses/*` +- `Microsoft.Network/virtualNetworks/*` +- `Microsoft.Network/virtualNetworks/subnets/*` +- `Microsoft.Network/natGateways/*` The built-in `Contributor` role is a superset of these permissions. @@ -145,91 +148,91 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `iam.serviceAccountKeys.create` -* `iam.serviceAccountKeys.delete` -* `iam.serviceAccountKeys.get` -* `iam.serviceAccounts.create` -* `iam.serviceAccounts.delete` -* `iam.serviceAccounts.get` -* `resourcemanager.projects.getIamPolicy` -* `resourcemanager.projects.setIamPolicy` + +- `iam.serviceAccountKeys.create` +- `iam.serviceAccountKeys.delete` +- `iam.serviceAccountKeys.get` +- `iam.serviceAccounts.create` +- `iam.serviceAccounts.delete` +- `iam.serviceAccounts.get` +- `resourcemanager.projects.getIamPolicy` +- `resourcemanager.projects.setIamPolicy` Together, the built-in roles `roles/editor` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `compute.addresses.createInternal` -* `compute.addresses.deleteInternal` -* `compute.addresses.get` -* `compute.addresses.useInternal` -* `compute.backendServices.create` -* `compute.backendServices.delete` -* `compute.backendServices.get` -* `compute.backendServices.use` -* `compute.disks.create` -* `compute.firewalls.create` -* `compute.firewalls.delete` -* `compute.firewalls.get` -* `compute.globalAddresses.create` -* `compute.globalAddresses.delete` -* `compute.globalAddresses.get` -* `compute.globalAddresses.use` -* `compute.globalForwardingRules.create` -* `compute.globalForwardingRules.delete` -* `compute.globalForwardingRules.get` -* `compute.globalForwardingRules.setLabels` -* `compute.globalOperations.get` -* `compute.healthChecks.create` -* `compute.healthChecks.delete` -* `compute.healthChecks.get` -* `compute.healthChecks.useReadOnly` -* `compute.instanceGroupManagers.create` -* `compute.instanceGroupManagers.delete` -* `compute.instanceGroupManagers.get` -* `compute.instanceGroups.create` -* `compute.instanceGroups.delete` -* `compute.instanceGroups.get` -* `compute.instanceGroups.use` -* `compute.instances.create` -* `compute.instances.setLabels` -* `compute.instances.setMetadata` -* `compute.instances.setTags` -* `compute.instanceTemplates.create` -* `compute.instanceTemplates.delete` -* `compute.instanceTemplates.get` -* `compute.instanceTemplates.useReadOnly` -* `compute.networks.create` -* `compute.networks.delete` -* `compute.networks.get` -* `compute.networks.updatePolicy` -* `compute.routers.create` -* `compute.routers.delete` -* `compute.routers.get` -* `compute.routers.update` -* `compute.subnetworks.create` -* `compute.subnetworks.delete` -* `compute.subnetworks.get` -* `compute.subnetworks.use` -* `compute.targetTcpProxies.create` -* `compute.targetTcpProxies.delete` -* `compute.targetTcpProxies.get` -* `compute.targetTcpProxies.use` -* `iam.serviceAccounts.actAs` + +- `compute.addresses.createInternal` +- `compute.addresses.deleteInternal` +- `compute.addresses.get` +- `compute.addresses.useInternal` +- `compute.backendServices.create` +- `compute.backendServices.delete` +- `compute.backendServices.get` +- `compute.backendServices.use` +- `compute.disks.create` +- `compute.firewalls.create` +- `compute.firewalls.delete` +- `compute.firewalls.get` +- `compute.globalAddresses.create` +- `compute.globalAddresses.delete` +- `compute.globalAddresses.get` +- `compute.globalAddresses.use` +- `compute.globalForwardingRules.create` +- `compute.globalForwardingRules.delete` +- `compute.globalForwardingRules.get` +- `compute.globalForwardingRules.setLabels` +- `compute.globalOperations.get` +- `compute.healthChecks.create` +- `compute.healthChecks.delete` +- `compute.healthChecks.get` +- `compute.healthChecks.useReadOnly` +- `compute.instanceGroupManagers.create` +- `compute.instanceGroupManagers.delete` +- `compute.instanceGroupManagers.get` +- `compute.instanceGroups.create` +- `compute.instanceGroups.delete` +- `compute.instanceGroups.get` +- `compute.instanceGroups.use` +- `compute.instances.create` +- `compute.instances.setLabels` +- `compute.instances.setMetadata` +- `compute.instances.setTags` +- `compute.instanceTemplates.create` +- `compute.instanceTemplates.delete` +- `compute.instanceTemplates.get` +- `compute.instanceTemplates.useReadOnly` +- `compute.networks.create` +- `compute.networks.delete` +- `compute.networks.get` +- `compute.networks.updatePolicy` +- `compute.routers.create` +- `compute.routers.delete` +- `compute.routers.get` +- `compute.routers.update` +- `compute.subnetworks.create` +- `compute.subnetworks.delete` +- `compute.subnetworks.get` +- `compute.subnetworks.use` +- `compute.targetTcpProxies.create` +- `compute.targetTcpProxies.delete` +- `compute.targetTcpProxies.get` +- `compute.targetTcpProxies.use` +- `iam.serviceAccounts.actAs` Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -279,8 +282,8 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -290,8 +293,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -307,8 +310,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -331,8 +334,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -348,9 +351,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.11/overview/clouds.md b/docs/versioned_docs/version-2.11/overview/clouds.md index c56a623b1..dfc3d5307 100644 --- a/docs/versioned_docs/version-2.11/overview/clouds.md +++ b/docs/versioned_docs/version-2.11/overview/clouds.md @@ -31,7 +31,7 @@ This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -\* Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.11/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.11/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.11/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.11/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.11/overview/performance/compute.md b/docs/versioned_docs/version-2.11/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/versioned_docs/version-2.11/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/versioned_docs/version-2.11/overview/performance/performance.md b/docs/versioned_docs/version-2.11/overview/performance/performance.md index 7f22a693e..59bf86602 100644 --- a/docs/versioned_docs/version-2.11/overview/performance/performance.md +++ b/docs/versioned_docs/version-2.11/overview/performance/performance.md @@ -1,18 +1,10 @@ # Performance analysis of Constellation -This section provides a comprehensive examination of the performance characteristics of Constellation, encompassing various aspects, including runtime encryption, I/O benchmarks, and real-world applications. +This section provides a comprehensive examination of the performance characteristics of Constellation. -## Impact of runtime encryption on performance +## Runtime encryption -All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. - -### AMD and Azure benchmarking - -AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. - -### AMD and Google benchmarking - -Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. ## I/O performance benchmarks diff --git a/docs/versioned_docs/version-2.11/workflows/config.md b/docs/versioned_docs/version-2.11/workflows/config.md index 95f95aeec..4dab6bd50 100644 --- a/docs/versioned_docs/version-2.11/workflows/config.md +++ b/docs/versioned_docs/version-2.11/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,49 +14,49 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. @@ -75,8 +75,8 @@ AWS is currently investigating the issue. SNP-based attestation will be enabled as soon as a fix is verified. ::: - - + + Fill the desired VM type into the **instanceType** fields in the `constellation-conf.yml` file. @@ -86,7 +86,6 @@ By default, Constellation creates the node groups `control_plane_default` and `w If you require additional control-plane or worker groups with different instance types, zone placements, or disk sizes, you can add additional node groups to the `constellation-conf.yml` file. Each node group can be scaled individually. - Consider the following example for AWS: ```yaml @@ -120,9 +119,9 @@ You can use the field `zone` to specify what availability zone nodes of the grou On Azure, this field is empty by default and nodes are automatically spread across availability zones. Consult the documentation of your cloud provider for more information: -- [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) -- [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) -- [GCP](https://cloud.google.com/compute/docs/regions-zones) +* [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) +* [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) +* [GCP](https://cloud.google.com/compute/docs/regions-zones) ## Choosing a Kubernetes version @@ -134,8 +133,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -155,8 +154,8 @@ Note that CVMs are currently only supported in a few regions, check [Azure's pro Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -170,8 +169,8 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -195,16 +194,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -233,9 +232,9 @@ The following describes the configuration fields and how you obtain the required The user-assigned identity is used by instances of the cluster to access other cloud resources. For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -259,9 +258,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -292,9 +291,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.11/workflows/create.md b/docs/versioned_docs/version-2.11/workflows/create.md index d2b0adf90..8dd4946de 100644 --- a/docs/versioned_docs/version-2.11/workflows/create.md +++ b/docs/versioned_docs/version-2.11/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -26,8 +26,8 @@ Before you create the cluster, make sure to have a [valid configuration file](./ ### Create - - + + ```bash constellation create @@ -35,8 +35,8 @@ constellation create *create* stores your cluster's state in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Terraform allows for an easier GitOps integration as well as meeting regulatory requirements. Since the Constellation CLI also uses Terraform under the hood, you can reuse the same Terraform files. @@ -75,8 +75,8 @@ CONSTELL_CSP=$(cat constellation-conf.yaml | yq ".provider | keys | .[0]") jq --null-input --arg cloudprovider "$CONSTELL_CSP" --arg ip "$CONSTELL_IP" --arg initsecret "$CONSTELL_INIT_SECRET" '{"cloudprovider":$cloudprovider,"ip":$ip,"initsecret":$initsecret}' > constellation-id.json ``` - - + + ## The *init* step @@ -94,6 +94,6 @@ export KUBECONFIG="$PWD/constellation-admin.conf" 🏁 That's it. You've successfully created a Constellation cluster. - ### Troubleshooting + In case `init` fails, the CLI collects logs from the bootstrapping instance and stores them inside `constellation-cluster.log`. diff --git a/docs/versioned_docs/version-2.11/workflows/recovery.md b/docs/versioned_docs/version-2.11/workflows/recovery.md index c26fb32eb..35596b8c9 100644 --- a/docs/versioned_docs/version-2.11/workflows/recovery.md +++ b/docs/versioned_docs/version-2.11/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.11/workflows/sbom.md b/docs/versioned_docs/version-2.11/workflows/sbom.md index 9ef6eb65c..6c1702dee 100644 --- a/docs/versioned_docs/version-2.11/workflows/sbom.md +++ b/docs/versioned_docs/version-2.11/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -11,13 +11,15 @@ SBOMs for Constellation are generated using [Syft](https://github.com/anchore/sy :::note The public key for Edgeless Systems' long-term code-signing key is: + ``` -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at https://edgeless.systems/es.pub and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -38,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.11/workflows/scale.md b/docs/versioned_docs/version-2.11/workflows/scale.md index 06898ad0c..63b727c7d 100644 --- a/docs/versioned_docs/version-2.11/workflows/scale.md +++ b/docs/versioned_docs/version-2.11/workflows/scale.md @@ -51,30 +51,30 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the worker ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + ## Control-plane node scaling @@ -82,30 +82,30 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.11/workflows/storage.md b/docs/versioned_docs/version-2.11/workflows/storage.md index 9e3d96346..06fbc4de6 100644 --- a/docs/versioned_docs/version-2.11/workflows/storage.md +++ b/docs/versioned_docs/version-2.11/workflows/storage.md @@ -21,30 +21,30 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. - - + + **Constellation CSI driver for AWS Elastic Block Store** Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -53,8 +53,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -82,8 +82,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -111,8 +111,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + AWS comes with two storage classes by default. @@ -140,8 +140,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) diff --git a/docs/versioned_docs/version-2.11/workflows/terminate.md b/docs/versioned_docs/version-2.11/workflows/terminate.md index 647eadb42..f33489ca5 100644 --- a/docs/versioned_docs/version-2.11/workflows/terminate.md +++ b/docs/versioned_docs/version-2.11/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-id.json constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.11/workflows/troubleshooting.md b/docs/versioned_docs/version-2.11/workflows/troubleshooting.md index a3e25a0fe..c40e6496e 100644 --- a/docs/versioned_docs/version-2.11/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.11/workflows/troubleshooting.md @@ -101,8 +101,8 @@ To provide information during early stages of a node's boot process, Constellati You can view this information in the following places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -112,8 +112,8 @@ You can view this information in the following places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -128,16 +128,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ### Node shell access diff --git a/docs/versioned_docs/version-2.11/workflows/trusted-launch.md b/docs/versioned_docs/version-2.11/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.11/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.11/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.11/workflows/verify-cli.md b/docs/versioned_docs/version-2.11/workflows/verify-cli.md index 1280c51b0..e33569d37 100644 --- a/docs/versioned_docs/version-2.11/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.11/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -33,7 +33,11 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +:::info +This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. +::: + +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.12/architecture/attestation.md b/docs/versioned_docs/version-2.12/architecture/attestation.md index e37533995..f9c9ac38e 100644 --- a/docs/versioned_docs/version-2.12/architecture/attestation.md +++ b/docs/versioned_docs/version-2.12/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,16 +217,16 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ### CVM verification To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. For verification of the CVM technology, Constellation may expose additional options in its config file. - - + + On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. @@ -248,18 +248,18 @@ You may customize certain parameters for verification of the attestation stateme More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. - - + + There is no additional configuration available for GCP. - - + + There is no additional configuration available for AWS. - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.12/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.12/getting-started/first-steps-local.md index de9c66e9b..a6e825906 100644 --- a/docs/versioned_docs/version-2.12/getting-started/first-steps-local.md +++ b/docs/versioned_docs/version-2.12/getting-started/first-steps-local.md @@ -45,8 +45,8 @@ sudo iptables -P FORWARD ACCEPT ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -74,8 +74,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -151,8 +151,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -205,8 +205,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -217,8 +217,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -246,8 +246,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/versioned_docs/version-2.12/getting-started/first-steps.md b/docs/versioned_docs/version-2.12/getting-started/first-steps.md index 07b7f8410..9811597e6 100644 --- a/docs/versioned_docs/version-2.12/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.12/getting-started/first-steps.md @@ -15,39 +15,39 @@ If you encounter any problem with the following steps, make sure to use the [lat 1. Create the [configuration file](../workflows/config.md) for your cloud provider. - + - + ```bash constellation config generate azure ``` - + - + ```bash constellation config generate gcp ``` - + - + ```bash constellation config generate aws ``` - + - + 2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config @@ -62,9 +62,9 @@ If you encounter any problem with the following steps, make sure to use the [lat * `westeurope` * `southeastasia` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config @@ -74,9 +74,9 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - + - + ```bash constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config @@ -103,8 +103,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.12/getting-started/install.md b/docs/versioned_docs/version-2.12/getting-started/install.md index a1dc93cde..2fabcf0b1 100644 --- a/docs/versioned_docs/version-2.12/getting-started/install.md +++ b/docs/versioned_docs/version-2.12/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,39 +105,42 @@ If you don't have a cloud subscription, you can also set up a [local Constellati ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] -* `Microsoft.Compute` -* `Microsoft.Insights` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` + +- `Microsoft.Attestation` +- `Microsoft.Compute` +- `Microsoft.Insights` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` By default, Constellation tries to register these automatically if they haven't been registered before. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `*/register/action` \[1] -* `Microsoft.Authorization/roleAssignments/*` -* `Microsoft.Authorization/roleDefinitions/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Resources/subscriptions/resourcegroups/*` + +- `*/register/action` \[1] +- `Microsoft.Authorization/roleAssignments/*` +- `Microsoft.Authorization/roleDefinitions/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Resources/subscriptions/resourcegroups/*` The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] -* `Microsoft.Compute/virtualMachineScaleSets/*` -* `Microsoft.Insights/components/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Network/loadBalancers/*` -* `Microsoft.Network/loadBalancers/backendAddressPools/*` -* `Microsoft.Network/networkSecurityGroups/*` -* `Microsoft.Network/publicIPAddresses/*` -* `Microsoft.Network/virtualNetworks/*` -* `Microsoft.Network/virtualNetworks/subnets/*` -* `Microsoft.Network/natGateways/*` + +- `Microsoft.Attestation/attestationProviders/*` +- `Microsoft.Compute/virtualMachineScaleSets/*` +- `Microsoft.Insights/components/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Network/loadBalancers/*` +- `Microsoft.Network/loadBalancers/backendAddressPools/*` +- `Microsoft.Network/networkSecurityGroups/*` +- `Microsoft.Network/publicIPAddresses/*` +- `Microsoft.Network/virtualNetworks/*` +- `Microsoft.Network/virtualNetworks/subnets/*` +- `Microsoft.Network/natGateways/*` The built-in `Contributor` role is a superset of these permissions. @@ -145,94 +148,94 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `iam.serviceAccountKeys.create` -* `iam.serviceAccountKeys.delete` -* `iam.serviceAccountKeys.get` -* `iam.serviceAccounts.create` -* `iam.serviceAccounts.delete` -* `iam.serviceAccounts.get` -* `resourcemanager.projects.getIamPolicy` -* `resourcemanager.projects.setIamPolicy` + +- `iam.serviceAccountKeys.create` +- `iam.serviceAccountKeys.delete` +- `iam.serviceAccountKeys.get` +- `iam.serviceAccounts.create` +- `iam.serviceAccounts.delete` +- `iam.serviceAccounts.get` +- `resourcemanager.projects.getIamPolicy` +- `resourcemanager.projects.setIamPolicy` Together, the built-in roles `roles/editor` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `compute.addresses.createInternal` -* `compute.addresses.deleteInternal` -* `compute.addresses.get` -* `compute.addresses.useInternal` -* `compute.backendServices.create` -* `compute.backendServices.delete` -* `compute.backendServices.get` -* `compute.backendServices.use` -* `compute.disks.create` -* `compute.firewalls.create` -* `compute.firewalls.delete` -* `compute.firewalls.get` -* `compute.firewalls.update` -* `compute.globalAddresses.create` -* `compute.globalAddresses.delete` -* `compute.globalAddresses.get` -* `compute.globalAddresses.use` -* `compute.globalForwardingRules.create` -* `compute.globalForwardingRules.delete` -* `compute.globalForwardingRules.get` -* `compute.globalForwardingRules.setLabels` -* `compute.globalOperations.get` -* `compute.healthChecks.create` -* `compute.healthChecks.delete` -* `compute.healthChecks.get` -* `compute.healthChecks.useReadOnly` -* `compute.instanceGroupManagers.create` -* `compute.instanceGroupManagers.delete` -* `compute.instanceGroupManagers.get` -* `compute.instanceGroupManagers.update` -* `compute.instanceGroups.create` -* `compute.instanceGroups.delete` -* `compute.instanceGroups.get` -* `compute.instanceGroups.update` -* `compute.instanceGroups.use` -* `compute.instances.create` -* `compute.instances.setLabels` -* `compute.instances.setMetadata` -* `compute.instances.setTags` -* `compute.instanceTemplates.create` -* `compute.instanceTemplates.delete` -* `compute.instanceTemplates.get` -* `compute.instanceTemplates.useReadOnly` -* `compute.networks.create` -* `compute.networks.delete` -* `compute.networks.get` -* `compute.networks.updatePolicy` -* `compute.routers.create` -* `compute.routers.delete` -* `compute.routers.get` -* `compute.routers.update` -* `compute.subnetworks.create` -* `compute.subnetworks.delete` -* `compute.subnetworks.get` -* `compute.subnetworks.use` -* `compute.targetTcpProxies.create` -* `compute.targetTcpProxies.delete` -* `compute.targetTcpProxies.get` -* `compute.targetTcpProxies.use` -* `iam.serviceAccounts.actAs` + +- `compute.addresses.createInternal` +- `compute.addresses.deleteInternal` +- `compute.addresses.get` +- `compute.addresses.useInternal` +- `compute.backendServices.create` +- `compute.backendServices.delete` +- `compute.backendServices.get` +- `compute.backendServices.use` +- `compute.disks.create` +- `compute.firewalls.create` +- `compute.firewalls.delete` +- `compute.firewalls.get` +- `compute.firewalls.update` +- `compute.globalAddresses.create` +- `compute.globalAddresses.delete` +- `compute.globalAddresses.get` +- `compute.globalAddresses.use` +- `compute.globalForwardingRules.create` +- `compute.globalForwardingRules.delete` +- `compute.globalForwardingRules.get` +- `compute.globalForwardingRules.setLabels` +- `compute.globalOperations.get` +- `compute.healthChecks.create` +- `compute.healthChecks.delete` +- `compute.healthChecks.get` +- `compute.healthChecks.useReadOnly` +- `compute.instanceGroupManagers.create` +- `compute.instanceGroupManagers.delete` +- `compute.instanceGroupManagers.get` +- `compute.instanceGroupManagers.update` +- `compute.instanceGroups.create` +- `compute.instanceGroups.delete` +- `compute.instanceGroups.get` +- `compute.instanceGroups.update` +- `compute.instanceGroups.use` +- `compute.instances.create` +- `compute.instances.setLabels` +- `compute.instances.setMetadata` +- `compute.instances.setTags` +- `compute.instanceTemplates.create` +- `compute.instanceTemplates.delete` +- `compute.instanceTemplates.get` +- `compute.instanceTemplates.useReadOnly` +- `compute.networks.create` +- `compute.networks.delete` +- `compute.networks.get` +- `compute.networks.updatePolicy` +- `compute.routers.create` +- `compute.routers.delete` +- `compute.routers.get` +- `compute.routers.update` +- `compute.subnetworks.create` +- `compute.subnetworks.delete` +- `compute.subnetworks.get` +- `compute.subnetworks.use` +- `compute.targetTcpProxies.create` +- `compute.targetTcpProxies.delete` +- `compute.targetTcpProxies.get` +- `compute.targetTcpProxies.use` +- `iam.serviceAccounts.actAs` Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -282,8 +285,8 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -293,8 +296,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -310,8 +313,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -334,8 +337,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -351,9 +354,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.12/overview/clouds.md b/docs/versioned_docs/version-2.12/overview/clouds.md index c56a623b1..dfc3d5307 100644 --- a/docs/versioned_docs/version-2.12/overview/clouds.md +++ b/docs/versioned_docs/version-2.12/overview/clouds.md @@ -31,7 +31,7 @@ This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -\* Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.12/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.12/overview/confidential-kubernetes.md index ca20df4de..bff8c3322 100644 --- a/docs/versioned_docs/version-2.12/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.12/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.12/overview/performance/compute.md b/docs/versioned_docs/version-2.12/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/versioned_docs/version-2.12/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/versioned_docs/version-2.12/overview/performance/performance.md b/docs/versioned_docs/version-2.12/overview/performance/performance.md index 7f22a693e..59bf86602 100644 --- a/docs/versioned_docs/version-2.12/overview/performance/performance.md +++ b/docs/versioned_docs/version-2.12/overview/performance/performance.md @@ -1,18 +1,10 @@ # Performance analysis of Constellation -This section provides a comprehensive examination of the performance characteristics of Constellation, encompassing various aspects, including runtime encryption, I/O benchmarks, and real-world applications. +This section provides a comprehensive examination of the performance characteristics of Constellation. -## Impact of runtime encryption on performance +## Runtime encryption -All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. - -### AMD and Azure benchmarking - -AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. - -### AMD and Google benchmarking - -Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. ## I/O performance benchmarks diff --git a/docs/versioned_docs/version-2.12/workflows/config.md b/docs/versioned_docs/version-2.12/workflows/config.md index 95f95aeec..4dab6bd50 100644 --- a/docs/versioned_docs/version-2.12/workflows/config.md +++ b/docs/versioned_docs/version-2.12/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,49 +14,49 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. @@ -75,8 +75,8 @@ AWS is currently investigating the issue. SNP-based attestation will be enabled as soon as a fix is verified. ::: - - + + Fill the desired VM type into the **instanceType** fields in the `constellation-conf.yml` file. @@ -86,7 +86,6 @@ By default, Constellation creates the node groups `control_plane_default` and `w If you require additional control-plane or worker groups with different instance types, zone placements, or disk sizes, you can add additional node groups to the `constellation-conf.yml` file. Each node group can be scaled individually. - Consider the following example for AWS: ```yaml @@ -120,9 +119,9 @@ You can use the field `zone` to specify what availability zone nodes of the grou On Azure, this field is empty by default and nodes are automatically spread across availability zones. Consult the documentation of your cloud provider for more information: -- [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) -- [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) -- [GCP](https://cloud.google.com/compute/docs/regions-zones) +* [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) +* [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) +* [GCP](https://cloud.google.com/compute/docs/regions-zones) ## Choosing a Kubernetes version @@ -134,8 +133,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -155,8 +154,8 @@ Note that CVMs are currently only supported in a few regions, check [Azure's pro Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -170,8 +169,8 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -195,16 +194,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -233,9 +232,9 @@ The following describes the configuration fields and how you obtain the required The user-assigned identity is used by instances of the cluster to access other cloud resources. For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -259,9 +258,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -292,9 +291,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.12/workflows/create.md b/docs/versioned_docs/version-2.12/workflows/create.md index ab7bf80ea..eccb2699a 100644 --- a/docs/versioned_docs/version-2.12/workflows/create.md +++ b/docs/versioned_docs/version-2.12/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -26,8 +26,8 @@ Before you create the cluster, make sure to have a [valid configuration file](./ ### Create - - + + ```bash constellation create @@ -35,8 +35,8 @@ constellation create *create* stores your cluster's state in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Terraform allows for an easier GitOps integration as well as meeting regulatory requirements. Since the Constellation CLI also uses Terraform under the hood, you can reuse the same Terraform files. @@ -77,8 +77,8 @@ yq eval '.infrastructure.initSecret ="$CONSTELL_INIT_SECRET"' --inplace constell yq eval '.infrastructure.clusterEndpoint ="$CONSTELL_IP"' --inplace constellation-state.yaml ``` - - + + ## The *init* step @@ -96,6 +96,6 @@ export KUBECONFIG="$PWD/constellation-admin.conf" 🏁 That's it. You've successfully created a Constellation cluster. - ### Troubleshooting + In case `init` fails, the CLI collects logs from the bootstrapping instance and stores them inside `constellation-cluster.log`. diff --git a/docs/versioned_docs/version-2.12/workflows/recovery.md b/docs/versioned_docs/version-2.12/workflows/recovery.md index 955981749..f2d5f22c1 100644 --- a/docs/versioned_docs/version-2.12/workflows/recovery.md +++ b/docs/versioned_docs/version-2.12/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.12/workflows/sbom.md b/docs/versioned_docs/version-2.12/workflows/sbom.md index 9ef6eb65c..6c1702dee 100644 --- a/docs/versioned_docs/version-2.12/workflows/sbom.md +++ b/docs/versioned_docs/version-2.12/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -11,13 +11,15 @@ SBOMs for Constellation are generated using [Syft](https://github.com/anchore/sy :::note The public key for Edgeless Systems' long-term code-signing key is: + ``` -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at https://edgeless.systems/es.pub and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -38,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.12/workflows/scale.md b/docs/versioned_docs/version-2.12/workflows/scale.md index 06898ad0c..63b727c7d 100644 --- a/docs/versioned_docs/version-2.12/workflows/scale.md +++ b/docs/versioned_docs/version-2.12/workflows/scale.md @@ -51,30 +51,30 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the worker ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + ## Control-plane node scaling @@ -82,30 +82,30 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.12/workflows/storage.md b/docs/versioned_docs/version-2.12/workflows/storage.md index 9e3d96346..06fbc4de6 100644 --- a/docs/versioned_docs/version-2.12/workflows/storage.md +++ b/docs/versioned_docs/version-2.12/workflows/storage.md @@ -21,30 +21,30 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. - - + + **Constellation CSI driver for AWS Elastic Block Store** Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -53,8 +53,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -82,8 +82,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -111,8 +111,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + AWS comes with two storage classes by default. @@ -140,8 +140,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) diff --git a/docs/versioned_docs/version-2.12/workflows/terminate.md b/docs/versioned_docs/version-2.12/workflows/terminate.md index 14a130d55..af7dbc1db 100644 --- a/docs/versioned_docs/version-2.12/workflows/terminate.md +++ b/docs/versioned_docs/version-2.12/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-state.yaml constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.12/workflows/troubleshooting.md b/docs/versioned_docs/version-2.12/workflows/troubleshooting.md index a3e25a0fe..c40e6496e 100644 --- a/docs/versioned_docs/version-2.12/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.12/workflows/troubleshooting.md @@ -101,8 +101,8 @@ To provide information during early stages of a node's boot process, Constellati You can view this information in the following places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -112,8 +112,8 @@ You can view this information in the following places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -128,16 +128,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ### Node shell access diff --git a/docs/versioned_docs/version-2.12/workflows/trusted-launch.md b/docs/versioned_docs/version-2.12/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.12/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.12/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.12/workflows/verify-cli.md b/docs/versioned_docs/version-2.12/workflows/verify-cli.md index 1280c51b0..e33569d37 100644 --- a/docs/versioned_docs/version-2.12/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.12/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -33,7 +33,11 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +:::info +This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. +::: + +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.13/architecture/attestation.md b/docs/versioned_docs/version-2.13/architecture/attestation.md index 576bc8865..8408cc5f0 100644 --- a/docs/versioned_docs/version-2.13/architecture/attestation.md +++ b/docs/versioned_docs/version-2.13/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,16 +217,16 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ### CVM verification To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. For verification of the CVM technology, Constellation may expose additional options in its config file. - - + + On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. @@ -248,18 +248,18 @@ You may customize certain parameters for verification of the attestation stateme More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. - - + + There is no additional configuration available for GCP. - - + + There is no additional configuration available for AWS. - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.13/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.13/getting-started/first-steps-local.md index 90a7317af..890a12654 100644 --- a/docs/versioned_docs/version-2.13/getting-started/first-steps-local.md +++ b/docs/versioned_docs/version-2.13/getting-started/first-steps-local.md @@ -45,8 +45,8 @@ sudo iptables -P FORWARD ACCEPT ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -74,8 +74,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -152,8 +152,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -206,8 +206,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -218,8 +218,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -247,8 +247,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/versioned_docs/version-2.13/getting-started/first-steps.md b/docs/versioned_docs/version-2.13/getting-started/first-steps.md index 040be5478..287e0737a 100644 --- a/docs/versioned_docs/version-2.13/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.13/getting-started/first-steps.md @@ -15,39 +15,39 @@ If you encounter any problem with the following steps, make sure to use the [lat 1. Create the [configuration file](../workflows/config.md) and state file for your cloud provider. - + - + ```bash constellation config generate azure ``` - + - + ```bash constellation config generate gcp ``` - + - + ```bash constellation config generate aws ``` - + - + 2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config @@ -62,9 +62,9 @@ If you encounter any problem with the following steps, make sure to use the [lat * `westeurope` * `southeastasia` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config @@ -74,9 +74,9 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - + - + ```bash constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config @@ -103,8 +103,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.13/getting-started/install.md b/docs/versioned_docs/version-2.13/getting-started/install.md index a1dc93cde..2fabcf0b1 100644 --- a/docs/versioned_docs/version-2.13/getting-started/install.md +++ b/docs/versioned_docs/version-2.13/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,39 +105,42 @@ If you don't have a cloud subscription, you can also set up a [local Constellati ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] -* `Microsoft.Compute` -* `Microsoft.Insights` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` + +- `Microsoft.Attestation` +- `Microsoft.Compute` +- `Microsoft.Insights` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` By default, Constellation tries to register these automatically if they haven't been registered before. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `*/register/action` \[1] -* `Microsoft.Authorization/roleAssignments/*` -* `Microsoft.Authorization/roleDefinitions/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Resources/subscriptions/resourcegroups/*` + +- `*/register/action` \[1] +- `Microsoft.Authorization/roleAssignments/*` +- `Microsoft.Authorization/roleDefinitions/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Resources/subscriptions/resourcegroups/*` The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] -* `Microsoft.Compute/virtualMachineScaleSets/*` -* `Microsoft.Insights/components/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Network/loadBalancers/*` -* `Microsoft.Network/loadBalancers/backendAddressPools/*` -* `Microsoft.Network/networkSecurityGroups/*` -* `Microsoft.Network/publicIPAddresses/*` -* `Microsoft.Network/virtualNetworks/*` -* `Microsoft.Network/virtualNetworks/subnets/*` -* `Microsoft.Network/natGateways/*` + +- `Microsoft.Attestation/attestationProviders/*` +- `Microsoft.Compute/virtualMachineScaleSets/*` +- `Microsoft.Insights/components/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Network/loadBalancers/*` +- `Microsoft.Network/loadBalancers/backendAddressPools/*` +- `Microsoft.Network/networkSecurityGroups/*` +- `Microsoft.Network/publicIPAddresses/*` +- `Microsoft.Network/virtualNetworks/*` +- `Microsoft.Network/virtualNetworks/subnets/*` +- `Microsoft.Network/natGateways/*` The built-in `Contributor` role is a superset of these permissions. @@ -145,94 +148,94 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `iam.serviceAccountKeys.create` -* `iam.serviceAccountKeys.delete` -* `iam.serviceAccountKeys.get` -* `iam.serviceAccounts.create` -* `iam.serviceAccounts.delete` -* `iam.serviceAccounts.get` -* `resourcemanager.projects.getIamPolicy` -* `resourcemanager.projects.setIamPolicy` + +- `iam.serviceAccountKeys.create` +- `iam.serviceAccountKeys.delete` +- `iam.serviceAccountKeys.get` +- `iam.serviceAccounts.create` +- `iam.serviceAccounts.delete` +- `iam.serviceAccounts.get` +- `resourcemanager.projects.getIamPolicy` +- `resourcemanager.projects.setIamPolicy` Together, the built-in roles `roles/editor` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `compute.addresses.createInternal` -* `compute.addresses.deleteInternal` -* `compute.addresses.get` -* `compute.addresses.useInternal` -* `compute.backendServices.create` -* `compute.backendServices.delete` -* `compute.backendServices.get` -* `compute.backendServices.use` -* `compute.disks.create` -* `compute.firewalls.create` -* `compute.firewalls.delete` -* `compute.firewalls.get` -* `compute.firewalls.update` -* `compute.globalAddresses.create` -* `compute.globalAddresses.delete` -* `compute.globalAddresses.get` -* `compute.globalAddresses.use` -* `compute.globalForwardingRules.create` -* `compute.globalForwardingRules.delete` -* `compute.globalForwardingRules.get` -* `compute.globalForwardingRules.setLabels` -* `compute.globalOperations.get` -* `compute.healthChecks.create` -* `compute.healthChecks.delete` -* `compute.healthChecks.get` -* `compute.healthChecks.useReadOnly` -* `compute.instanceGroupManagers.create` -* `compute.instanceGroupManagers.delete` -* `compute.instanceGroupManagers.get` -* `compute.instanceGroupManagers.update` -* `compute.instanceGroups.create` -* `compute.instanceGroups.delete` -* `compute.instanceGroups.get` -* `compute.instanceGroups.update` -* `compute.instanceGroups.use` -* `compute.instances.create` -* `compute.instances.setLabels` -* `compute.instances.setMetadata` -* `compute.instances.setTags` -* `compute.instanceTemplates.create` -* `compute.instanceTemplates.delete` -* `compute.instanceTemplates.get` -* `compute.instanceTemplates.useReadOnly` -* `compute.networks.create` -* `compute.networks.delete` -* `compute.networks.get` -* `compute.networks.updatePolicy` -* `compute.routers.create` -* `compute.routers.delete` -* `compute.routers.get` -* `compute.routers.update` -* `compute.subnetworks.create` -* `compute.subnetworks.delete` -* `compute.subnetworks.get` -* `compute.subnetworks.use` -* `compute.targetTcpProxies.create` -* `compute.targetTcpProxies.delete` -* `compute.targetTcpProxies.get` -* `compute.targetTcpProxies.use` -* `iam.serviceAccounts.actAs` + +- `compute.addresses.createInternal` +- `compute.addresses.deleteInternal` +- `compute.addresses.get` +- `compute.addresses.useInternal` +- `compute.backendServices.create` +- `compute.backendServices.delete` +- `compute.backendServices.get` +- `compute.backendServices.use` +- `compute.disks.create` +- `compute.firewalls.create` +- `compute.firewalls.delete` +- `compute.firewalls.get` +- `compute.firewalls.update` +- `compute.globalAddresses.create` +- `compute.globalAddresses.delete` +- `compute.globalAddresses.get` +- `compute.globalAddresses.use` +- `compute.globalForwardingRules.create` +- `compute.globalForwardingRules.delete` +- `compute.globalForwardingRules.get` +- `compute.globalForwardingRules.setLabels` +- `compute.globalOperations.get` +- `compute.healthChecks.create` +- `compute.healthChecks.delete` +- `compute.healthChecks.get` +- `compute.healthChecks.useReadOnly` +- `compute.instanceGroupManagers.create` +- `compute.instanceGroupManagers.delete` +- `compute.instanceGroupManagers.get` +- `compute.instanceGroupManagers.update` +- `compute.instanceGroups.create` +- `compute.instanceGroups.delete` +- `compute.instanceGroups.get` +- `compute.instanceGroups.update` +- `compute.instanceGroups.use` +- `compute.instances.create` +- `compute.instances.setLabels` +- `compute.instances.setMetadata` +- `compute.instances.setTags` +- `compute.instanceTemplates.create` +- `compute.instanceTemplates.delete` +- `compute.instanceTemplates.get` +- `compute.instanceTemplates.useReadOnly` +- `compute.networks.create` +- `compute.networks.delete` +- `compute.networks.get` +- `compute.networks.updatePolicy` +- `compute.routers.create` +- `compute.routers.delete` +- `compute.routers.get` +- `compute.routers.update` +- `compute.subnetworks.create` +- `compute.subnetworks.delete` +- `compute.subnetworks.get` +- `compute.subnetworks.use` +- `compute.targetTcpProxies.create` +- `compute.targetTcpProxies.delete` +- `compute.targetTcpProxies.get` +- `compute.targetTcpProxies.use` +- `iam.serviceAccounts.actAs` Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -282,8 +285,8 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -293,8 +296,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -310,8 +313,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -334,8 +337,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -351,9 +354,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.13/overview/clouds.md b/docs/versioned_docs/version-2.13/overview/clouds.md index c56a623b1..dfc3d5307 100644 --- a/docs/versioned_docs/version-2.13/overview/clouds.md +++ b/docs/versioned_docs/version-2.13/overview/clouds.md @@ -31,7 +31,7 @@ This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -\* Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.13/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.13/overview/confidential-kubernetes.md index ca20df4de..bff8c3322 100644 --- a/docs/versioned_docs/version-2.13/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.13/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.13/overview/performance/compute.md b/docs/versioned_docs/version-2.13/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/versioned_docs/version-2.13/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/versioned_docs/version-2.13/overview/performance/performance.md b/docs/versioned_docs/version-2.13/overview/performance/performance.md index 7f22a693e..59bf86602 100644 --- a/docs/versioned_docs/version-2.13/overview/performance/performance.md +++ b/docs/versioned_docs/version-2.13/overview/performance/performance.md @@ -1,18 +1,10 @@ # Performance analysis of Constellation -This section provides a comprehensive examination of the performance characteristics of Constellation, encompassing various aspects, including runtime encryption, I/O benchmarks, and real-world applications. +This section provides a comprehensive examination of the performance characteristics of Constellation. -## Impact of runtime encryption on performance +## Runtime encryption -All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. - -### AMD and Azure benchmarking - -AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. - -### AMD and Google benchmarking - -Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. ## I/O performance benchmarks diff --git a/docs/versioned_docs/version-2.13/workflows/config.md b/docs/versioned_docs/version-2.13/workflows/config.md index 95f95aeec..4dab6bd50 100644 --- a/docs/versioned_docs/version-2.13/workflows/config.md +++ b/docs/versioned_docs/version-2.13/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,49 +14,49 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. @@ -75,8 +75,8 @@ AWS is currently investigating the issue. SNP-based attestation will be enabled as soon as a fix is verified. ::: - - + + Fill the desired VM type into the **instanceType** fields in the `constellation-conf.yml` file. @@ -86,7 +86,6 @@ By default, Constellation creates the node groups `control_plane_default` and `w If you require additional control-plane or worker groups with different instance types, zone placements, or disk sizes, you can add additional node groups to the `constellation-conf.yml` file. Each node group can be scaled individually. - Consider the following example for AWS: ```yaml @@ -120,9 +119,9 @@ You can use the field `zone` to specify what availability zone nodes of the grou On Azure, this field is empty by default and nodes are automatically spread across availability zones. Consult the documentation of your cloud provider for more information: -- [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) -- [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) -- [GCP](https://cloud.google.com/compute/docs/regions-zones) +* [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) +* [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) +* [GCP](https://cloud.google.com/compute/docs/regions-zones) ## Choosing a Kubernetes version @@ -134,8 +133,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -155,8 +154,8 @@ Note that CVMs are currently only supported in a few regions, check [Azure's pro Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -170,8 +169,8 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -195,16 +194,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -233,9 +232,9 @@ The following describes the configuration fields and how you obtain the required The user-assigned identity is used by instances of the cluster to access other cloud resources. For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -259,9 +258,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -292,9 +291,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.13/workflows/create.md b/docs/versioned_docs/version-2.13/workflows/create.md index 605413cac..f347e9f27 100644 --- a/docs/versioned_docs/version-2.13/workflows/create.md +++ b/docs/versioned_docs/version-2.13/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -26,8 +26,8 @@ Before you create the cluster, make sure to have a [valid configuration file](./ ### Create - - + + ```bash constellation create @@ -35,8 +35,8 @@ constellation create *create* stores your cluster's state in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Self-managed infrastructure allows for more flexibility in the setup, by separating the infrastructure setup from the Constellation cluster management. This provides flexibility in DevOps and can meet potential regulatory requirements. @@ -55,7 +55,7 @@ management tooling of your choice. You need to keep the essential functionality :::info - On Azure, if the enforcement policy is set to `MAAFallback` in `constellation-config.yaml`, a manual update to the MAA provider's policy is necessary. + On Azure, a manual update to the MAA provider's policy is necessary. You can apply the update with the following command after creating the infrastructure, with `` being the URL of the MAA provider (i.e., `$(terraform output attestationURL | jq -r)`, when using the minimal Terraform configuration). ```bash @@ -72,8 +72,8 @@ Fill these outputs into the corresponding fields of the `Infrastructure` block i Continue with [initializing your cluster](#the-apply-step). - - + + ## The *apply* step diff --git a/docs/versioned_docs/version-2.13/workflows/recovery.md b/docs/versioned_docs/version-2.13/workflows/recovery.md index 955981749..f2d5f22c1 100644 --- a/docs/versioned_docs/version-2.13/workflows/recovery.md +++ b/docs/versioned_docs/version-2.13/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.13/workflows/sbom.md b/docs/versioned_docs/version-2.13/workflows/sbom.md index 9ef6eb65c..6c1702dee 100644 --- a/docs/versioned_docs/version-2.13/workflows/sbom.md +++ b/docs/versioned_docs/version-2.13/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -11,13 +11,15 @@ SBOMs for Constellation are generated using [Syft](https://github.com/anchore/sy :::note The public key for Edgeless Systems' long-term code-signing key is: + ``` -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at https://edgeless.systems/es.pub and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -38,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.13/workflows/scale.md b/docs/versioned_docs/version-2.13/workflows/scale.md index 06898ad0c..63b727c7d 100644 --- a/docs/versioned_docs/version-2.13/workflows/scale.md +++ b/docs/versioned_docs/version-2.13/workflows/scale.md @@ -51,30 +51,30 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the worker ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + ## Control-plane node scaling @@ -82,30 +82,30 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.13/workflows/storage.md b/docs/versioned_docs/version-2.13/workflows/storage.md index 9e3d96346..06fbc4de6 100644 --- a/docs/versioned_docs/version-2.13/workflows/storage.md +++ b/docs/versioned_docs/version-2.13/workflows/storage.md @@ -21,30 +21,30 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. - - + + **Constellation CSI driver for AWS Elastic Block Store** Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -53,8 +53,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -82,8 +82,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -111,8 +111,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + AWS comes with two storage classes by default. @@ -140,8 +140,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) diff --git a/docs/versioned_docs/version-2.13/workflows/terminate.md b/docs/versioned_docs/version-2.13/workflows/terminate.md index 062214c1c..e9599cb2b 100644 --- a/docs/versioned_docs/version-2.13/workflows/terminate.md +++ b/docs/versioned_docs/version-2.13/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-state.yaml constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.13/workflows/terraform-module.md b/docs/versioned_docs/version-2.13/workflows/terraform-module.md index e0534b9f5..07525cd27 100644 --- a/docs/versioned_docs/version-2.13/workflows/terraform-module.md +++ b/docs/versioned_docs/version-2.13/workflows/terraform-module.md @@ -1,12 +1,15 @@ # Use the Terraform module + You can manage a Constellation cluster through Terraform. The module package is available as part of the [GitHub release](https://github.com/edgelesssys/constellation/releases/). It consists of a convenience module for each cloud service provider (`{csp}-constellation`) that combines the IAM (`infrastructure/{csp}/iam`), infrastructure (`infrastructure/{csp}`), and constellation (`constellation-cluster`) modules. ## Prerequisites + - a Linux / Mac operating system - a Terraform installation of version `v1.4.4` or above ## Quick setup + The convenience module allows setting up a Constellation cluster with a single module. It's easiest to consume the module through a remote source, as shown below. This allows to upgrade the cluster to a newer Constellation version by simply updating the module source. @@ -18,6 +21,7 @@ The files are deleted on `terraform destroy`. ::: 1. Create a directory (workspace) for your Constellation cluster. + ```bash mkdir constellation-workspace cd constellation-workspace @@ -25,9 +29,9 @@ The files are deleted on `terraform destroy`. 1. Create a `main.tf` file to call the CSP specific Constellation module. - + - + ``` module "azure-constellation" { @@ -55,9 +59,9 @@ The files are deleted on `terraform destroy`. } ``` - + - + ``` module "aws-constellation" { @@ -86,9 +90,9 @@ The files are deleted on `terraform destroy`. } ``` - + - + ``` module "gcp-constellation" { @@ -118,25 +122,29 @@ The files are deleted on `terraform destroy`. } ``` - - + + 3. Initialize and apply the module. + ```bash terraform init terraform apply ``` ## Custom setup + If you need to separate IAM and cluster management or need custom infrastructure, you can also call the submodules individually. Look at the respective convenience module (`{csp}-constellation`) for how you can structure the module calls. The submodules are: + - `constellation-cluster`: manages the Constellation cluster - `fetch-image`: translates the Constellation image version to the image ID of the cloud service provider - `infrastructure/{csp}`: contains the cluster infrastructure resources - `infrastructure/iam/{csp}`: contains the IAM resources used within the cluster ## Cluster upgrades + :::tip For general information on cluster upgrades, see [Upgrade your cluster](./upgrade.md). ::: @@ -145,6 +153,7 @@ Using a [remote address as module source](https://developer.hashicorp.com/terraf 1. Update the `` variable inside the `source` field of the module. 2. Upgrade the Terraform module and provider dependencies and apply the Constellation upgrade. + ```bash terraform init -upgrade terraform apply diff --git a/docs/versioned_docs/version-2.13/workflows/troubleshooting.md b/docs/versioned_docs/version-2.13/workflows/troubleshooting.md index 05f515ed7..e8220c9a2 100644 --- a/docs/versioned_docs/version-2.13/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.13/workflows/troubleshooting.md @@ -101,8 +101,8 @@ To provide information during early stages of a node's boot process, Constellati You can view this information in the following places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -112,8 +112,8 @@ You can view this information in the following places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -128,16 +128,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ### Node shell access diff --git a/docs/versioned_docs/version-2.13/workflows/trusted-launch.md b/docs/versioned_docs/version-2.13/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.13/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.13/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.13/workflows/verify-cli.md b/docs/versioned_docs/version-2.13/workflows/verify-cli.md index 1280c51b0..e33569d37 100644 --- a/docs/versioned_docs/version-2.13/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.13/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -33,7 +33,11 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +:::info +This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. +::: + +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.14/architecture/attestation.md b/docs/versioned_docs/version-2.14/architecture/attestation.md index 04b85d8ad..415b41f47 100644 --- a/docs/versioned_docs/version-2.14/architecture/attestation.md +++ b/docs/versioned_docs/version-2.14/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,16 +217,16 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ### CVM verification To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. For verification of the CVM technology, Constellation may expose additional options in its config file. - - + + On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. @@ -248,13 +248,13 @@ You may customize certain parameters for verification of the attestation stateme More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. - - + + There is no additional configuration available for GCP. - - + + On AWS, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the VM and it's vTPM. @@ -275,8 +275,8 @@ You may customize certain parameters for verification of the attestation stateme This is the intermediate certificate for verifying the SEV-SNP report's signature. If it's not specified, the CLI fetches it from the AMD key distribution server. - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.14/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.14/getting-started/first-steps-local.md index 052d29eae..98f0302de 100644 --- a/docs/versioned_docs/version-2.14/getting-started/first-steps-local.md +++ b/docs/versioned_docs/version-2.14/getting-started/first-steps-local.md @@ -45,8 +45,8 @@ sudo iptables -P FORWARD ACCEPT ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -74,8 +74,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -145,8 +145,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -199,8 +199,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -211,8 +211,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -240,8 +240,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/versioned_docs/version-2.14/getting-started/first-steps.md b/docs/versioned_docs/version-2.14/getting-started/first-steps.md index c58d4a0ae..a1f6cba25 100644 --- a/docs/versioned_docs/version-2.14/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.14/getting-started/first-steps.md @@ -15,39 +15,39 @@ If you encounter any problem with the following steps, make sure to use the [lat 1. Create the [configuration file](../workflows/config.md) and state file for your cloud provider. - + - + ```bash constellation config generate azure ``` - + - + ```bash constellation config generate gcp ``` - + - + ```bash constellation config generate aws ``` - + - + 2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config @@ -62,9 +62,9 @@ If you encounter any problem with the following steps, make sure to use the [lat * `westeurope` * `southeastasia` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config @@ -74,9 +74,9 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - + - + ```bash constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config @@ -103,8 +103,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.14/getting-started/install.md b/docs/versioned_docs/version-2.14/getting-started/install.md index 01f9178ca..08e2315ef 100644 --- a/docs/versioned_docs/version-2.14/getting-started/install.md +++ b/docs/versioned_docs/version-2.14/getting-started/install.md @@ -22,8 +22,8 @@ If you prefer to use Terraform, you can alternatively use the [Terraform provide The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -39,8 +39,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -56,9 +56,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -74,9 +74,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -92,8 +92,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -109,12 +109,12 @@ If you don't have a cloud subscription, you can also set up a [local Constellati ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] +* `Microsoft.Attestation` * `Microsoft.Compute` * `Microsoft.Insights` * `Microsoft.ManagedIdentity` @@ -134,7 +134,7 @@ The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] +* `Microsoft.Attestation/attestationProviders/*` * `Microsoft.Compute/virtualMachineScaleSets/*` * `Microsoft.Insights/components/*` * `Microsoft.ManagedIdentity/userAssignedIdentities/*` @@ -152,10 +152,8 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -240,8 +238,8 @@ Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and ` Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -291,8 +289,8 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -302,8 +300,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -319,8 +317,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -343,8 +341,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -360,9 +358,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.14/overview/clouds.md b/docs/versioned_docs/version-2.14/overview/clouds.md index c56a623b1..dfc3d5307 100644 --- a/docs/versioned_docs/version-2.14/overview/clouds.md +++ b/docs/versioned_docs/version-2.14/overview/clouds.md @@ -31,7 +31,7 @@ This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -\* Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.14/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.14/overview/confidential-kubernetes.md index ca20df4de..bff8c3322 100644 --- a/docs/versioned_docs/version-2.14/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.14/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.14/overview/performance/compute.md b/docs/versioned_docs/version-2.14/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/versioned_docs/version-2.14/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/versioned_docs/version-2.14/overview/performance/performance.md b/docs/versioned_docs/version-2.14/overview/performance/performance.md index 7f22a693e..59bf86602 100644 --- a/docs/versioned_docs/version-2.14/overview/performance/performance.md +++ b/docs/versioned_docs/version-2.14/overview/performance/performance.md @@ -1,18 +1,10 @@ # Performance analysis of Constellation -This section provides a comprehensive examination of the performance characteristics of Constellation, encompassing various aspects, including runtime encryption, I/O benchmarks, and real-world applications. +This section provides a comprehensive examination of the performance characteristics of Constellation. -## Impact of runtime encryption on performance +## Runtime encryption -All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. - -### AMD and Azure benchmarking - -AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. - -### AMD and Google benchmarking - -Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. ## I/O performance benchmarks diff --git a/docs/versioned_docs/version-2.14/workflows/config.md b/docs/versioned_docs/version-2.14/workflows/config.md index 165100b81..81d2b49fd 100644 --- a/docs/versioned_docs/version-2.14/workflows/config.md +++ b/docs/versioned_docs/version-2.14/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,49 +14,49 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. @@ -67,8 +67,8 @@ If you are using the attestation variant `awsNitroTPM`, you can choose any of th The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. - - + + Fill the desired VM type into the **instanceType** fields in the `constellation-conf.yml` file. @@ -125,8 +125,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -146,8 +146,8 @@ Note that CVMs are currently only supported in a few regions, check [Azure's pro Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -161,8 +161,8 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -186,16 +186,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -224,9 +224,9 @@ The following describes the configuration fields and how you obtain the required The user-assigned identity is used by instances of the cluster to access other cloud resources. For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -250,9 +250,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -283,9 +283,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.14/workflows/create.md b/docs/versioned_docs/version-2.14/workflows/create.md index 54bc9dcbc..6074ebb16 100644 --- a/docs/versioned_docs/version-2.14/workflows/create.md +++ b/docs/versioned_docs/version-2.14/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -27,8 +27,8 @@ If you don't have a cloud subscription, you can also set up a [local Constellati Before you create the cluster, make sure to have a [valid configuration file](./config.md). - - + + ```bash constellation apply @@ -36,8 +36,8 @@ constellation apply `apply` stores the state of your cluster's cloud resources in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Self-managed infrastructure allows for more flexibility in the setup, by separating the infrastructure setup from the Constellation cluster management. This provides flexibility in DevOps and can meet potential regulatory requirements. @@ -56,7 +56,7 @@ management tooling of your choice. You need to keep the essential functionality :::info - On Azure, if the enforcement policy is set to `MAAFallback` in `constellation-config.yaml`, a manual update to the MAA provider's policy is necessary. + On Azure, a manual update to the MAA provider's policy is necessary. You can apply the update with the following command after creating the infrastructure, with `` being the URL of the MAA provider (i.e., `$(terraform output attestation_url | jq -r)`, when using the minimal Terraform configuration). ```bash @@ -77,8 +77,8 @@ With the required cloud resources set up, continue with initializing your cluste constellation apply --skip-phases=infrastructure ``` - - + + Finally, configure `kubectl` for your cluster: diff --git a/docs/versioned_docs/version-2.14/workflows/recovery.md b/docs/versioned_docs/version-2.14/workflows/recovery.md index 955981749..f2d5f22c1 100644 --- a/docs/versioned_docs/version-2.14/workflows/recovery.md +++ b/docs/versioned_docs/version-2.14/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.14/workflows/sbom.md b/docs/versioned_docs/version-2.14/workflows/sbom.md index 9ef6eb65c..6c1702dee 100644 --- a/docs/versioned_docs/version-2.14/workflows/sbom.md +++ b/docs/versioned_docs/version-2.14/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -11,13 +11,15 @@ SBOMs for Constellation are generated using [Syft](https://github.com/anchore/sy :::note The public key for Edgeless Systems' long-term code-signing key is: + ``` -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at https://edgeless.systems/es.pub and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -38,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.14/workflows/scale.md b/docs/versioned_docs/version-2.14/workflows/scale.md index 06898ad0c..63b727c7d 100644 --- a/docs/versioned_docs/version-2.14/workflows/scale.md +++ b/docs/versioned_docs/version-2.14/workflows/scale.md @@ -51,30 +51,30 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the worker ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + ## Control-plane node scaling @@ -82,30 +82,30 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.14/workflows/storage.md b/docs/versioned_docs/version-2.14/workflows/storage.md index 9e3d96346..06fbc4de6 100644 --- a/docs/versioned_docs/version-2.14/workflows/storage.md +++ b/docs/versioned_docs/version-2.14/workflows/storage.md @@ -21,30 +21,30 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. - - + + **Constellation CSI driver for AWS Elastic Block Store** Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -53,8 +53,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -82,8 +82,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -111,8 +111,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + AWS comes with two storage classes by default. @@ -140,8 +140,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) diff --git a/docs/versioned_docs/version-2.14/workflows/terminate.md b/docs/versioned_docs/version-2.14/workflows/terminate.md index 58c274bdd..2c45bebe3 100644 --- a/docs/versioned_docs/version-2.14/workflows/terminate.md +++ b/docs/versioned_docs/version-2.14/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-state.yaml constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.14/workflows/terraform-provider.md b/docs/versioned_docs/version-2.14/workflows/terraform-provider.md index 7de44a530..e831ccc9e 100644 --- a/docs/versioned_docs/version-2.14/workflows/terraform-provider.md +++ b/docs/versioned_docs/version-2.14/workflows/terraform-provider.md @@ -21,9 +21,9 @@ This example shows how to set up a Constellation cluster with the reference IAM 2. Use one of the [example configurations for using the Constellation Terraform provider](https://github.com/edgelesssys/constellation/tree/main/terraform-provider-constellation/examples/full) or create a `main.tf` file and fill it with the resources you want to create. The [Constellation Terraform provider documentation](https://registry.terraform.io/providers/edgelesssys/constellation/latest) offers thorough documentation on the resources and their attributes. 3. Initialize and apply the Terraform configuration. - + - + When creating a cluster on Azure, you need to manually patch the policy of the MAA provider before creating the Constellation cluster, as this feature isn't available in Azure's Terraform provider yet. The Constellation CLI provides a utility for patching, but you can also do it manually. @@ -57,8 +57,8 @@ This example shows how to set up a Constellation cluster with the reference IAM }; ``` - - + + Initialize the providers and apply the configuration. ```bash @@ -67,8 +67,8 @@ This example shows how to set up a Constellation cluster with the reference IAM ``` Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - - + + Initialize the providers and apply the configuration. ```bash @@ -77,8 +77,8 @@ This example shows how to set up a Constellation cluster with the reference IAM ``` Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - - + + 4. Connect to the cluster. ```bash diff --git a/docs/versioned_docs/version-2.14/workflows/troubleshooting.md b/docs/versioned_docs/version-2.14/workflows/troubleshooting.md index 633053e0b..64d7d3355 100644 --- a/docs/versioned_docs/version-2.14/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.14/workflows/troubleshooting.md @@ -101,8 +101,8 @@ To provide information during early stages of a node's boot process, Constellati You can view this information in the following places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -112,8 +112,8 @@ You can view this information in the following places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -128,16 +128,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ### Node shell access diff --git a/docs/versioned_docs/version-2.14/workflows/trusted-launch.md b/docs/versioned_docs/version-2.14/workflows/trusted-launch.md index 9bc7e785f..d6d01d8eb 100644 --- a/docs/versioned_docs/version-2.14/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.14/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: diff --git a/docs/versioned_docs/version-2.14/workflows/verify-cli.md b/docs/versioned_docs/version-2.14/workflows/verify-cli.md index 1280c51b0..e33569d37 100644 --- a/docs/versioned_docs/version-2.14/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.14/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -33,7 +33,11 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +:::info +This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. +::: + +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.15/architecture/attestation.md b/docs/versioned_docs/version-2.15/architecture/attestation.md index 3e184fa03..286b2466d 100644 --- a/docs/versioned_docs/version-2.15/architecture/attestation.md +++ b/docs/versioned_docs/version-2.15/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,16 +217,16 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ### CVM verification To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. For verification of the CVM technology, Constellation may expose additional options in its config file. - - + + On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. @@ -248,13 +248,13 @@ You may customize certain parameters for verification of the attestation stateme More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. - - + + There is no additional configuration available for GCP. - - + + On AWS, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the VM and it's vTPM. @@ -275,8 +275,8 @@ You may customize certain parameters for verification of the attestation stateme This is the intermediate certificate for verifying the SEV-SNP report's signature. If it's not specified, the CLI fetches it from the AMD key distribution server. - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.15/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.15/getting-started/first-steps-local.md index 052d29eae..98f0302de 100644 --- a/docs/versioned_docs/version-2.15/getting-started/first-steps-local.md +++ b/docs/versioned_docs/version-2.15/getting-started/first-steps-local.md @@ -45,8 +45,8 @@ sudo iptables -P FORWARD ACCEPT ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -74,8 +74,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -145,8 +145,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -199,8 +199,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -211,8 +211,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -240,8 +240,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/versioned_docs/version-2.15/getting-started/first-steps.md b/docs/versioned_docs/version-2.15/getting-started/first-steps.md index dc867bf77..a6efd758f 100644 --- a/docs/versioned_docs/version-2.15/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.15/getting-started/first-steps.md @@ -15,39 +15,39 @@ If you encounter any problem with the following steps, make sure to use the [lat 1. Create the [configuration file](../workflows/config.md) and state file for your cloud provider. - + - + ```bash constellation config generate azure ``` - + - + ```bash constellation config generate gcp ``` - + - + ```bash constellation config generate aws ``` - + - + 2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config @@ -68,9 +68,9 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config @@ -80,9 +80,9 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - + - + ```bash constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config @@ -109,8 +109,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.15/getting-started/install.md b/docs/versioned_docs/version-2.15/getting-started/install.md index 01f9178ca..08e2315ef 100644 --- a/docs/versioned_docs/version-2.15/getting-started/install.md +++ b/docs/versioned_docs/version-2.15/getting-started/install.md @@ -22,8 +22,8 @@ If you prefer to use Terraform, you can alternatively use the [Terraform provide The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -39,8 +39,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -56,9 +56,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -74,9 +74,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -92,8 +92,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -109,12 +109,12 @@ If you don't have a cloud subscription, you can also set up a [local Constellati ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] +* `Microsoft.Attestation` * `Microsoft.Compute` * `Microsoft.Insights` * `Microsoft.ManagedIdentity` @@ -134,7 +134,7 @@ The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] +* `Microsoft.Attestation/attestationProviders/*` * `Microsoft.Compute/virtualMachineScaleSets/*` * `Microsoft.Insights/components/*` * `Microsoft.ManagedIdentity/userAssignedIdentities/*` @@ -152,10 +152,8 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -240,8 +238,8 @@ Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and ` Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -291,8 +289,8 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -302,8 +300,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -319,8 +317,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -343,8 +341,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -360,9 +358,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.15/overview/clouds.md b/docs/versioned_docs/version-2.15/overview/clouds.md index 75acd17cd..934f6c710 100644 --- a/docs/versioned_docs/version-2.15/overview/clouds.md +++ b/docs/versioned_docs/version-2.15/overview/clouds.md @@ -19,7 +19,7 @@ The following table summarizes the state of features for different infrastructur | **1. Custom images** | Yes | Yes | Yes | Yes | | **2. SEV-SNP or TDX** | Yes | Yes | Yes | Depends on kernel/HV | | **3. Raw guest attestation** | Yes | Yes | Yes | Depends on kernel/HV | -| **4. Reviewable firmware** | No | No | Yes | Depends on kernel/HV | +| **4. Reviewable firmware** | No* | No | Yes | Depends on kernel/HV | | **5. Confidential measured boot** | Yes | No | No | Depends on kernel/HV | ## Microsoft Azure @@ -32,6 +32,8 @@ This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. + ## Google Cloud Platform (GCP) The [CVMs Generally Available in GCP](https://cloud.google.com/confidential-computing/confidential-vm/docs/confidential-vm-overview#amd_sev) are based on AMD SEV but don't have SNP features enabled. diff --git a/docs/versioned_docs/version-2.15/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.15/overview/confidential-kubernetes.md index ca20df4de..bff8c3322 100644 --- a/docs/versioned_docs/version-2.15/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.15/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.15/overview/performance/compute.md b/docs/versioned_docs/version-2.15/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/versioned_docs/version-2.15/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/versioned_docs/version-2.15/overview/performance/performance.md b/docs/versioned_docs/version-2.15/overview/performance/performance.md index 7f22a693e..59bf86602 100644 --- a/docs/versioned_docs/version-2.15/overview/performance/performance.md +++ b/docs/versioned_docs/version-2.15/overview/performance/performance.md @@ -1,18 +1,10 @@ # Performance analysis of Constellation -This section provides a comprehensive examination of the performance characteristics of Constellation, encompassing various aspects, including runtime encryption, I/O benchmarks, and real-world applications. +This section provides a comprehensive examination of the performance characteristics of Constellation. -## Impact of runtime encryption on performance +## Runtime encryption -All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. - -### AMD and Azure benchmarking - -AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. - -### AMD and Google benchmarking - -Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. ## I/O performance benchmarks diff --git a/docs/versioned_docs/version-2.15/workflows/config.md b/docs/versioned_docs/version-2.15/workflows/config.md index a5216510d..92ff9d040 100644 --- a/docs/versioned_docs/version-2.15/workflows/config.md +++ b/docs/versioned_docs/version-2.15/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,49 +14,49 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. @@ -67,8 +67,8 @@ If you are using the attestation variant `awsNitroTPM`, you can choose any of th The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. - - + + Fill the desired VM type into the `instanceType` fields in the `constellation-conf.yml` file. @@ -125,8 +125,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -151,8 +151,8 @@ You can find a list of all [regions in Azure's documentation](https://azure.micr Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -166,8 +166,8 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -191,16 +191,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -236,9 +236,9 @@ The following describes the configuration fields and how you obtain the required The user-assigned identity is used by instances of the cluster to access other cloud resources. For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -262,9 +262,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -295,9 +295,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.15/workflows/create.md b/docs/versioned_docs/version-2.15/workflows/create.md index 54bc9dcbc..6074ebb16 100644 --- a/docs/versioned_docs/version-2.15/workflows/create.md +++ b/docs/versioned_docs/version-2.15/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -27,8 +27,8 @@ If you don't have a cloud subscription, you can also set up a [local Constellati Before you create the cluster, make sure to have a [valid configuration file](./config.md). - - + + ```bash constellation apply @@ -36,8 +36,8 @@ constellation apply `apply` stores the state of your cluster's cloud resources in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Self-managed infrastructure allows for more flexibility in the setup, by separating the infrastructure setup from the Constellation cluster management. This provides flexibility in DevOps and can meet potential regulatory requirements. @@ -56,7 +56,7 @@ management tooling of your choice. You need to keep the essential functionality :::info - On Azure, if the enforcement policy is set to `MAAFallback` in `constellation-config.yaml`, a manual update to the MAA provider's policy is necessary. + On Azure, a manual update to the MAA provider's policy is necessary. You can apply the update with the following command after creating the infrastructure, with `` being the URL of the MAA provider (i.e., `$(terraform output attestation_url | jq -r)`, when using the minimal Terraform configuration). ```bash @@ -77,8 +77,8 @@ With the required cloud resources set up, continue with initializing your cluste constellation apply --skip-phases=infrastructure ``` - - + + Finally, configure `kubectl` for your cluster: diff --git a/docs/versioned_docs/version-2.15/workflows/recovery.md b/docs/versioned_docs/version-2.15/workflows/recovery.md index 9396bf8f2..592ab74af 100644 --- a/docs/versioned_docs/version-2.15/workflows/recovery.md +++ b/docs/versioned_docs/version-2.15/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via serial console output. In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.15/workflows/sbom.md b/docs/versioned_docs/version-2.15/workflows/sbom.md index 9ef6eb65c..6c1702dee 100644 --- a/docs/versioned_docs/version-2.15/workflows/sbom.md +++ b/docs/versioned_docs/version-2.15/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -11,13 +11,15 @@ SBOMs for Constellation are generated using [Syft](https://github.com/anchore/sy :::note The public key for Edgeless Systems' long-term code-signing key is: + ``` -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at https://edgeless.systems/es.pub and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -38,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.15/workflows/scale.md b/docs/versioned_docs/version-2.15/workflows/scale.md index 06898ad0c..63b727c7d 100644 --- a/docs/versioned_docs/version-2.15/workflows/scale.md +++ b/docs/versioned_docs/version-2.15/workflows/scale.md @@ -51,30 +51,30 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the worker ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + ## Control-plane node scaling @@ -82,30 +82,30 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.15/workflows/storage.md b/docs/versioned_docs/version-2.15/workflows/storage.md index 9e3d96346..06fbc4de6 100644 --- a/docs/versioned_docs/version-2.15/workflows/storage.md +++ b/docs/versioned_docs/version-2.15/workflows/storage.md @@ -21,30 +21,30 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. - - + + **Constellation CSI driver for AWS Elastic Block Store** Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -53,8 +53,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -82,8 +82,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -111,8 +111,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + AWS comes with two storage classes by default. @@ -140,8 +140,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) diff --git a/docs/versioned_docs/version-2.15/workflows/terminate.md b/docs/versioned_docs/version-2.15/workflows/terminate.md index 58c274bdd..2c45bebe3 100644 --- a/docs/versioned_docs/version-2.15/workflows/terminate.md +++ b/docs/versioned_docs/version-2.15/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-state.yaml constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.15/workflows/terraform-provider.md b/docs/versioned_docs/version-2.15/workflows/terraform-provider.md index 7de44a530..e831ccc9e 100644 --- a/docs/versioned_docs/version-2.15/workflows/terraform-provider.md +++ b/docs/versioned_docs/version-2.15/workflows/terraform-provider.md @@ -21,9 +21,9 @@ This example shows how to set up a Constellation cluster with the reference IAM 2. Use one of the [example configurations for using the Constellation Terraform provider](https://github.com/edgelesssys/constellation/tree/main/terraform-provider-constellation/examples/full) or create a `main.tf` file and fill it with the resources you want to create. The [Constellation Terraform provider documentation](https://registry.terraform.io/providers/edgelesssys/constellation/latest) offers thorough documentation on the resources and their attributes. 3. Initialize and apply the Terraform configuration. - + - + When creating a cluster on Azure, you need to manually patch the policy of the MAA provider before creating the Constellation cluster, as this feature isn't available in Azure's Terraform provider yet. The Constellation CLI provides a utility for patching, but you can also do it manually. @@ -57,8 +57,8 @@ This example shows how to set up a Constellation cluster with the reference IAM }; ``` - - + + Initialize the providers and apply the configuration. ```bash @@ -67,8 +67,8 @@ This example shows how to set up a Constellation cluster with the reference IAM ``` Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - - + + Initialize the providers and apply the configuration. ```bash @@ -77,8 +77,8 @@ This example shows how to set up a Constellation cluster with the reference IAM ``` Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - - + + 4. Connect to the cluster. ```bash diff --git a/docs/versioned_docs/version-2.15/workflows/trusted-launch.md b/docs/versioned_docs/version-2.15/workflows/trusted-launch.md index 9bc7e785f..d6d01d8eb 100644 --- a/docs/versioned_docs/version-2.15/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.15/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: diff --git a/docs/versioned_docs/version-2.15/workflows/verify-cli.md b/docs/versioned_docs/version-2.15/workflows/verify-cli.md index 1280c51b0..e33569d37 100644 --- a/docs/versioned_docs/version-2.15/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.15/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -33,7 +33,11 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +:::info +This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. +::: + +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.15/workflows/verify-cluster.md b/docs/versioned_docs/version-2.15/workflows/verify-cluster.md index 20d416790..b6595ebf2 100644 --- a/docs/versioned_docs/version-2.15/workflows/verify-cluster.md +++ b/docs/versioned_docs/version-2.15/workflows/verify-cluster.md @@ -88,6 +88,7 @@ The `verify` command also allows you to verify any Constellation deployment that * The IP address of a running Constellation cluster's [VerificationService](../architecture/microservices.md#verificationservice). The `VerificationService` is exposed via a `NodePort` service using the external IP address of your cluster. Run `kubectl get nodes -o wide` and look for `EXTERNAL-IP`. * The cluster's *clusterID*. See [cluster identity](../architecture/keys.md#cluster-identity) for more details. +* A `constellation-conf.yaml` file with the expected measurements of the cluster in your working directory. For example: diff --git a/docs/versioned_docs/version-2.16/architecture/attestation.md b/docs/versioned_docs/version-2.16/architecture/attestation.md index 5a8638964..a07b35e5a 100644 --- a/docs/versioned_docs/version-2.16/architecture/attestation.md +++ b/docs/versioned_docs/version-2.16/architecture/attestation.md @@ -78,15 +78,15 @@ The idea is that Constellation nodes should have verifiable integrity from the C The solution is a verifiable boot chain and an integrity-protected runtime environment. Constellation uses measured boot within CVMs, measuring each component in the boot process before executing it. -Outside of CC, it's usually implemented via TPMs. +Outside of CC, this is usually implemented via TPMs. CVM technologies differ in how they implement runtime measurements, but the general concepts are similar to those of a TPM. For simplicity, TPM terminology like *PCR* is used in the following. -When a Constellation node image boots inside a CVM, it uses measured boot for all stages and components of the boot chain. +When a Constellation node image boots inside a CVM, measured boot is used for all stages and components of the boot chain. This process goes up to the root filesystem. -The root filesystem is mounted read-only with integrity protection, guaranteeing forward integrity. +The root filesystem is mounted read-only with integrity protection. For the details on the image and boot stages see the [image architecture](../architecture/images.md) documentation. -Any changes to the image will inevitably also change the measured boot's PCR values. +Any changes to the image will inevitably also change the corresponding PCR values. To create a node attestation statement, the Constellation image obtains a CVM attestation statement from the hardware. This includes the runtime measurements and thereby binds the measured boot results to the CVM hardware measurement. @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -153,8 +153,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -184,8 +184,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -217,8 +217,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses a hypervisor-based vTPM for runtime measurements. @@ -249,16 +249,16 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ### CVM verification To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. For verification of the CVM technology, Constellation may expose additional options in its config file. - - + + On AWS, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the VM. @@ -279,8 +279,8 @@ You may customize certain parameters for verification of the attestation stateme This is the intermediate certificate for verifying the SEV-SNP report's signature. If it's not specified, the CLI fetches it from the AMD key distribution server. - - + + On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. @@ -302,22 +302,22 @@ You may customize certain parameters for verification of the attestation stateme More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. - - + + On GCP, AMD SEV-ES is used to provide runtime encryption to the VMs. The hypervisor-based vTPM is used to establish trust in the VM via [runtime measurements](#runtime-measurements). There is no additional configuration available for GCP. - - + + On STACKIT, AMD SEV-ES is used to provide runtime encryption to the VMs. The hypervisor-based vTPM is used to establish trust in the VM via [runtime measurements](#runtime-measurements). There is no additional configuration available for STACKIT. - - + + ## Cluster attestation @@ -341,32 +341,52 @@ When an initialized node tries to join another cluster, its measurements inevita The [*VerificationService*](microservices.md#verificationservice) provides an endpoint for obtaining its hardware-based remote attestation statement, which includes the runtime measurements. A user can [verify](../workflows/verify-cluster.md) this statement and compare the measurements against the configured ground truth and, thus, verify the identity and integrity of all Constellation components and the cluster configuration. Subsequently, the user knows that the entire cluster is in the expected state and is trustworthy. -## Chain of trust +## Putting it all together -So far, this page described how an entire Constellation cluster can be verified using hardware attestation capabilities and runtime measurements. -The last missing link is how the ground truth in the form of runtime measurements can be securely distributed to the verifying party. +This section puts the aforementioned concepts together and illustrate how trust into a Constellation cluster is established and maintained. -The build process of Constellation images also creates the ground truth runtime measurements. The builds of Constellation images are reproducible and the measurements of an image can be recalculated and verified by everyone. -With every release, Edgeless Systems publishes signed runtime measurements. +### CLI and node images -The CLI executable is also signed by Edgeless Systems. -You can [verify its signature](../workflows/verify-cli.md). +It all starts with the CLI executable. The CLI is signed by Edgeless Systems. To ensure non-repudiability for CLI releases, Edgeless Systems publishes corresponding signatures to the public ledger of the [sigstore project](https://www.sigstore.dev/). There's a [step-by-step guide](../workflows/verify-cli.md) on how to verify CLI signatures based on sigstore. -The CLI contains the public key required to verify signed runtime measurements from Edgeless Systems. -When a cluster is [created](../workflows/create.md) or [upgraded](../workflows/upgrade.md), the CLI automatically verifies the measurements for the selected image. +The CLI contains the latest runtime measurements of the Constellation node image for all supported cloud platforms. In case a different version of the node image is to be used, the corresponding runtime measurements can be fetched using the CLI's [fetch-measurements command](../reference/cli.md#constellation-config-fetch-measurements). This command downloads the runtime measurements and the corresponding signature from cdn.confidential.cloud. See for example the following files corresponding to node image v2.16.3: -Thus, there's a chain of trust based on cryptographic signatures, which goes from CLI to runtime measurements to images. This is illustrated in the following diagram. +* [Measurements](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json) +* [Signature](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json.sig) + +The CLI contains the long-term public key of Edgeless Systems to verify the signature of downloaded runtime measurements. + +### Cluster creation + +When a cluster is [created](../workflows/create.md), the CLI automatically verifies the runtime measurements of the *first node* using remote attestation. Based on this, the CLI and the first node set up a temporary TLS connection. This [aTLS](#attested-tls-atls) connection is used for two things: + +1. The CLI sends the [master secret](../architecture/keys.md#master-secret) of the to-be-created cluster to the CLI. The master secret is generated by the first node. +2. The first node sends a [kubeconfig file](https://www.redhat.com/sysadmin/kubeconfig) with Kubernetes credentials to the CLI. + +After this, the aTLS connection is closed and the first node bootstraps the Kubernetes cluster. All subsequent interactions between the CLI and the cluster go via the [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) server running inside the cluster. The CLI (and other tools like kubectl) use the credentials referenced by the kubeconfig file to authenticate themselves towards the Kubernetes API server and to establish a mTLS connection. + +The CLI connects to the Kubernetes API to write the runtime measurements for the applicable node image to etcd. The JoinService uses these runtime measurements to verify all nodes that join the cluster subsequently. + +### Chain of trust + +In summary, there's a chain of trust based on cryptographic signatures that goes from the user to the cluster via the CLI. This is illustrated in the following diagram. ```mermaid flowchart LR - A[Edgeless]-- "signs (cosign)" -->B[CLI] - C[User]-- "verifies (cosign)" -->B[CLI] - B[CLI]-- "contains" -->D["Public Key"] - A[Edgeless]-- "signs" -->E["Runtime measurements"] - D["Public key"]-- "verifies" -->E["Runtime measurements"] - E["Runtime measurements"]-- "verify" -->F["Constellation cluster"] + A[User]-- "verifies" -->B[CLI] + B[CLI]-- "verifies" -->C([Runtime measurements]) + D[Edgeless Systems]-- "signs" -->B[CLI] + D[Edgeless Systems]-- "signs" -->C([Runtime measurements]) + B[CLI]-- "verifies (remote attestation)" -->E[First node] + E[First node]-- "verifies (remote attestation)" -->F[Other nodes] + C([Runtime measurements]) -.-> E[First node] + C([Runtime measurements]) -.-> F[Other nodes] ``` +### Upgrades + +Whenever a cluster is [upgraded](../workflows/upgrade.md) to a new version of the node image, the CLI sends the corresponding runtime measurements via the Kubernetes API server. The new runtime measurements are stored in etcd within the cluster and replace any previous runtime measurements. The new runtime measurements are then used automatically by the JoinService for the verification of new nodes. + ## References [^1]: Linux IMA produces runtime measurements of user-space binaries. diff --git a/docs/versioned_docs/version-2.16/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.16/getting-started/first-steps-local.md index 052d29eae..98f0302de 100644 --- a/docs/versioned_docs/version-2.16/getting-started/first-steps-local.md +++ b/docs/versioned_docs/version-2.16/getting-started/first-steps-local.md @@ -45,8 +45,8 @@ sudo iptables -P FORWARD ACCEPT ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -74,8 +74,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -145,8 +145,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -199,8 +199,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -211,8 +211,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -240,8 +240,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/versioned_docs/version-2.16/getting-started/first-steps.md b/docs/versioned_docs/version-2.16/getting-started/first-steps.md index ff4975496..d82d93836 100644 --- a/docs/versioned_docs/version-2.16/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.16/getting-started/first-steps.md @@ -15,41 +15,41 @@ If you encounter any problem with the following steps, make sure to use the [lat 1. Create the [configuration file](../workflows/config.md) and state file for your cloud provider. - - + + ```bash constellation config generate aws ``` - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate stackit ``` - - + + 2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). - - + + ```bash constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config @@ -76,8 +76,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config @@ -98,8 +98,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). - - + + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config @@ -109,16 +109,16 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - - + + To use Constellation on STACKIT, the cluster will use the User Access Token (UAT) that's generated [during the install step](./install.md). After creating the accounts, fill in the STACKIT details in `constellation-conf.yaml` under `provider.openstack`: - - `stackitProjectID`: STACKIT project id (can be found after login on ) + * `stackitProjectID`: STACKIT project id (can be found after login on the [STACKIT portal](https://portal.stackit.cloud)) - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.16/getting-started/install.md b/docs/versioned_docs/version-2.16/getting-started/install.md index 99a8933e3..d52e43476 100644 --- a/docs/versioned_docs/version-2.16/getting-started/install.md +++ b/docs/versioned_docs/version-2.16/getting-started/install.md @@ -22,8 +22,8 @@ If you prefer to use Terraform, you can alternatively use the [Terraform provide The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -39,8 +39,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -56,9 +56,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -74,9 +74,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -92,9 +92,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -115,8 +115,8 @@ Invoke-WebRequest -OutFile ./constellation.exe -Uri 'https://github.com/edgeless 5. Click `New` 6. Enter the path to the folder containing the binary you want on your PATH: `C:\Program Files\Constellation\bin` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -132,8 +132,8 @@ If you don't have a cloud subscription, you can also set up a [local Constellati ### Required permissions - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -183,12 +183,12 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] +* `Microsoft.Attestation` * `Microsoft.Compute` * `Microsoft.Insights` * `Microsoft.ManagedIdentity` @@ -208,7 +208,7 @@ The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] +* `Microsoft.Attestation/attestationProviders/*` * `Microsoft.Compute/virtualMachineScaleSets/*` * `Microsoft.Insights/components/*` * `Microsoft.ManagedIdentity/userAssignedIdentities/*` @@ -226,10 +226,8 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -314,16 +312,16 @@ Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and ` Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + Constellation on STACKIT requires a User Access Token (UAT) for the OpenStack API and a STACKIT service account. The UAT already has all required permissions by default. The STACKIT service account needs the `editor` role to create STACKIT LoadBalancers. Look at the [STACKIT documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) on how to create the service account and assign the role. - - + + ### Authentication @@ -333,8 +331,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -350,8 +348,8 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - - + + **Testing** @@ -367,8 +365,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -391,8 +389,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + You need to authenticate with the infrastructure API (OpenStack) and create a service account (STACKIT API). @@ -422,9 +420,9 @@ You need to authenticate with the infrastructure API (OpenStack) and create a se {"STACKIT_SERVICE_ACCOUNT_TOKEN":"REPLACE_WITH_TOKEN"} ``` - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.16/getting-started/marketplaces.md b/docs/versioned_docs/version-2.16/getting-started/marketplaces.md index b16d796d2..a6763a42a 100644 --- a/docs/versioned_docs/version-2.16/getting-started/marketplaces.md +++ b/docs/versioned_docs/version-2.16/getting-started/marketplaces.md @@ -4,8 +4,8 @@ Constellation is available through the Marketplaces of AWS, Azure, GCP, and STAC This document explains how to run Constellation with the dynamically billed cloud marketplace images. - - + + To use Constellation's marketplace images, ensure that you are subscribed to the [marketplace offering](https://aws.amazon.com/marketplace/pp/prodview-2mbn65nv57oys) through the web portal. @@ -15,8 +15,8 @@ Then, enable the use of marketplace images in your Constellation `constellation- yq eval -i ".provider.aws.useMarketplaceImage = true" constellation-conf.yaml ``` - - + + Constellation has a private marketplace plan. Please [contact us](https://www.edgeless.systems/enterprise-support/) to gain access. @@ -32,8 +32,8 @@ Then, enable the use of marketplace images in your Constellation `constellation- yq eval -i ".provider.azure.useMarketplaceImage = true" constellation-conf.yaml ``` - - + + To use a marketplace image, ensure that the account is entitled to use marketplace images by Edgeless Systems by accepting the terms through the [web portal](https://console.cloud.google.com/marketplace/vm/config/edgeless-systems-public/constellation). @@ -43,13 +43,13 @@ Then, enable the use of marketplace images in your Constellation `constellation- yq eval -i ".provider.gcp.useMarketplaceImage = true" constellation-conf.yaml ``` - - + + On STACKIT, the selected Constellation image is always a marketplace image. You can find more information on the STACKIT portal. - - + + Ensure that the cluster uses an official release image version (i.e., `.image=vX.Y.Z` in the `constellation-conf.yaml` file). diff --git a/docs/versioned_docs/version-2.16/overview/clouds.md b/docs/versioned_docs/version-2.16/overview/clouds.md index a7b1361e8..5f19d8877 100644 --- a/docs/versioned_docs/version-2.16/overview/clouds.md +++ b/docs/versioned_docs/version-2.16/overview/clouds.md @@ -19,7 +19,7 @@ The following table summarizes the state of features for different infrastructur | **1. Custom images** | Yes | Yes | Yes | Yes | Yes | | **2. SEV-SNP or TDX** | Yes | Yes | Yes | No | Depends on kernel/HV | | **3. Raw guest attestation** | Yes | Yes | Yes | No | Depends on kernel/HV | -| **4. Reviewable firmware** | No | No | Yes | No | Depends on kernel/HV | +| **4. Reviewable firmware** | No* | No | Yes | No | Depends on kernel/HV | | **5. Confidential measured boot** | Yes | No | No | No | Depends on kernel/HV | ## Microsoft Azure @@ -32,6 +32,8 @@ This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. + ## Google Cloud Platform (GCP) The [CVMs Generally Available in GCP](https://cloud.google.com/confidential-computing/confidential-vm/docs/confidential-vm-overview#amd_sev) are based on AMD SEV but don't have SNP features enabled. diff --git a/docs/versioned_docs/version-2.16/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.16/overview/confidential-kubernetes.md index ca20df4de..bff8c3322 100644 --- a/docs/versioned_docs/version-2.16/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.16/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.16/overview/performance/compute.md b/docs/versioned_docs/version-2.16/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/versioned_docs/version-2.16/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/versioned_docs/version-2.16/overview/performance/performance.md b/docs/versioned_docs/version-2.16/overview/performance/performance.md index 7f22a693e..59bf86602 100644 --- a/docs/versioned_docs/version-2.16/overview/performance/performance.md +++ b/docs/versioned_docs/version-2.16/overview/performance/performance.md @@ -1,18 +1,10 @@ # Performance analysis of Constellation -This section provides a comprehensive examination of the performance characteristics of Constellation, encompassing various aspects, including runtime encryption, I/O benchmarks, and real-world applications. +This section provides a comprehensive examination of the performance characteristics of Constellation. -## Impact of runtime encryption on performance +## Runtime encryption -All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. - -### AMD and Azure benchmarking - -AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. - -### AMD and Google benchmarking - -Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. ## I/O performance benchmarks diff --git a/docs/versioned_docs/version-2.16/workflows/config.md b/docs/versioned_docs/version-2.16/workflows/config.md index c59207054..120bf8ed7 100644 --- a/docs/versioned_docs/version-2.16/workflows/config.md +++ b/docs/versioned_docs/version-2.16/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,44 +14,44 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate aws ``` - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate stackit ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. @@ -62,20 +62,20 @@ If you are using the attestation variant `awsNitroTPM`, you can choose any of th The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m1a.4cd` VMs (4 vCPUs, 30 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. @@ -93,8 +93,8 @@ You can choose any of the SEV-enabled instance types. You can find a list of all The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. - - + + Fill the desired VM type into the `instanceType` fields in the `constellation-conf.yml` file. @@ -153,8 +153,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -178,8 +178,8 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -204,8 +204,8 @@ You can find a list of all [regions in Azure's documentation](https://azure.micr Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -219,21 +219,21 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + STACKIT requires manual creation and configuration of service accounts. Look at the [first steps](../getting-started/first-steps.md) for more information. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -264,8 +264,8 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -301,8 +301,8 @@ The following describes the configuration fields and how you obtain the required The user-assigned identity is used by instances of the cluster to access other cloud resources. For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). - - + + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -326,13 +326,13 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - - + + STACKIT requires manual creation and configuration of service accounts. Look at the [first steps](../getting-started/first-steps.md) for more information. - - + +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.16/workflows/create.md b/docs/versioned_docs/version-2.16/workflows/create.md index 54bc9dcbc..6074ebb16 100644 --- a/docs/versioned_docs/version-2.16/workflows/create.md +++ b/docs/versioned_docs/version-2.16/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -27,8 +27,8 @@ If you don't have a cloud subscription, you can also set up a [local Constellati Before you create the cluster, make sure to have a [valid configuration file](./config.md). - - + + ```bash constellation apply @@ -36,8 +36,8 @@ constellation apply `apply` stores the state of your cluster's cloud resources in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Self-managed infrastructure allows for more flexibility in the setup, by separating the infrastructure setup from the Constellation cluster management. This provides flexibility in DevOps and can meet potential regulatory requirements. @@ -56,7 +56,7 @@ management tooling of your choice. You need to keep the essential functionality :::info - On Azure, if the enforcement policy is set to `MAAFallback` in `constellation-config.yaml`, a manual update to the MAA provider's policy is necessary. + On Azure, a manual update to the MAA provider's policy is necessary. You can apply the update with the following command after creating the infrastructure, with `` being the URL of the MAA provider (i.e., `$(terraform output attestation_url | jq -r)`, when using the minimal Terraform configuration). ```bash @@ -77,8 +77,8 @@ With the required cloud resources set up, continue with initializing your cluste constellation apply --skip-phases=infrastructure ``` - - + + Finally, configure `kubectl` for your cluster: diff --git a/docs/versioned_docs/version-2.16/workflows/lb.md b/docs/versioned_docs/version-2.16/workflows/lb.md index 11e403237..868e61076 100644 --- a/docs/versioned_docs/version-2.16/workflows/lb.md +++ b/docs/versioned_docs/version-2.16/workflows/lb.md @@ -4,12 +4,25 @@ Constellation integrates the native load balancers of each CSP. Therefore, to ex ## Internet-facing LB service on AWS -To expose your application service externally you might want to use a Kubernetes Service of type `LoadBalancer`. On AWS, load-balancing is achieved through the [AWS Load Balancing Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller) as in the managed EKS. +To expose your application service externally you might want to use a Kubernetes Service of type `LoadBalancer`. On AWS, load-balancing is achieved through the [AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller) as in the managed EKS. -Since recent versions, the controller deploy an internal LB by default requiring to set an annotation `service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing` to have an internet-facing LB. For more details, see the [official docs](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/service/nlb/). +Since recent versions, the controller deploy an internal LB by default requiring to set an annotation `service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing` to have an internet-facing LB. For more details, see the [official docs](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/guide/service/nlb/). For general information on LB with AWS see [Network load balancing on Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/network-load-balancing.html). :::caution Before terminating the cluster, all LB backed services should be deleted, so that the controller can cleanup the related resources. ::: + +## Ingress on AWS + +The AWS Load Balancer Controller also provisions `Ingress` resources of class `alb`. +AWS Application Load Balancers (ALBs) can be configured with a [`target-type`](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/guide/ingress/annotations/#target-type). +The target type `ip` requires using the EKS container network solution, which makes it incompatible with Constellation. +If a service can be exposed on a `NodePort`, the target type `instance` can be used. + +See [Application load balancing on Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html) for more information. + +:::caution +Ingress handlers backed by AWS ALBs reside outside the Constellation cluster, so they shouldn't be handling sensitive traffic! +::: diff --git a/docs/versioned_docs/version-2.16/workflows/recovery.md b/docs/versioned_docs/version-2.16/workflows/recovery.md index aea370e2f..50cd7ee72 100644 --- a/docs/versioned_docs/version-2.16/workflows/recovery.md +++ b/docs/versioned_docs/version-2.16/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via serial console output. In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -47,8 +47,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -82,8 +82,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the STACKIT portal to view all servers in your project. Select individual control plane nodes `--control-plane--` and check that enough members are in a *Running* state. @@ -149,8 +149,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.16/workflows/sbom.md b/docs/versioned_docs/version-2.16/workflows/sbom.md index 9ef6eb65c..6c1702dee 100644 --- a/docs/versioned_docs/version-2.16/workflows/sbom.md +++ b/docs/versioned_docs/version-2.16/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -11,13 +11,15 @@ SBOMs for Constellation are generated using [Syft](https://github.com/anchore/sy :::note The public key for Edgeless Systems' long-term code-signing key is: + ``` -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at https://edgeless.systems/es.pub and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -38,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.16/workflows/scale.md b/docs/versioned_docs/version-2.16/workflows/scale.md index 0b52b9540..28f19e3f1 100644 --- a/docs/versioned_docs/version-2.16/workflows/scale.md +++ b/docs/versioned_docs/version-2.16/workflows/scale.md @@ -51,36 +51,36 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Go to Auto Scaling Groups and select the worker ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + Dynamic cluster scaling isn't yet supported for STACKIT. Support will be introduced in one of the upcoming releases. - - + + ## Control-plane node scaling @@ -88,35 +88,35 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - - + + 1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + Dynamic cluster scaling isn't yet supported for STACKIT. Support will be introduced in one of the upcoming releases. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.16/workflows/storage.md b/docs/versioned_docs/version-2.16/workflows/storage.md index f1344d6ad..a5c52be90 100644 --- a/docs/versioned_docs/version-2.16/workflows/storage.md +++ b/docs/versioned_docs/version-2.16/workflows/storage.md @@ -21,37 +21,37 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for AWS Elastic Block Store** Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. - - + + **Constellation CSI driver for STACKIT / OpenStack Cinder** Mount [Cinder](https://docs.openstack.org/cinder/latest/) block storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-cloud-provider-openstack) for more information. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -60,8 +60,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + AWS comes with two storage classes by default. @@ -89,8 +89,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + Azure comes with two storage classes by default. @@ -118,8 +118,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -147,8 +147,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + STACKIT comes with two storage classes by default. @@ -176,8 +176,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) diff --git a/docs/versioned_docs/version-2.16/workflows/terminate.md b/docs/versioned_docs/version-2.16/workflows/terminate.md index 58c274bdd..2c45bebe3 100644 --- a/docs/versioned_docs/version-2.16/workflows/terminate.md +++ b/docs/versioned_docs/version-2.16/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-state.yaml constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.16/workflows/terraform-provider.md b/docs/versioned_docs/version-2.16/workflows/terraform-provider.md index 8a3cedc62..ed8f46eda 100644 --- a/docs/versioned_docs/version-2.16/workflows/terraform-provider.md +++ b/docs/versioned_docs/version-2.16/workflows/terraform-provider.md @@ -21,8 +21,9 @@ This example shows how to set up a Constellation cluster with the reference IAM 2. Use one of the [example configurations for using the Constellation Terraform provider](https://github.com/edgelesssys/constellation/tree/main/terraform-provider-constellation/examples/full) or create a `main.tf` file and fill it with the resources you want to create. The [Constellation Terraform provider documentation](https://registry.terraform.io/providers/edgelesssys/constellation/latest) offers thorough documentation on the resources and their attributes. 3. Initialize and apply the Terraform configuration. - - + + + Initialize the providers and apply the configuration. ```bash @@ -31,8 +32,8 @@ This example shows how to set up a Constellation cluster with the reference IAM ``` Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - - + + When creating a cluster on Azure, you need to manually patch the policy of the MAA provider before creating the Constellation cluster, as this feature isn't available in Azure's Terraform provider yet. The Constellation CLI provides a utility for patching, but you can also do it manually. @@ -66,8 +67,8 @@ This example shows how to set up a Constellation cluster with the reference IAM }; ``` - - + + Initialize the providers and apply the configuration. ```bash @@ -76,8 +77,8 @@ This example shows how to set up a Constellation cluster with the reference IAM ``` Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - - + + Initialize the providers and apply the configuration. ```bash @@ -86,9 +87,9 @@ This example shows how to set up a Constellation cluster with the reference IAM ``` Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. - + - + 4. Connect to the cluster. ```bash diff --git a/docs/versioned_docs/version-2.16/workflows/troubleshooting.md b/docs/versioned_docs/version-2.16/workflows/troubleshooting.md index 3c952dddc..195bce1cc 100644 --- a/docs/versioned_docs/version-2.16/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.16/workflows/troubleshooting.md @@ -40,6 +40,24 @@ Or alternatively, for `terminate`: ARM_SKIP_PROVIDER_REGISTRATION=true constellation terminate ``` +### Azure: Can't update attestation policy + +On Azure, you may receive the following error when running `apply` from within an Azure environment, e.g., an Azure VM: + +```shell-session +An error occurred: patching policies: updating attestation policy: unexpected status code: 403 Forbidden +``` + +The problem occurs because the Azure SDK we use internally attempts to [authenticate towards the Azure API with the managed identity of your current environment instead of the Azure CLI token](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential). + +We decided not to deviate from this behavior and comply with the ordering of credentials. + +A solution is to add the [required permissions](../getting-started/install.md#required-permissions) to the managed identity of your environment. For example, the managed identity of your Azure VM, instead of the account that you've authenticated with in the Azure CLI. + +If your setup requires a change in the ordering of credentials, please open an issue and explain your desired behavior. + + + ### Nodes fail to join with error `untrusted measurement value` This error indicates that a node's [attestation statement](../architecture/attestation.md) contains measurements that don't match the trusted values expected by the [JoinService](../architecture/microservices.md#joinservice). diff --git a/docs/versioned_docs/version-2.16/workflows/trusted-launch.md b/docs/versioned_docs/version-2.16/workflows/trusted-launch.md index 9bc7e785f..d6d01d8eb 100644 --- a/docs/versioned_docs/version-2.16/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.16/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: diff --git a/docs/versioned_docs/version-2.16/workflows/verify-cli.md b/docs/versioned_docs/version-2.16/workflows/verify-cli.md index 78341f314..e33569d37 100644 --- a/docs/versioned_docs/version-2.16/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.16/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -37,7 +37,7 @@ You don't need to verify the Constellation node images. This is done automatical This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. ::: -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.16/workflows/verify-cluster.md b/docs/versioned_docs/version-2.16/workflows/verify-cluster.md index 20d416790..b6595ebf2 100644 --- a/docs/versioned_docs/version-2.16/workflows/verify-cluster.md +++ b/docs/versioned_docs/version-2.16/workflows/verify-cluster.md @@ -88,6 +88,7 @@ The `verify` command also allows you to verify any Constellation deployment that * The IP address of a running Constellation cluster's [VerificationService](../architecture/microservices.md#verificationservice). The `VerificationService` is exposed via a `NodePort` service using the external IP address of your cluster. Run `kubectl get nodes -o wide` and look for `EXTERNAL-IP`. * The cluster's *clusterID*. See [cluster identity](../architecture/keys.md#cluster-identity) for more details. +* A `constellation-conf.yaml` file with the expected measurements of the cluster in your working directory. For example: diff --git a/docs/versioned_docs/version-2.17/_media/SLSA-Badge-full-level3.svg b/docs/versioned_docs/version-2.17/_media/SLSA-Badge-full-level3.svg new file mode 100644 index 000000000..7154d4a13 --- /dev/null +++ b/docs/versioned_docs/version-2.17/_media/SLSA-Badge-full-level3.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_fio_azure_bw.png b/docs/versioned_docs/version-2.17/_media/benchmark_fio_azure_bw.png new file mode 100644 index 000000000..a82ebe2d0 Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_fio_azure_bw.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_fio_azure_iops.png b/docs/versioned_docs/version-2.17/_media/benchmark_fio_azure_iops.png new file mode 100644 index 000000000..1723257a8 Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_fio_azure_iops.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_fio_gcp_bw.png b/docs/versioned_docs/version-2.17/_media/benchmark_fio_gcp_bw.png new file mode 100644 index 000000000..4f0ecc94b Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_fio_gcp_bw.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_fio_gcp_iops.png b/docs/versioned_docs/version-2.17/_media/benchmark_fio_gcp_iops.png new file mode 100644 index 000000000..571086da2 Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_fio_gcp_iops.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_net_p2p_azure.png b/docs/versioned_docs/version-2.17/_media/benchmark_net_p2p_azure.png new file mode 100644 index 000000000..9130349c7 Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_net_p2p_azure.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_net_p2p_gcp.png b/docs/versioned_docs/version-2.17/_media/benchmark_net_p2p_gcp.png new file mode 100644 index 000000000..a41557e96 Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_net_p2p_gcp.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_net_p2svc_azure.png b/docs/versioned_docs/version-2.17/_media/benchmark_net_p2svc_azure.png new file mode 100644 index 000000000..d83e17f5a Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_net_p2svc_azure.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_net_p2svc_gcp.png b/docs/versioned_docs/version-2.17/_media/benchmark_net_p2svc_gcp.png new file mode 100644 index 000000000..55916a1de Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_net_p2svc_gcp.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/max_latency.png b/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/max_latency.png new file mode 100644 index 000000000..696250181 Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/max_latency.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/mean_latency.png b/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/mean_latency.png new file mode 100644 index 000000000..3b43298ac Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/mean_latency.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/min_latency.png b/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/min_latency.png new file mode 100644 index 000000000..1046df67e Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/min_latency.png differ diff --git a/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/p99_latency.png b/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/p99_latency.png new file mode 100644 index 000000000..0190118b2 Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/benchmark_vault/5replicas/p99_latency.png differ diff --git a/docs/versioned_docs/version-2.17/_media/concept-constellation.svg b/docs/versioned_docs/version-2.17/_media/concept-constellation.svg new file mode 100644 index 000000000..30d32bf6d --- /dev/null +++ b/docs/versioned_docs/version-2.17/_media/concept-constellation.svg @@ -0,0 +1,460 @@ + + diff --git a/docs/versioned_docs/version-2.17/_media/concept-managed.svg b/docs/versioned_docs/version-2.17/_media/concept-managed.svg new file mode 100644 index 000000000..5645a608f --- /dev/null +++ b/docs/versioned_docs/version-2.17/_media/concept-managed.svg @@ -0,0 +1,591 @@ + + diff --git a/docs/versioned_docs/version-2.17/_media/constellation_oneline.svg b/docs/versioned_docs/version-2.17/_media/constellation_oneline.svg new file mode 100644 index 000000000..4e354958a --- /dev/null +++ b/docs/versioned_docs/version-2.17/_media/constellation_oneline.svg @@ -0,0 +1,52 @@ + + + + + + + + diff --git a/docs/versioned_docs/version-2.17/_media/example-emojivoto.jpg b/docs/versioned_docs/version-2.17/_media/example-emojivoto.jpg new file mode 100644 index 000000000..4be0d5b26 Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/example-emojivoto.jpg differ diff --git a/docs/versioned_docs/version-2.17/_media/example-online-boutique.jpg b/docs/versioned_docs/version-2.17/_media/example-online-boutique.jpg new file mode 100644 index 000000000..026f0d865 Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/example-online-boutique.jpg differ diff --git a/docs/versioned_docs/version-2.17/_media/recovery-gcp-serial-console-link.png b/docs/versioned_docs/version-2.17/_media/recovery-gcp-serial-console-link.png new file mode 100644 index 000000000..eb67f0e99 Binary files /dev/null and b/docs/versioned_docs/version-2.17/_media/recovery-gcp-serial-console-link.png differ diff --git a/docs/versioned_docs/version-2.17/_media/tcb.svg b/docs/versioned_docs/version-2.17/_media/tcb.svg new file mode 100644 index 000000000..e5bcb5b95 --- /dev/null +++ b/docs/versioned_docs/version-2.17/_media/tcb.svg @@ -0,0 +1,535 @@ + + diff --git a/docs/versioned_docs/version-2.17/architecture/attestation.md b/docs/versioned_docs/version-2.17/architecture/attestation.md new file mode 100644 index 000000000..a07b35e5a --- /dev/null +++ b/docs/versioned_docs/version-2.17/architecture/attestation.md @@ -0,0 +1,394 @@ +# Attestation + +This page explains Constellation's attestation process and highlights the cornerstones of its trust model. + +## Terms + +The following lists terms and concepts that help to understand the attestation concept of Constellation. + +### Trusted Platform Module (TPM) + +A TPM chip is a dedicated tamper-resistant crypto-processor. +It can securely store artifacts such as passwords, certificates, encryption keys, or *runtime measurements* (more on this below). +When a TPM is implemented in software, it's typically called a *virtual* TPM (vTPM). + +### Runtime measurement + +A runtime measurement is a cryptographic hash of the memory pages of a so called *runtime component*. Runtime components of interest typically include a system's bootloader or OS kernel. + +### Platform Configuration Register (PCR) + +A Platform Configuration Register (PCR) is a memory location in the TPM that has some unique properties. +To store a new value in a PCR, the existing value is extended with a new value as follows: + +``` +PCR[N] = HASHalg( PCR[N] || ArgumentOfExtend ) +``` + +The PCRs are typically used to store runtime measurements. +The new value of a PCR is always an extension of the existing value. +Thus, storing the measurements of multiple components into the same PCR irreversibly links them together. + +### Measured boot + +Measured boot builds on the concept of chained runtime measurements. +Each component in the boot chain loads and measures the next component into the PCR before executing it. +By comparing the resulting PCR values against trusted reference values, the integrity of the entire boot chain and thereby the running system can be ensured. + +### Remote attestation (RA) + +Remote attestation is the process of verifying certain properties of an application or platform, such as integrity and confidentiality, from a remote location. +In the case of a measured boot, the goal is to obtain a signed attestation statement on the PCR values of the boot measurements. +The statement can then be verified and compared to a set of trusted reference values. +This way, the integrity of the platform can be ensured before sharing secrets with it. + +### Confidential virtual machine (CVM) + +Confidential computing (CC) is the protection of data in-use with hardware-based trusted execution environments (TEEs). +With CVMs, TEEs encapsulate entire virtual machines and isolate them against the hypervisor, other VMs, and direct memory access. +After loading the initial VM image into encrypted memory, the hypervisor calls for a secure processor to measure these initial memory pages. +The secure processor locks these pages and generates an attestation report on the initial page measurements. +CVM memory pages are encrypted with a key that resides inside the secure processor, which makes sure only the guest VM can access them. +The attestation report is signed by the secure processor and can be verified using remote attestation via the certificate authority of the hardware vendor. +Such an attestation statement guarantees the confidentiality and integrity of a CVM. + +### Attested TLS (aTLS) + +In a CC environment, attested TLS (aTLS) can be used to establish secure connections between two parties using the remote attestation features of the CC components. + +aTLS modifies the TLS handshake by embedding an attestation statement into the TLS certificate. +Instead of relying on a certificate authority, aTLS uses this attestation statement to establish trust in the certificate. + +The protocol can be used by clients to verify a server certificate, by a server to verify a client certificate, or for mutual verification (mutual aTLS). + +## Overview + +The challenge for Constellation is to lift a CVM's attestation statement to the Kubernetes software layer and make it end-to-end verifiable. +From there, Constellation needs to expand the attestation from a single CVM to the entire cluster. + +The [*JoinService*](microservices.md#joinservice) and [*VerificationService*](microservices.md#verificationservice) are where all runs together. +Internally, the *JoinService* uses remote attestation to securely join CVM nodes to the cluster. +Externally, the *VerificationService* provides an attestation statement for the cluster's CVMs and configuration. + +The following explains the details of both steps. + +## Node attestation + +The idea is that Constellation nodes should have verifiable integrity from the CVM hardware measurement up to the Kubernetes software layer. +The solution is a verifiable boot chain and an integrity-protected runtime environment. + +Constellation uses measured boot within CVMs, measuring each component in the boot process before executing it. +Outside of CC, this is usually implemented via TPMs. +CVM technologies differ in how they implement runtime measurements, but the general concepts are similar to those of a TPM. +For simplicity, TPM terminology like *PCR* is used in the following. + +When a Constellation node image boots inside a CVM, measured boot is used for all stages and components of the boot chain. +This process goes up to the root filesystem. +The root filesystem is mounted read-only with integrity protection. +For the details on the image and boot stages see the [image architecture](../architecture/images.md) documentation. +Any changes to the image will inevitably also change the corresponding PCR values. +To create a node attestation statement, the Constellation image obtains a CVM attestation statement from the hardware. +This includes the runtime measurements and thereby binds the measured boot results to the CVM hardware measurement. + +In addition to the image measurements, Constellation extends a PCR during the [initialization phase](../workflows/create.md) that irrevocably marks the node as initialized. +The measurement is created using the [*clusterID*](../architecture/keys.md#cluster-identity), tying all future attestation statements to this ID. +Thereby, an attestation statement is unique for every cluster and a node can be identified unambiguously as being initialized. + +To verify an attestation, the hardware's signature and a statement are verified first to establish trust in the contained runtime measurements. +If successful, the measurements are verified against the trusted values of the particular Constellation release version. +Finally, the measurement of the *clusterID* can be compared by calculating it with the [master secret](keys.md#master-secret). + +### Runtime measurements + +Constellation uses runtime measurements to implement the measured boot approach. +As stated above, the underlying hardware technology and guest firmware differ in their implementations of runtime measurements. +The following gives a detailed description of the available measurements in the different cloud environments. + +The runtime measurements consist of two types of values: + +* **Measurements produced by the cloud infrastructure and firmware of the CVM**: +These are measurements of closed-source firmware and other values controlled by the cloud provider. +While not being reproducible for the user, some of them can be compared against previously observed values. +Others may change frequently and aren't suitable for verification. +The [signed image measurements](#chain-of-trust) include measurements that are known, previously observed values. + +* **Measurements produced by the Constellation bootloader and boot chain**: +The Constellation Bootloader takes over from the CVM firmware and [measures the rest of the boot chain](images.md). +The Constellation [Bootstrapper](microservices.md#bootstrapper) is the first user mode component that runs in a Constellation image. +It extends PCR registers with the [IDs](keys.md#cluster-identity) of the cluster marking a node as initialized. + +Constellation allows to specify in the config which measurements should be enforced during the attestation process. +Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. +By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. + + + + +Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. + +The vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +The VMs are attested by obtaining signed PCR values over the VM's boot configuration from the TPM and comparing them to a known, good state (measured boot). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | Firmware | AWS | No | +| 1 | Firmware | AWS | No | +| 2 | Firmware | AWS | No | +| 3 | Firmware | AWS | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | AWS, Constellation Bootloader | Yes | +| 5 | Firmware | AWS | No | +| 6 | Firmware | AWS | No | +| 7 | Secure Boot Policy | AWS, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. +This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +It provides a [measured boot](https://docs.microsoft.com/en-us/azure/security/fundamentals/measured-boot-host-attestation#measured-boot) verification that's based on the trusted launch feature of [Trusted Launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | Firmware | Azure | No | +| 1 | Firmware | Azure | No | +| 2 | Firmware | Azure | No | +| 3 | Firmware | Azure | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | Azure, Constellation Bootloader | Yes | +| 5 | Reserved | Azure | No | +| 6 | VM Unique ID | Azure | No | +| 7 | Secure Boot State | Azure, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. +Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. + +The vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +It provides a [launch attestation report](https://cloud.google.com/compute/confidential-vm/docs/monitoring#about_launch_attestation_report_events) that's based on the measured boot feature of [Shielded VMs](https://cloud.google.com/compute/shielded-vm/docs/shielded-vm#measured-boot). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | CVM version and technology | GCP | No | +| 1 | Firmware | GCP | No | +| 2 | Firmware | GCP | No | +| 3 | Firmware | GCP | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | GCP, Constellation Bootloader | Yes | +| 5 | Disk GUID partition table | GCP | No | +| 6 | Disk GUID partition table | GCP | No | +| 7 | GCP Secure Boot Policy | GCP, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +Constellation uses a hypervisor-based vTPM for runtime measurements. + +The vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +The VMs are attested by obtaining signed PCR values over the VM's boot configuration from the TPM and comparing them to a known, good state (measured boot). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | Firmware | STACKIT | No | +| 1 | Firmware | STACKIT | No | +| 2 | Firmware | STACKIT | No | +| 3 | Firmware | STACKIT | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | STACKIT, Constellation Bootloader | Yes | +| 5 | Firmware | STACKIT | No | +| 6 | Firmware | STACKIT | No | +| 7 | Secure Boot Policy | STACKIT, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +### CVM verification + +To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. +For verification of the CVM technology, Constellation may expose additional options in its config file. + + + + +On AWS, AMD SEV-SNP is used to provide runtime encryption to the VMs. +An SEV-SNP attestation report is used to establish trust in the VM. +You may customize certain parameters for verification of the attestation statement using the Constellation config file. + +* TCB versions + + You can set the minimum version numbers of components in the SEV-SNP TCB. + Use the latest versions to enforce that only machines with the most recent firmware updates are allowed to join the cluster. + Alternatively, you can set a lower minimum version to allow slightly out-of-date machines to still be able to join the cluster. + +* AMD Root Key Certificate + + This certificate is the root of trust for verifying the SEV-SNP certificate chain. + +* AMD Signing Key Certificate + + This is the intermediate certificate for verifying the SEV-SNP report's signature. + If it's not specified, the CLI fetches it from the AMD key distribution server. + + + + +On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. +An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. +You may customize certain parameters for verification of the attestation statement using the Constellation config file. + +* TCB versions + + You can set the minimum version numbers of components in the SEV-SNP TCB. + Use the latest versions to enforce that only machines with the most recent firmware updates are allowed to join the cluster. + Alternatively, you can set a lower minimum version to allow slightly out-of-date machines to still be able to join the cluster. + +* AMD Root Key Certificate + + This certificate is the root of trust for verifying the SEV-SNP certificate chain. + +* Firmware Signer + + This config option allows you to specify how the firmware signer should be verified. + More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. + You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. + + + + +On GCP, AMD SEV-ES is used to provide runtime encryption to the VMs. +The hypervisor-based vTPM is used to establish trust in the VM via [runtime measurements](#runtime-measurements). +There is no additional configuration available for GCP. + + + + +On STACKIT, AMD SEV-ES is used to provide runtime encryption to the VMs. +The hypervisor-based vTPM is used to establish trust in the VM via [runtime measurements](#runtime-measurements). +There is no additional configuration available for STACKIT. + + + + +## Cluster attestation + +Cluster-facing, Constellation's [*JoinService*](microservices.md#joinservice) verifies each node joining the cluster given the configured ground truth runtime measurements. +User-facing, the [*VerificationService*](microservices.md#verificationservice) provides an interface to verify a node using remote attestation. +By verifying the first node during the [initialization](microservices.md#bootstrapper) and configuring the ground truth measurements that are subsequently enforced by the *JoinService*, the whole cluster is verified in a transitive way. + +### Cluster-facing attestation + +The *JoinService* is provided with the runtime measurements of the whitelisted Constellation image version as the ground truth. +During the initialization and the cluster bootstrapping, each node connects to the *JoinService* using [aTLS](#attested-tls-atls). +During the handshake, the node transmits an attestation statement including its runtime measurements. +The *JoinService* verifies that statement and compares the measurements against the ground truth. +For details of the initialization process check the [microservice descriptions](microservices.md). + +After the initialization, every node updates its runtime measurements with the *clusterID* value, marking it irreversibly as initialized. +When an initialized node tries to join another cluster, its measurements inevitably mismatch the measurements of an uninitialized node and it will be declined. + +### User-facing attestation + +The [*VerificationService*](microservices.md#verificationservice) provides an endpoint for obtaining its hardware-based remote attestation statement, which includes the runtime measurements. +A user can [verify](../workflows/verify-cluster.md) this statement and compare the measurements against the configured ground truth and, thus, verify the identity and integrity of all Constellation components and the cluster configuration. Subsequently, the user knows that the entire cluster is in the expected state and is trustworthy. + +## Putting it all together + +This section puts the aforementioned concepts together and illustrate how trust into a Constellation cluster is established and maintained. + +### CLI and node images + +It all starts with the CLI executable. The CLI is signed by Edgeless Systems. To ensure non-repudiability for CLI releases, Edgeless Systems publishes corresponding signatures to the public ledger of the [sigstore project](https://www.sigstore.dev/). There's a [step-by-step guide](../workflows/verify-cli.md) on how to verify CLI signatures based on sigstore. + +The CLI contains the latest runtime measurements of the Constellation node image for all supported cloud platforms. In case a different version of the node image is to be used, the corresponding runtime measurements can be fetched using the CLI's [fetch-measurements command](../reference/cli.md#constellation-config-fetch-measurements). This command downloads the runtime measurements and the corresponding signature from cdn.confidential.cloud. See for example the following files corresponding to node image v2.16.3: + +* [Measurements](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json) +* [Signature](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json.sig) + +The CLI contains the long-term public key of Edgeless Systems to verify the signature of downloaded runtime measurements. + +### Cluster creation + +When a cluster is [created](../workflows/create.md), the CLI automatically verifies the runtime measurements of the *first node* using remote attestation. Based on this, the CLI and the first node set up a temporary TLS connection. This [aTLS](#attested-tls-atls) connection is used for two things: + +1. The CLI sends the [master secret](../architecture/keys.md#master-secret) of the to-be-created cluster to the CLI. The master secret is generated by the first node. +2. The first node sends a [kubeconfig file](https://www.redhat.com/sysadmin/kubeconfig) with Kubernetes credentials to the CLI. + +After this, the aTLS connection is closed and the first node bootstraps the Kubernetes cluster. All subsequent interactions between the CLI and the cluster go via the [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) server running inside the cluster. The CLI (and other tools like kubectl) use the credentials referenced by the kubeconfig file to authenticate themselves towards the Kubernetes API server and to establish a mTLS connection. + +The CLI connects to the Kubernetes API to write the runtime measurements for the applicable node image to etcd. The JoinService uses these runtime measurements to verify all nodes that join the cluster subsequently. + +### Chain of trust + +In summary, there's a chain of trust based on cryptographic signatures that goes from the user to the cluster via the CLI. This is illustrated in the following diagram. + +```mermaid +flowchart LR + A[User]-- "verifies" -->B[CLI] + B[CLI]-- "verifies" -->C([Runtime measurements]) + D[Edgeless Systems]-- "signs" -->B[CLI] + D[Edgeless Systems]-- "signs" -->C([Runtime measurements]) + B[CLI]-- "verifies (remote attestation)" -->E[First node] + E[First node]-- "verifies (remote attestation)" -->F[Other nodes] + C([Runtime measurements]) -.-> E[First node] + C([Runtime measurements]) -.-> F[Other nodes] +``` + +### Upgrades + +Whenever a cluster is [upgraded](../workflows/upgrade.md) to a new version of the node image, the CLI sends the corresponding runtime measurements via the Kubernetes API server. The new runtime measurements are stored in etcd within the cluster and replace any previous runtime measurements. The new runtime measurements are then used automatically by the JoinService for the verification of new nodes. + +## References + +[^1]: Linux IMA produces runtime measurements of user-space binaries. +However, these measurements aren't deterministic and thus, PCR\[10] can't be compared to a constant value. +Instead, a policy engine must be used to verify the TPM event log against a policy. diff --git a/docs/versioned_docs/version-2.17/architecture/encrypted-storage.md b/docs/versioned_docs/version-2.17/architecture/encrypted-storage.md new file mode 100644 index 000000000..f047fa4a9 --- /dev/null +++ b/docs/versioned_docs/version-2.17/architecture/encrypted-storage.md @@ -0,0 +1,62 @@ +# Encrypted persistent storage + +Confidential VMs provide runtime memory encryption to protect data in use. +In the context of Kubernetes, this is sufficient for the confidentiality and integrity of stateless services. +Consider a front-end web server, for example, that keeps all connection information cached in main memory. +No sensitive data is ever written to an insecure medium. +However, many real-world applications need some form of state or data-lake service that's connected to a persistent storage device and requires encryption at rest. +As described in [Use persistent storage](../workflows/storage.md), cloud service providers (CSPs) use the container storage interface (CSI) to make their storage solutions available to Kubernetes workloads. +These CSI storage solutions often support some sort of encryption. +For example, Google Cloud [encrypts data at rest by default](https://cloud.google.com/security/encryption/default-encryption), without any action required by the customer. + +## Cloud provider-managed encryption + +CSP-managed storage solutions encrypt the data in the cloud backend before writing it physically to disk. +In the context of confidential computing and Constellation, the CSP and its managed services aren't trusted. +Hence, cloud provider-managed encryption protects your data from offline hardware access to physical storage devices. +It doesn't protect it from anyone with infrastructure-level access to the storage backend or a malicious insider in the cloud platform. +Even with "bring your own key" or similar concepts, the CSP performs the encryption process with access to the keys and plaintext data. + +In the security model of Constellation, securing persistent storage and thereby data at rest requires that all cryptographic operations are performed inside a trusted execution environment. +Consequently, using CSP-managed encryption of persistent storage usually isn't an option. + +## Constellation-managed encryption + +Constellation provides CSI drivers for storage solutions in all major clouds with built-in encryption support. +Block storage provisioned by the CSP is [mapped](https://guix.gnu.org/manual/en/html_node/Mapped-Devices.html) using the [dm-crypt](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-crypt.html), and optionally the [dm-integrity](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-integrity.html), kernel modules, before it's formatted and accessed by the Kubernetes workloads. +All cryptographic operations happen inside the trusted environment of the confidential Constellation node. + +Note that for integrity-protected disks, [volume expansion](https://kubernetes.io/blog/2018/07/12/resizing-persistent-volumes-using-kubernetes/) isn't supported. + +By default the driver uses data encryption keys (DEKs) issued by the Constellation [*KeyService*](microservices.md#keyservice). +The DEKs are in turn derived from the Constellation's key encryption key (KEK), which is directly derived from the [master secret](keys.md#master-secret). +This is the recommended mode of operation, and also requires the least amount of setup by the cluster administrator. + +Alternatively, the driver can be configured to use a key management system to store and access KEKs and DEKs. + +Refer to [keys and cryptography](keys.md) for more details on key management in Constellation. + +Once deployed and configured, the CSI driver ensures transparent encryption and integrity of all persistent volumes provisioned via its storage class. +Data at rest is secured without any additional actions required by the developer. + +## Cryptographic algorithms + +This section gives an overview of the libraries, cryptographic algorithms, and their configurations, used in Constellation's CSI drivers. + +### dm-crypt + +To interact with the dm-crypt kernel module, Constellation uses [libcryptsetup](https://gitlab.com/cryptsetup/cryptsetup/). +New devices are formatted as [LUKS2](https://gitlab.com/cryptsetup/LUKS2-docs/-/tree/master) partitions with a sector size of 4096 bytes. +The used key derivation function is [Argon2id](https://datatracker.ietf.org/doc/html/rfc9106) with the [recommended parameters for memory-constrained environments](https://datatracker.ietf.org/doc/html/rfc9106#section-7.4) of 3 iterations and 64 MiB of memory, utilizing 4 parallel threads. +For encryption Constellation uses AES in XTS-Plain64. The key size is 512 bit. + +### dm-integrity + +To interact with the dm-integrity kernel module, Constellation uses [libcryptsetup](https://gitlab.com/cryptsetup/cryptsetup/). +When enabled, the used data integrity algorithm is [HMAC](https://datatracker.ietf.org/doc/html/rfc2104) with SHA256 as the hash function. +The tag size is 32 Bytes. + +## Encrypted S3 object storage + +Constellation comes with a service that you can use to transparently retrofit client-side encryption to existing applications that use S3 (AWS or compatible) for storage. +To learn more, check out the [s3proxy documentation](../workflows/s3proxy.md). diff --git a/docs/versioned_docs/version-2.17/architecture/images.md b/docs/versioned_docs/version-2.17/architecture/images.md new file mode 100644 index 000000000..8a9c51d36 --- /dev/null +++ b/docs/versioned_docs/version-2.17/architecture/images.md @@ -0,0 +1,49 @@ +# Constellation images + +Constellation uses a minimal version of Fedora as the operating system running inside confidential VMs. This Linux distribution is optimized for containers and designed to be stateless. +The Constellation images provide measured boot and an immutable filesystem. + +## Measured boot + +```mermaid +flowchart LR + Firmware --> Bootloader + Bootloader --> uki + subgraph uki[Unified Kernel Image] + Kernel[Kernel] + initramfs[Initramfs] + cmdline[Kernel Command Line] + end + uki --> rootfs[Root Filesystem] +``` + +Measured boot uses a Trusted Platform Module (TPM) to measure every part of the boot process. This allows for verification of the integrity of a running system at any point in time. To ensure correct measurements of every stage, each stage is responsible to measure the next stage before transitioning. + +### Firmware + +With confidential VMs, the firmware is the root of trust and is measured automatically at boot. After initialization, the firmware will load and measure the bootloader before executing it. + +### Bootloader + +The bootloader is the first modifiable part of the boot chain. The bootloader is tasked with loading the kernel, initramfs and setting the kernel command line. The Constellation bootloader measures these components before starting the kernel. + +### initramfs + +The initramfs is a small filesystem loaded to prepare the actual root filesystem. The Constellation initramfs maps the block device containing the root filesystem with [dm-verity](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html). The initramfs then mounts the root filesystem from the mapped block device. + +dm-verity provides integrity checking using a cryptographic hash tree. When a block is read, its integrity is checked by verifying the tree against a trusted root hash. The initramfs reads this root hash from the previously measured kernel command line. Thus, if any block of the root filesystem's device is modified on disk, trying to read the modified block will result in a kernel panic at runtime. + +After mounting the root filesystem, the initramfs will switch over and start the `init` process of the integrity-protected root filesystem. + +## State disk + +In addition to the read-only root filesystem, each Constellation node has a disk for storing state data. +This disk is mounted readable and writable by the initramfs and contains data that should persist across reboots. +Such data can contain sensitive information and, therefore, must be stored securely. +To that end, the state disk is protected by authenticated encryption. +See the section on [keys and encryption](keys.md#storage-encryption) for more information on the cryptographic primitives in use. + +## Kubernetes components + +During initialization, the [*Bootstrapper*](microservices.md#bootstrapper) downloads and verifies the [Kubernetes components](https://kubernetes.io/docs/concepts/overview/components/) as configured by the user. +They're stored on the state partition and can be updated once new releases need to be installed. diff --git a/docs/versioned_docs/version-2.17/architecture/keys.md b/docs/versioned_docs/version-2.17/architecture/keys.md new file mode 100644 index 000000000..553d9d4e2 --- /dev/null +++ b/docs/versioned_docs/version-2.17/architecture/keys.md @@ -0,0 +1,131 @@ +# Key management and cryptographic primitives + +Constellation protects and isolates your cluster and workloads. +To that end, cryptography is the foundation that ensures the confidentiality and integrity of all components. +Evaluating the security and compliance of Constellation requires a precise understanding of the cryptographic primitives and keys used. +The following gives an overview of the architecture and explains the technical details. + +## Confidential VMs + +Confidential VM (CVM) technology comes with hardware and software components for memory encryption, isolation, and remote attestation. +For details on the implementations and cryptographic soundness, refer to the hardware vendors' documentation and advisories. + +## Master secret + +The master secret is the cryptographic material used for deriving the [*clusterID*](#cluster-identity) and the *key encryption key (KEK)* for [storage encryption](#storage-encryption). +It's generated during the bootstrapping of a Constellation cluster. +It can either be managed by [Constellation](#constellation-managed-key-management) or an [external key management system](#user-managed-key-management). +In case of [recovery](#recovery-and-migration), the master secret allows to decrypt the state and recover a Constellation cluster. + +## Cluster identity + +The identity of a Constellation cluster is represented by cryptographic [measurements](attestation.md#runtime-measurements): + +The **base measurements** represent the identity of a valid, uninitialized Constellation node. +They depend on the node image, but are otherwise the same for every Constellation cluster. +On node boot, they're determined using the CVM's attestation mechanism and [measured boot up to the read-only root filesystem](images.md). + +The **clusterID** represents the identity of a single initialized Constellation cluster. +It's derived from the master secret and a cryptographically random salt and unique for every Constellation cluster. +The [Bootstrapper](microservices.md#bootstrapper) measures the *clusterID* into its own PCR before executing any code not measured as part of the *base measurements*. +See [Node attestation](attestation.md#node-attestation) for details. + +The remote attestation statement of a Constellation cluster combines the *base measurements* and the *clusterID* for a verifiable, unspoofable, unique identity. + +## Network encryption + +Constellation encrypts all cluster network communication using the [container network interface (CNI)](https://github.com/containernetworking/cni). +See [network encryption](networking.md) for more details. + +The Cilium agent running on each node establishes a secure [WireGuard](https://www.wireguard.com/) tunnel between it and all other known nodes in the cluster. +Each node creates its own [Curve25519](http://cr.yp.to/ecdh.html) encryption key pair and distributes its public key via Kubernetes. +A node uses another node's public key to decrypt and encrypt traffic from and to Cilium-managed endpoints running on that node. +Connections are always encrypted peer-to-peer using [ChaCha20](http://cr.yp.to/chacha.html) with [Poly1305](http://cr.yp.to/mac.html). +WireGuard implements [forward secrecy with key rotation every 2 minutes](https://lists.zx2c4.com/pipermail/wireguard/2017-December/002141.html). +Cilium supports [key rotation](https://docs.cilium.io/en/stable/security/network/encryption-ipsec/#key-rotation) for the long-term node keys via Kubernetes secrets. + +## Storage encryption + +Constellation supports transparent encryption of persistent storage. +The Linux kernel's device mapper-based encryption features are used to encrypt the data on the block storage level. +Currently, the following primitives are used for block storage encryption: + +* [dm-crypt](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-crypt.html) +* [dm-integrity](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-integrity.html) + +Adding primitives for integrity protection in the CVM attacker model are under active development and will be available in a future version of Constellation. +See [encrypted storage](encrypted-storage.md) for more details. + +As a cluster administrator, when creating a cluster, you can use the Constellation [installation program](orchestration.md) to select one of the following methods for key management: + +* Constellation-managed key management +* User-managed key management + +### Constellation-managed key management + +#### Key material and key derivation + +During the creation of a Constellation cluster, the cluster's master secret is used to derive a KEK. +This means creating two clusters with the same master secret will yield the same KEK. +Any data encryption key (DEK) is derived from the KEK via HKDF. +Note that the master secret is recommended to be unique for every cluster and shouldn't be reused (except in case of [recovering](../workflows/recovery.md) a cluster). + +#### State and storage + +The KEK is derived from the master secret during the initialization. +Subsequently, all other key material is derived from the KEK. +Given the same KEK, any DEK can be derived deterministically from a given identifier. +Hence, there is no need to store DEKs. They can be derived on demand. +After the KEK was derived, it's stored in memory only and never leaves the CVM context. + +#### Availability + +Constellation-managed key management has the same availability as the underlying Kubernetes cluster. +Therefore, the KEK is stored in the [distributed Kubernetes etcd storage](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/) to allow for unexpected but non-fatal (control-plane) node failure. +The etcd storage is backed by the encrypted and integrity protected [state disk](images.md#state-disk) of the nodes. + +#### Recovery + +Constellation clusters can be recovered in the event of a disaster, even when all node machines have been stopped and need to be rebooted. +For details on the process see the [recovery workflow](../workflows/recovery.md). + +### User-managed key management + +User-managed key management is under active development and will be available soon. +In scenarios where constellation-managed key management isn't an option, this mode allows you to keep full control of your keys. +For example, compliance requirements may force you to keep your KEKs in an on-prem key management system (KMS). + +During the creation of a Constellation cluster, you specify a KEK present in a remote KMS. +This follows the common scheme of "bring your own key" (BYOK). +Constellation will support several KMSs for managing the storage and access of your KEK. +Initially, it will support the following KMSs: + +* [AWS KMS](https://aws.amazon.com/kms/) +* [GCP KMS](https://cloud.google.com/security-key-management) +* [Azure Key Vault](https://azure.microsoft.com/en-us/services/key-vault/#product-overview) +* [KMIP-compatible KMS](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=kmip) + +Storing the keys in Cloud KMS of AWS, Azure, or GCP binds the key usage to the particular cloud identity access management (IAM). +In the future, Constellation will support remote attestation-based access policies for Cloud KMS once available. +Note that using a Cloud KMS limits the isolation and protection to the guarantees of the particular offering. + +KMIP support allows you to use your KMIP-compatible on-prem KMS and keep full control over your keys. +This follows the common scheme of "hold your own key" (HYOK). + +The KEK is used to encrypt per-data "data encryption keys" (DEKs). +DEKs are generated to encrypt your data before storing it on persistent storage. +After being encrypted by the KEK, the DEKs are stored on dedicated cloud storage for persistence. +Currently, Constellation supports the following cloud storage options: + +* [AWS S3](https://aws.amazon.com/s3/) +* [GCP Cloud Storage](https://cloud.google.com/storage) +* [Azure Blob Storage](https://azure.microsoft.com/en-us/services/storage/blobs/#overview) + +The DEKs are only present in plaintext form in the encrypted main memory of the CVMs. +Similarly, the cryptographic operations for encrypting data before writing it to persistent storage are performed in the context of the CVMs. + +#### Recovery and migration + +In the case of a disaster, the KEK can be used to decrypt the DEKs locally and subsequently use them to decrypt and retrieve the data. +In case of migration, configuring the same KEK will provide seamless migration of data. +Thus, only the DEK storage needs to be transferred to the new cluster alongside the encrypted data for seamless migration. diff --git a/docs/versioned_docs/version-2.17/architecture/microservices.md b/docs/versioned_docs/version-2.17/architecture/microservices.md new file mode 100644 index 000000000..90bae783b --- /dev/null +++ b/docs/versioned_docs/version-2.17/architecture/microservices.md @@ -0,0 +1,73 @@ +# Microservices + +Constellation takes care of bootstrapping and initializing a Confidential Kubernetes cluster. +During the lifetime of the cluster, it handles day 2 operations such as key management, remote attestation, and updates. +These features are provided by several microservices: + +* The [Bootstrapper](microservices.md#bootstrapper) initializes a Constellation node and bootstraps the cluster +* The [JoinService](microservices.md#joinservice) joins new nodes to an existing cluster +* The [VerificationService](microservices.md#verificationservice) provides remote attestation functionality +* The [KeyService](microservices.md#keyservice) manages Constellation-internal keys + +The relations between microservices are shown in the following diagram: + +```mermaid +flowchart LR + subgraph admin [Admin's machine] + A[Constellation CLI] + end + subgraph img [Constellation OS image] + B[Constellation OS] + C[Bootstrapper] + end + subgraph Kubernetes + D[JoinService] + E[KeyService] + F[VerificationService] + end + A -- deploys --> + B -- starts --> C + C -- deploys --> D + C -- deploys --> E + C -- deploys --> F +``` + +## Bootstrapper + +The *Bootstrapper* is the first microservice launched after booting a Constellation node image. +It sets up that machine as a Kubernetes node and integrates that node into the Kubernetes cluster. +To this end, the *Bootstrapper* first downloads and verifies the [Kubernetes components](https://kubernetes.io/docs/concepts/overview/components/) at the configured versions. +The *Bootstrapper* tries to find an existing cluster and if successful, communicates with the [JoinService](microservices.md#joinservice) to join the node. +Otherwise, it waits for an initialization request to create a new Kubernetes cluster. + +## JoinService + +The *JoinService* runs as [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) on each control-plane node. +New nodes (at cluster start, or later through autoscaling) send a request to the service over [attested TLS (aTLS)](attestation.md#attested-tls-atls). +The *JoinService* verifies the new node's certificate and attestation statement. +If attestation is successful, the new node is supplied with an encryption key from the [*KeyService*](microservices.md#keyservice) for its state disk, and a Kubernetes bootstrap token. + + +```mermaid +sequenceDiagram + participant New node + participant JoinService + New node->>JoinService: aTLS handshake (server side verification) + JoinService-->>New node: # + New node->>+JoinService: IssueJoinTicket(DiskUUID, NodeName, IsControlPlane) + JoinService->>+KeyService: GetDataKey(DiskUUID) + KeyService-->>-JoinService: DiskEncryptionKey + JoinService-->>-New node: DiskEncryptionKey, KubernetesJoinToken, ... +``` + +## VerificationService + +The *VerificationService* runs as DaemonSet on each node. +It provides user-facing functionality for remote attestation during the cluster's lifetime via an endpoint for [verifying the cluster](attestation.md#cluster-attestation). +Read more about the hardware-based [attestation feature](attestation.md) of Constellation and how to [verify](../workflows/verify-cluster.md) a cluster on the client side. + +## KeyService + +The *KeyService* runs as DaemonSet on each control-plane node. +It implements the key management for the [storage encryption keys](keys.md#storage-encryption) in Constellation. These keys are used for the [state disk](images.md#state-disk) of each node and the [transparently encrypted storage](encrypted-storage.md) for Kubernetes. +Depending on wether the [constellation-managed](keys.md#constellation-managed-key-management) or [user-managed](keys.md#user-managed-key-management) mode is used, the *KeyService* holds the key encryption key (KEK) directly or calls an external key management service (KMS) for key derivation respectively. diff --git a/docs/versioned_docs/version-2.17/architecture/networking.md b/docs/versioned_docs/version-2.17/architecture/networking.md new file mode 100644 index 000000000..e9cbdf029 --- /dev/null +++ b/docs/versioned_docs/version-2.17/architecture/networking.md @@ -0,0 +1,22 @@ +# Network encryption + +Constellation encrypts all pod communication using the [container network interface (CNI)](https://github.com/containernetworking/cni). +To that end, Constellation deploys, configures, and operates the [Cilium](https://cilium.io/) CNI plugin. +Cilium provides [transparent encryption](https://docs.cilium.io/en/stable/security/network/encryption) for all cluster traffic using either IPSec or [WireGuard](https://www.wireguard.com/). +Currently, Constellation only supports WireGuard as the encryption engine. +You can read more about the cryptographic soundness of WireGuard [in their white paper](https://www.wireguard.com/papers/wireguard.pdf). + +Cilium is actively working on implementing a feature called [`host-to-host`](https://github.com/cilium/cilium/pull/19401) encryption mode for WireGuard. +With `host-to-host`, all traffic between nodes will be tunneled via WireGuard (host-to-host, host-to-pod, pod-to-host, pod-to-pod). +Until the `host-to-host` feature is released, Constellation enables `pod-to-pod` encryption. +This mode encrypts all traffic between Kubernetes pods using WireGuard tunnels. + +When using Cilium in the default setup but with encryption enabled, there is a [known issue](https://docs.cilium.io/en/v1.12/gettingstarted/encryption/#egress-traffic-to-not-yet-discovered-remote-endpoints-may-be-unencrypted) +that can cause pod-to-pod traffic to be unencrypted. +To mitigate this issue, Constellation adds a *strict* mode to Cilium's `pod-to-pod` encryption. +This mode changes the default behavior of traffic that's destined for an unknown endpoint to not be send out in plaintext, but instead being dropped. +The strict mode distinguishes between traffic that's send to a pod from traffic that's destined for a cluster-external endpoint by considering the pod's CIDR range. + +Traffic originating from hosts isn't encrypted yet. +This mainly includes health checks from Kubernetes API server. +Also, traffic proxied over the API server via e.g. `kubectl port-forward` isn't encrypted. diff --git a/docs/versioned_docs/version-2.17/architecture/observability.md b/docs/versioned_docs/version-2.17/architecture/observability.md new file mode 100644 index 000000000..0f4daffd4 --- /dev/null +++ b/docs/versioned_docs/version-2.17/architecture/observability.md @@ -0,0 +1,74 @@ +# Observability + +In Kubernetes, observability is the ability to gain insight into the behavior and performance of applications. +It helps identify and resolve issues more effectively, ensuring stability and performance of Kubernetes workloads, reducing downtime and outages, and improving efficiency. +The "three pillars of observability" are logs, metrics, and traces. + +In the context of Confidential Computing, observability is a delicate subject and needs to be applied such that it doesn't leak any sensitive information. +The following gives an overview of where and how you can apply standard observability tools in Constellation. + +## Cloud resource monitoring + +While inaccessible, Constellation's nodes are still visible as black box VMs to the hypervisor. +Resource consumption, such as memory and CPU utilization, can be monitored from the outside and observed via the cloud platforms directly. +Similarly, other resources, such as storage and network and their respective metrics, are visible via the cloud platform. + +## Metrics + +Metrics are numeric representations of data measured over intervals of time. They're essential for understanding system health and gaining insights using telemetry signals. + +By default, Constellation exposes the [metrics for Kubernetes system components](https://kubernetes.io/docs/concepts/cluster-administration/system-metrics/) inside the cluster. +Similarly, the [etcd metrics](https://etcd.io/docs/v3.5/metrics/) endpoints are exposed inside the cluster. +These [metrics endpoints can be disabled](https://kubernetes.io/docs/concepts/cluster-administration/system-metrics/#disabling-metrics). + +You can collect these cluster-internal metrics via tools such as [Prometheus](https://prometheus.io/) or the [Elastic Stack](https://www.elastic.co/de/elastic-stack/). + +Constellation's CNI Cilium also supports [metrics via Prometheus endpoints](https://docs.cilium.io/en/latest/observability/metrics/). +However, in Constellation, they're disabled by default and must be enabled first. + +## Logs + +Logs represent discrete events that usually describe what's happening with your service. +The payload is an actual message emitted from your system along with a metadata section containing a timestamp, labels, and tracking identifiers. + +### System logs + +Detailed system-level logs are accessible via `/var/log` and [journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) on the nodes directly. +They can be collected from there, for example, via [Filebeat and Logstash](https://www.elastic.co/guide/en/beats/filebeat/current/logstash-output.html), which are tools of the [Elastic Stack](https://www.elastic.co/de/elastic-stack/). + +In case of an error during the initialization, the CLI automatically collects the [Bootstrapper](./microservices.md#bootstrapper) logs and returns these as a file for [troubleshooting](../workflows/troubleshooting.md). Here is an example of such an event: + +```shell-session +Cluster initialization failed. This error is not recoverable. +Terminate your cluster and try again. +Fetched bootstrapper logs are stored in "constellation-cluster.log" +``` + +### Kubernetes logs + +Constellation supports the [Kubernetes logging architecture](https://kubernetes.io/docs/concepts/cluster-administration/logging/). +By default, logs are written to the nodes' encrypted state disks. +These include the Pod and container logs and the [system component logs](https://kubernetes.io/docs/concepts/cluster-administration/logging/#system-component-logs). + +[Constellation services](microservices.md) run as Pods inside the `kube-system` namespace and use the standard container logging mechanism. +The same applies for the [Cilium Pods](https://docs.cilium.io/en/latest/operations/troubleshooting/#logs). + +You can collect logs from within the cluster via tools such as [Fluentd](https://github.com/fluent/fluentd), [Loki](https://github.com/grafana/loki), or the [Elastic Stack](https://www.elastic.co/de/elastic-stack/). + +## Traces + +Modern systems are implemented as interconnected complex and distributed microservices. Understanding request flows and system communications is challenging, mainly because all systems in a chain need to be modified to propagate tracing information. Distributed tracing is a new approach to increasing observability and understanding performance bottlenecks. A trace represents consecutive events that reflect an end-to-end request path in a distributed system. + +Constellation supports [traces for Kubernetes system components](https://kubernetes.io/docs/concepts/cluster-administration/system-traces/). +By default, they're disabled and need to be enabled first. + +Similarly, Cilium can be enabled to [export traces](https://cilium.io/use-cases/metrics-export/). + +You can collect these traces via tools such as [Jaeger](https://www.jaegertracing.io/) or [Zipkin](https://zipkin.io/). + +## Integrations + +Platforms and SaaS solutions such as Datadog, logz.io, Dynatrace, or New Relic facilitate the observability challenge for Kubernetes and provide all-in-one SaaS solutions. +They install agents into the cluster that collect metrics, logs, and tracing information and upload them into the data lake of the platform. +Technically, the agent-based approach is compatible with Constellation, and attaching these platforms is straightforward. +However, you need to evaluate if the exported data might violate Constellation's compliance and privacy guarantees by uploading them to a third-party platform. diff --git a/docs/versioned_docs/version-2.17/architecture/orchestration.md b/docs/versioned_docs/version-2.17/architecture/orchestration.md new file mode 100644 index 000000000..3c8d529e7 --- /dev/null +++ b/docs/versioned_docs/version-2.17/architecture/orchestration.md @@ -0,0 +1,83 @@ +# Orchestrating Constellation clusters + +You can use the CLI to create a cluster on the supported cloud platforms. +The CLI provisions the resources in your cloud environment and initiates the initialization of your cluster. +It uses a set of parameters and an optional configuration file to manage your cluster installation. +The CLI is also used for updating your cluster. + +## Workspaces + +Each Constellation cluster has an associated *workspace*. +The workspace is where data such as the Constellation state and config files are stored. +Each workspace is associated with a single cluster and configuration. +The CLI stores state in the local filesystem making the current directory the active workspace. +Multiple clusters require multiple workspaces, hence, multiple directories. +Note that every operation on a cluster always has to be performed from the directory associated with its workspace. + +You may copy files from the workspace to other locations, +but you shouldn't move or delete them while the cluster is still being used. +The Constellation CLI takes care of managing the workspace. +Only when a cluster was terminated, and you are sure the files aren't needed anymore, should you remove a workspace. + +## Cluster creation process + +To allow for fine-grained configuration of your cluster and cloud environment, Constellation supports an extensive configuration file with strong defaults. [Generating the configuration file](../workflows/config.md) is typically the first thing you do in the workspace. + +Altogether, the following files are generated during the creation of a Constellation cluster and stored in the current workspace: + +* a configuration file +* a state file +* a Base64-encoded master secret +* [Terraform artifacts](../reference/terraform.md), stored in subdirectories +* a Kubernetes `kubeconfig` file. + +After the initialization of your cluster, the CLI will provide you with a Kubernetes `kubeconfig` file. +This file grants you access to your Kubernetes cluster and configures the [kubectl](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) tool. +In addition, the cluster's [identifier](orchestration.md#post-installation-configuration) is returned and stored in the state file. + +### Creation process details + +1. The CLI `apply` command first creates the confidential VM (CVM) resources in your cloud environment and configures the network +2. Each CVM boots the Constellation node image and measures every component in the boot chain +3. The first microservice launched in each node is the [*Bootstrapper*](microservices.md#bootstrapper) +4. The *Bootstrapper* waits until it either receives an initialization request or discovers an initialized cluster +5. The CLI then connects to the *Bootstrapper* of a selected node, sends the configuration, and initiates the initialization of the cluster +6. The *Bootstrapper* of **that** node [initializes the Kubernetes cluster](microservices.md#bootstrapper) and deploys the other Constellation [microservices](microservices.md) including the [*JoinService*](microservices.md#joinservice) +7. Subsequently, the *Bootstrappers* of the other nodes discover the initialized cluster and send join requests to the *JoinService* +8. As part of the join request each node includes an attestation statement of its boot measurements as authentication +9. The *JoinService* verifies the attestation statements and joins the nodes to the Kubernetes cluster +10. This process is repeated for every node joining the cluster later (e.g., through autoscaling) + +## Post-installation configuration + +Post-installation the CLI provides a configuration for [accessing the cluster using the Kubernetes API](https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/). +The `kubeconfig` file provides the credentials and configuration for connecting and authenticating to the API server. +Once configured, orchestrate the Kubernetes cluster via `kubectl`. + +After the initialization, the CLI will present you with a couple of tokens: + +* The [*master secret*](keys.md#master-secret) (stored in the `constellation-mastersecret.json` file by default) +* The [*clusterID*](keys.md#cluster-identity) of your cluster in Base64 encoding + +You can read more about these values and their meaning in the guide on [cluster identity](keys.md#cluster-identity). + +The *master secret* must be kept secret and can be used to [recover your cluster](../workflows/recovery.md). +Instead of managing this secret manually, you can [use your key management solution of choice](keys.md#user-managed-key-management) with Constellation. + +The *clusterID* uniquely identifies a cluster and can be used to [verify your cluster](../workflows/verify-cluster.md). + +## Upgrades + +Constellation images and microservices may need to be upgraded to new versions during the lifetime of a cluster. +Constellation implements a rolling update mechanism ensuring no downtime of the control or data plane. +You can upgrade a Constellation cluster with a single operation by using the CLI. +For step-by-step instructions on how to do this, refer to [Upgrade your cluster](../workflows/upgrade.md). + +### Attestation of upgrades + +With every new image, corresponding measurements are released. +During an update procedure, the CLI provides new measurements to the [JoinService](microservices.md#joinservice) securely. +New measurements for an updated image are automatically pulled and verified by the CLI following the [supply chain security concept](attestation.md#chain-of-trust) of Constellation. +The [attestation section](attestation.md#cluster-facing-attestation) describes in detail how these measurements are then used by the JoinService for the attestation of nodes. + + diff --git a/docs/versioned_docs/version-2.17/architecture/overview.md b/docs/versioned_docs/version-2.17/architecture/overview.md new file mode 100644 index 000000000..386f93b2f --- /dev/null +++ b/docs/versioned_docs/version-2.17/architecture/overview.md @@ -0,0 +1,30 @@ +# Overview + +Constellation is a cloud-based confidential orchestration platform. +The foundation of Constellation is Kubernetes and therefore shares the same technology stack and architecture principles. +To learn more about Constellation and Kubernetes, see [product overview](../overview/product.md). + +## About orchestration and updates + +As a cluster administrator, you can use the [Constellation CLI](orchestration.md) to install and deploy a cluster. +Updates are provided in accordance with the [support policy](versions.md). + +## About microservices and attestation + +Constellation manages the nodes and network in your cluster. All nodes are bootstrapped by the [*Bootstrapper*](microservices.md#bootstrapper). They're verified and authenticated by the [*JoinService*](microservices.md#joinservice) before being added to the cluster and the network. Finally, the entire cluster can be verified via the [*VerificationService*](microservices.md#verificationservice) using [remote attestation](attestation.md). + +## About node images and verified boot + +Constellation comes with operating system images for Kubernetes control-plane and worker nodes. +They're highly optimized for running containerized workloads and specifically prepared for running inside confidential VMs. +You can learn more about [the images](images.md) and how verified boot ensures their integrity during boot and beyond. + +## About key management and cryptographic primitives + +Encryption of data at-rest, in-transit, and in-use is the fundamental building block for confidential computing and Constellation. Learn more about the [keys and cryptographic primitives](keys.md) used in Constellation, [encrypted persistent storage](encrypted-storage.md), and [network encryption](networking.md). + +## About observability + +Observability in Kubernetes refers to the capability to troubleshoot issues using telemetry signals such as logs, metrics, and traces. +In the realm of Confidential Computing, it's crucial that observability aligns with confidentiality, necessitating careful implementation. +Learn more about the [observability capabilities in Constellation](./observability.md). diff --git a/docs/versioned_docs/version-2.17/architecture/versions.md b/docs/versioned_docs/version-2.17/architecture/versions.md new file mode 100644 index 000000000..85d35e6a9 --- /dev/null +++ b/docs/versioned_docs/version-2.17/architecture/versions.md @@ -0,0 +1,21 @@ +# Versions and support policy + +All components of Constellation use a three-digit version number of the form `v..`. +The components are released in lock step, usually on the first Tuesday of every month. This release primarily introduces new features, but may also include security or performance improvements. The `MINOR` version will be incremented as part of this release. + +Additional `PATCH` releases may be created on demand, to fix security issues or bugs before the next `MINOR` release window. + +New releases are published on [GitHub](https://github.com/edgelesssys/constellation/releases). + +## Kubernetes support policy + +Constellation is aligned to the [version support policy of Kubernetes](https://kubernetes.io/releases/version-skew-policy/#supported-versions), and therefore usually supports the most recent three minor versions. +When a new minor version of Kubernetes is released, support is added to the next Constellation release, and that version then supports four Kubernetes versions. +Subsequent Constellation releases drop support for the oldest (and deprecated) Kubernetes version. + +The following Kubernetes versions are currently supported: + + +* v1.28.11 +* v1.29.6 +* v1.30.2 diff --git a/docs/versioned_docs/version-2.17/getting-started/examples.md b/docs/versioned_docs/version-2.17/getting-started/examples.md new file mode 100644 index 000000000..fded84980 --- /dev/null +++ b/docs/versioned_docs/version-2.17/getting-started/examples.md @@ -0,0 +1,6 @@ +# Examples + +After you [installed the CLI](install.md) and [created your first cluster](first-steps.md), you're ready to deploy applications. Why not start with one of the following examples? +* [Emojivoto](examples/emojivoto.md): a simple but fun web application +* [Online Boutique](examples/online-boutique.md): an e-commerce demo application by Google consisting of 11 separate microservices +* [Horizontal Pod Autoscaling](examples/horizontal-scaling.md): an example demonstrating Constellation's autoscaling capabilities diff --git a/docs/versioned_docs/version-2.17/getting-started/examples/emojivoto.md b/docs/versioned_docs/version-2.17/getting-started/examples/emojivoto.md new file mode 100644 index 000000000..2bbe27917 --- /dev/null +++ b/docs/versioned_docs/version-2.17/getting-started/examples/emojivoto.md @@ -0,0 +1,22 @@ +# Emojivoto +[Emojivoto](https://github.com/BuoyantIO/emojivoto) is a simple and fun application that's well suited to test the basic functionality of your cluster. + + + +
emojivoto - Web UI + + + +1. Deploy the application: + ```bash + kubectl apply -k github.com/BuoyantIO/emojivoto/kustomize/deployment + ``` +2. Wait until it becomes available: + ```bash + kubectl wait --for=condition=available --timeout=60s -n emojivoto --all deployments + ``` +3. Forward the web service to your machine: + ```bash + kubectl -n emojivoto port-forward svc/web-svc 8080:80 + ``` +4. Visit [http://localhost:8080](http://localhost:8080) diff --git a/docs/versioned_docs/version-2.17/getting-started/examples/filestash-s3proxy.md b/docs/versioned_docs/version-2.17/getting-started/examples/filestash-s3proxy.md new file mode 100644 index 000000000..b9a394256 --- /dev/null +++ b/docs/versioned_docs/version-2.17/getting-started/examples/filestash-s3proxy.md @@ -0,0 +1,107 @@ + +# Deploying Filestash + +Filestash is a web frontend for different storage backends, including S3. +It's a useful application to showcase s3proxy in action. + +1. Deploy s3proxy as described in [Deployment](../../workflows/s3proxy.md#deployment). +2. Create a deployment file for Filestash with one pod: + +```sh +cat << EOF > "deployment-filestash.yaml" +apiVersion: apps/v1 +kind: Deployment +metadata: + name: filestash +spec: + replicas: 1 + selector: + matchLabels: + app: filestash + template: + metadata: + labels: + app: filestash + spec: + hostAliases: + - ip: $(kubectl get svc s3proxy-service -o=jsonpath='{.spec.clusterIP}') + hostnames: + - "s3.us-east-1.amazonaws.com" + - "s3.us-east-2.amazonaws.com" + - "s3.us-west-1.amazonaws.com" + - "s3.us-west-2.amazonaws.com" + - "s3.eu-north-1.amazonaws.com" + - "s3.eu-south-1.amazonaws.com" + - "s3.eu-south-2.amazonaws.com" + - "s3.eu-west-1.amazonaws.com" + - "s3.eu-west-2.amazonaws.com" + - "s3.eu-west-3.amazonaws.com" + - "s3.eu-central-1.amazonaws.com" + - "s3.eu-central-2.amazonaws.com" + - "s3.ap-northeast-1.amazonaws.com" + - "s3.ap-northeast-2.amazonaws.com" + - "s3.ap-northeast-3.amazonaws.com" + - "s3.ap-east-1.amazonaws.com" + - "s3.ap-southeast-1.amazonaws.com" + - "s3.ap-southeast-2.amazonaws.com" + - "s3.ap-southeast-3.amazonaws.com" + - "s3.ap-southeast-4.amazonaws.com" + - "s3.ap-south-1.amazonaws.com" + - "s3.ap-south-2.amazonaws.com" + - "s3.me-south-1.amazonaws.com" + - "s3.me-central-1.amazonaws.com" + - "s3.il-central-1.amazonaws.com" + - "s3.af-south-1.amazonaws.com" + - "s3.ca-central-1.amazonaws.com" + - "s3.sa-east-1.amazonaws.com" + containers: + - name: filestash + image: machines/filestash:latest + ports: + - containerPort: 8334 + volumeMounts: + - name: ca-cert + mountPath: /etc/ssl/certs/kube-ca.crt + subPath: kube-ca.crt + volumes: + - name: ca-cert + secret: + secretName: s3proxy-tls + items: + - key: ca.crt + path: kube-ca.crt +EOF +``` + +The pod spec includes the `hostAliases` key, which adds an entry to the pod's `/etc/hosts`. +The entry forwards all requests for any of the currently defined AWS regions to the Kubernetes service `s3proxy-service`. +If you followed the s3proxy [Deployment](../../workflows/s3proxy.md#deployment) guide, this service points to a s3proxy pod. + +The deployment specifies all regions explicitly to prevent accidental data leaks. +If one of your buckets were located in a region that's not part of the `hostAliases` key, traffic towards those buckets would not be redirected to s3proxy. +Similarly, if you want to exclude data for specific regions from going through s3proxy you can remove those regions from the deployment. + +The spec also includes a volume mount for the TLS certificate and adds it to the pod's certificate trust store. +The volume is called `ca-cert`. +The key `ca.crt` of that volume is mounted to `/etc/ssl/certs/kube-ca.crt`, which is the default certificate trust store location for that container's OpenSSL library. +Not adding the CA certificate will result in TLS authentication errors. + +3. Apply the file: `kubectl apply -f deployment-filestash.yaml` + +Afterward, you can use a port forward to access the Filestash pod: +`kubectl port-forward pod/$(kubectl get pod --selector='app=filestash' -o=jsonpath='{.items[*].metadata.name}') 8334:8334` + +4. After browsing to `localhost:8443`, Filestash will ask you to set an administrator password. +After setting it, you can directly leave the admin area by clicking the blue cloud symbol in the top left corner. +Subsequently, you can select S3 as storage backend and enter your credentials. +This will bring you to an overview of your buckets. +If you want to deploy Filestash in production, take a look at its [documentation](https://www.filestash.app/docs/). + +5. To see the logs of s3proxy intercepting requests made to S3, run: `kubectl logs -f pod/$(kubectl get pod --selector='app=s3proxy' -o=jsonpath='{.items[*].metadata.name}')` +Look out for log messages labeled `intercepting`. +There is one such log message for each message that's encrypted, decrypted, or blocked. + +6. Once you have uploaded a file with Filestash, you should be able to view the file in Filestash. +However, if you go to the AWS S3 [Web UI](https://s3.console.aws.amazon.com/s3/home) and download the file you just uploaded in Filestash, you won't be able to read it. +Another way to spot encrypted files without downloading them is to click on a file, scroll to the Metadata section, and look for the header named `x-amz-meta-constellation-encryption`. +This header holds the encrypted data encryption key of the object and is only present on objects that are encrypted by s3proxy. diff --git a/docs/versioned_docs/version-2.17/getting-started/examples/horizontal-scaling.md b/docs/versioned_docs/version-2.17/getting-started/examples/horizontal-scaling.md new file mode 100644 index 000000000..dfaf9e742 --- /dev/null +++ b/docs/versioned_docs/version-2.17/getting-started/examples/horizontal-scaling.md @@ -0,0 +1,98 @@ +# Horizontal Pod Autoscaling +This example demonstrates Constellation's autoscaling capabilities. It's based on the Kubernetes [HorizontalPodAutoscaler Walkthrough](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). During the following steps, Constellation will spawn new VMs on demand, verify them, add them to the cluster, and delete them again when the load has settled down. + +## Requirements +The cluster needs to be initialized with Kubernetes 1.23 or later. In addition, [autoscaling must be enabled](../../workflows/scale.md) to enable Constellation to assign new nodes dynamically. + +Just for this example specifically, the cluster should have as few worker nodes in the beginning as possible. Start with a small cluster with only *one* low-powered node for the control-plane node and *one* low-powered worker node. + +:::info +We tested the example using instances of types `Standard_DC4as_v5` on Azure and `n2d-standard-4` on GCP. +::: + +## Setup + +1. Install the Kubernetes Metrics Server: + ```bash + kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml + ``` + +2. Deploy the HPA example server that's supposed to be scaled under load. + + This manifest is similar to the one from the Kubernetes HPA walkthrough, but with increased CPU limits and requests to facilitate the triggering of node scaling events. + ```bash + cat < + +Online Boutique - Web UI + + + +1. Create a namespace: + ```bash + kubectl create ns boutique + ``` +2. Deploy the application: + ```bash + kubectl apply -n boutique -f https://github.com/GoogleCloudPlatform/microservices-demo/raw/main/release/kubernetes-manifests.yaml + ``` +3. Wait for all services to become available: + ```bash + kubectl wait --for=condition=available --timeout=300s -n boutique --all deployments + ``` +4. Get the frontend's external IP address: + ```shell-session + $ kubectl get service frontend-external -n boutique | awk '{print $4}' + EXTERNAL-IP + + ``` + (`` is a placeholder for the IP assigned by your CSP.) +5. Enter the IP from the result in your browser to browse the online shop. diff --git a/docs/versioned_docs/version-2.17/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.17/getting-started/first-steps-local.md new file mode 100644 index 000000000..98f0302de --- /dev/null +++ b/docs/versioned_docs/version-2.17/getting-started/first-steps-local.md @@ -0,0 +1,277 @@ +# First steps with a local cluster + +A local cluster lets you deploy and test Constellation without a cloud subscription. +You have two options: + +* Use MiniConstellation to automatically deploy a two-node cluster. +* For more fine-grained control, create the cluster using the QEMU provider. + +Both options use virtualization to create a local cluster with control-plane nodes and worker nodes. They **don't** require hardware with Confidential VM (CVM) support. For attestation, they currently use a software-based vTPM provided by KVM/QEMU. + +You need an x64 machine with a Linux OS. +You can use a VM, but it needs nested virtualization. + +## Prerequisites + +* Machine requirements: + * An x86-64 CPU with at least 4 cores (6 cores are recommended) + * At least 4 GB RAM (6 GB are recommended) + * 20 GB of free disk space + * Hardware virtualization enabled in the BIOS/UEFI (often referred to as Intel VT-x or AMD-V/SVM) / nested-virtualization support when using a VM +* Software requirements: + * Linux OS with [KVM kernel module](https://www.linux-kvm.org/page/Main_Page) + * Recommended: Ubuntu 22.04 LTS + * [Docker](https://docs.docker.com/engine/install/) + * [xsltproc](https://gitlab.gnome.org/GNOME/libxslt/-/wikis/home) + * (Optional) [virsh](https://www.libvirt.org/manpages/virsh.html) to observe and access your nodes + +### Software installation on Ubuntu + +```bash +# install Docker +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null +sudo apt update +sudo apt install docker-ce +# install other dependencies +sudo apt install xsltproc +sudo snap install kubectl --classic +# install Constellation CLI +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-linux-amd64 +sudo install constellation-linux-amd64 /usr/local/bin/constellation +# do not drop forwarded packages +sudo iptables -P FORWARD ACCEPT +``` + +## Create a cluster + + + + + +With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). + + +:::caution + +MiniConstellation has specific soft- and hardware requirements such as a Linux OS running on an x86-64 CPU. Pay attention to all [prerequisites](#prerequisites) when setting up. + +::: + +:::note + +Since MiniConstellation runs on your local system, cloud features such as load balancing, +attaching persistent storage, or autoscaling aren't available. + +::: + +The following creates your MiniConstellation cluster (may take up to 10 minutes to complete): + +```bash +constellation mini up +``` + +This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. +All `constellation` commands concerning this cluster need to be issued from this directory. + + + + +With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. + +:::caution + +Constellation on QEMU has specific soft- and hardware requirements such as a Linux OS running on an x86-64 CPU. Pay attention to all [prerequisites](#prerequisites) when setting up. + +::: + +:::note + +Since Constellation on QEMU runs on your local system, cloud features such as load balancing, +attaching persistent storage, or autoscaling aren't available. + +::: + +1. To set up your local cluster, you need to create a configuration file for Constellation first. + + ```bash + constellation config generate qemu + ``` + + This creates a [configuration file](../workflows/config.md) for QEMU called `constellation-conf.yaml`. After that, your current folder also becomes your [workspace](../architecture/orchestration.md#workspaces). All `constellation` commands for your cluster need to be executed from this directory. + +2. Now you can create your cluster and its nodes. `constellation apply` uses the options set in `constellation-conf.yaml`. + + ```bash + constellation apply -y + ``` + + The Output should look like the following: + + ```shell-session + $ constellation apply -y + Checking for infrastructure changes + The following Constellation cluster will be created: + 3 control-plane nodes of type 2-vCPUs will be created. + 1 worker node of type 2-vCPUs will be created. + Creating + Cloud infrastructure created successfully. + Your Constellation master secret was successfully written to ./constellation-mastersecret.json + Connecting + Initializing cluster + Installing Kubernetes components + Your Constellation cluster was successfully initialized. + + Constellation cluster identifier g6iMP5wRU1b7mpOz2WEISlIYSfdAhB0oNaOg6XEwKFY= + Kubernetes configuration constellation-admin.conf + + You can now connect to your cluster by executing: + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + + The cluster's identifier will be different in your output. + Keep `constellation-mastersecret.json` somewhere safe. + This will allow you to [recover your cluster](../workflows/recovery.md) in case of a disaster. + + :::info + + Depending on your setup, `constellation apply` may take 10+ minutes to complete. + + ::: + +3. Configure kubectl + + ```bash + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + + + + +## Connect to the cluster + +Your cluster initially consists of a single control-plane node: + +```shell-session +$ kubectl get nodes +NAME STATUS ROLES AGE VERSION +control-plane-0 Ready control-plane 66s v1.24.6 +``` + +Additional nodes will request to join the cluster shortly. Before each additional node is allowed to join the cluster, its state is verified using remote attestation by the [JoinService](../architecture/microservices.md#joinservice). +If verification passes successfully, the new node receives keys and certificates to join the cluster. + +You can follow this process by viewing the logs of the JoinService: + +```shell-session +$ kubectl logs -n kube-system daemonsets/join-service -f +{"level":"INFO","ts":"2022-10-14T09:32:20Z","caller":"cmd/main.go:48","msg":"Constellation Node Join Service","version":"2.1.0","cloudProvider":"qemu"} +{"level":"INFO","ts":"2022-10-14T09:32:20Z","logger":"validator","caller":"watcher/validator.go:96","msg":"Updating expected measurements"} +... +``` + +Once all nodes have joined your cluster, it may take a couple of minutes for all resources to become available. +You can check on the state of your cluster by running the following: + +```shell-session +$ kubectl get nodes +NAME STATUS ROLES AGE VERSION +control-plane-0 Ready control-plane 2m59s v1.24.6 +worker-0 Ready 32s v1.24.6 +``` + +## Deploy a sample application + +1. Deploy the [emojivoto app](https://github.com/BuoyantIO/emojivoto) + + ```bash + kubectl apply -k github.com/BuoyantIO/emojivoto/kustomize/deployment + ``` + +2. Expose the frontend service locally + + ```bash + kubectl wait --for=condition=available --timeout=60s -n emojivoto --all deployments + kubectl -n emojivoto port-forward svc/web-svc 8080:80 & + curl http://localhost:8080 + kill %1 + ``` + +## Terminate your cluster + + + + +Once you are done, you can clean up the created resources using the following command: + +```bash +constellation mini down +``` + +This will destroy your cluster and clean up your workspace. +The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. + + + + +Once you are done, you can clean up the created resources using the following command: + +```bash +constellation terminate +``` + +This should give the following output: + +```shell-session +$ constellation terminate +You are about to terminate a Constellation cluster. +All of its associated resources will be DESTROYED. +This action is irreversible and ALL DATA WILL BE LOST. +Do you want to continue? [y/n]: +``` + +Confirm with `y` to terminate the cluster: + +```shell-session +Terminating ... +Your Constellation cluster was terminated successfully. +``` + +This will destroy your cluster and clean up your workspace. +The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. + + + + +## Troubleshooting + +Make sure to use the [latest release](https://github.com/edgelesssys/constellation/releases/latest) and check out the [known issues](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22). + +### VMs have no internet access / CLI remains in "Initializing cluster" state + +`iptables` rules may prevent your VMs from accessing the internet. +Make sure your rules aren't dropping forwarded packages. + +List your rules: + +```bash +sudo iptables -S +``` + +The output may look similar to the following: + +```shell-session +-P INPUT ACCEPT +-P FORWARD DROP +-P OUTPUT ACCEPT +-N DOCKER +-N DOCKER-ISOLATION-STAGE-1 +-N DOCKER-ISOLATION-STAGE-2 +-N DOCKER-USER +``` + +If your `FORWARD` chain is set to `DROP`, you need to update your rules: + +```bash +sudo iptables -P FORWARD ACCEPT +``` diff --git a/docs/versioned_docs/version-2.17/getting-started/first-steps.md b/docs/versioned_docs/version-2.17/getting-started/first-steps.md new file mode 100644 index 000000000..9b37efa64 --- /dev/null +++ b/docs/versioned_docs/version-2.17/getting-started/first-steps.md @@ -0,0 +1,229 @@ +# First steps with Constellation + +The following steps guide you through the process of creating a cluster and deploying a sample app. This example assumes that you have successfully [installed and set up Constellation](install.md), +and have access to a cloud subscription. + +:::tip +If you don't have a cloud subscription, you can also set up a [local Constellation cluster using virtualization](../getting-started/first-steps-local.md) for testing. +::: + +:::note +If you encounter any problem with the following steps, make sure to use the [latest release](https://github.com/edgelesssys/constellation/releases/latest) and check out the [known issues](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22). +::: + +## Create a cluster + +1. Create the [configuration file](../workflows/config.md) and state file for your cloud provider. If you are following the steps of this guide, there is no need to edit the file. + + + + + ```bash + constellation config generate aws + ``` + + + + + ```bash + constellation config generate azure + ``` + + + + + ```bash + constellation config generate gcp + ``` + + + + + ```bash + constellation config generate stackit + ``` + + + + +2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). + + + + + ```bash + constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config + ``` + + This command creates IAM configuration for the AWS zone `us-east-2a` using the prefix `constellTest` for all named resources being created. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. + + Depending on the attestation variant selected on config generation, different regions are available. + AMD SEV-SNP machines (requires the default attestation variant `awsSEVSNP`) are currently available in the following regions: + * `eu-west-1` + * `us-east-2` + + You can find a list of regions that support AMD SEV-SNP in [AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/snp-requirements.html). + + NitroTPM machines (requires the attestation variant `awsNitroTPM`) are available in all regions. + Constellation OS images are currently replicated to the following regions: + * `eu-central-1` + * `eu-west-1` + * `eu-west-3` + * `us-east-2` + * `ap-south-1` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+AWS+image+region:+xx-xxxx-x). + + You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). + + + + + ```bash + constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config + ``` + + This command creates IAM configuration on the Azure region `westus` creating a new resource group `constellTest` and a new service principal `spTest`. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. + + CVMs are available in several Azure regions. Constellation OS images are currently replicated to the following: + + * `germanywestcentral` + * `westus` + * `eastus` + * `northeurope` + * `westeurope` + * `southeastasia` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+Azure+image+region:+xx-xxxx-x). + + You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). + + + + + ```bash + constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config + ``` + + This command creates IAM configuration in the GCP project `yourproject-12345` on the GCP zone `europe-west2-a` creating a new service account `constell-test`. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. + + Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. + + + + + To use Constellation on STACKIT, the cluster will use the User Access Token (UAT) that's generated [during the install step](./install.md). + After creating the accounts, fill in the STACKIT details in `constellation-conf.yaml` under `provider.openstack`: + + * `stackitProjectID`: STACKIT project id (can be found after login on the [STACKIT portal](https://portal.stackit.cloud)) + + + + + :::tip + To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). + ::: + + + +3. Create the cluster. `constellation apply` uses options set in `constellation-conf.yaml`. + If you want to manually manage your cloud resources, for example by using [Terraform](../reference/terraform.md), follow the corresponding instructions in the [Create workflow](../workflows/create.md). + + :::tip + + On Azure, you may need to wait 15+ minutes at this point for role assignments to propagate. + + ::: + + ```bash + constellation apply -y + ``` + + This should look similar to the following: + + ```shell-session + $ constellation apply -y + Checking for infrastructure changes + The following Constellation cluster will be created: + 3 control-plane nodes of type n2d-standard-4 will be created. + 1 worker node of type n2d-standard-4 will be created. + Creating + Cloud infrastructure created successfully + Your Constellation master secret was successfully written to ./constellation-mastersecret.json + Connecting + Initializing cluster + Installing Kubernetes components + Your Constellation cluster was successfully initialized. + + Constellation cluster identifier g6iMP5wRU1b7mpOz2WEISlIYSfdAhB0oNaOg6XEwKFY= + Kubernetes configuration constellation-admin.conf + + You can now connect to your cluster by executing: + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + + The cluster's identifier will be different in your output. + Keep `constellation-mastersecret.json` somewhere safe. + This will allow you to [recover your cluster](../workflows/recovery.md) in case of a disaster. + + :::info + + Depending on your CSP and region, `constellation apply` may take 10+ minutes to complete. + + ::: + +4. Configure kubectl. + + ```bash + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + +## Deploy a sample application + +1. Deploy the [emojivoto app](https://github.com/BuoyantIO/emojivoto) + + ```bash + kubectl apply -k github.com/BuoyantIO/emojivoto/kustomize/deployment + ``` + +2. Expose the frontend service locally + + ```bash + kubectl wait --for=condition=available --timeout=60s -n emojivoto --all deployments + kubectl -n emojivoto port-forward svc/web-svc 8080:80 & + curl http://localhost:8080 + kill %1 + ``` + +## Terminate your cluster + +Use the CLI to terminate your cluster. If you manually used [Terraform](../reference/terraform.md) to manage your cloud resources, follow the corresponding instructions in the [Terminate workflow](../workflows/terminate.md). + +```bash +constellation terminate +``` + +This should give the following output: + +```shell-session +$ constellation terminate +You are about to terminate a Constellation cluster. +All of its associated resources will be DESTROYED. +This action is irreversible and ALL DATA WILL BE LOST. +Do you want to continue? [y/n]: +``` + +Confirm with `y` to terminate the cluster: + +```shell-session +Terminating ... +Your Constellation cluster was terminated successfully. +``` + +Optionally, you can also [delete your IAM resources](../workflows/config.md#deleting-an-iam-configuration). diff --git a/docs/versioned_docs/version-2.17/getting-started/install.md b/docs/versioned_docs/version-2.17/getting-started/install.md new file mode 100644 index 000000000..d52e43476 --- /dev/null +++ b/docs/versioned_docs/version-2.17/getting-started/install.md @@ -0,0 +1,429 @@ +# Installation and setup + +Constellation runs entirely in your cloud environment and can be controlled via a dedicated [command-line interface (CLI)](../reference/cli.md) or a [Terraform provider](../workflows/terraform-provider.md). + +## Prerequisites + +Make sure the following requirements are met: + +* Your machine is running Linux, macOS, or Windows +* You have admin rights on your machine +* [kubectl](https://kubernetes.io/docs/tasks/tools/) is installed +* Your CSP is Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), or STACKIT + +## Install the Constellation CLI + +:::tip + +If you prefer to use Terraform, you can alternatively use the [Terraform provider](../workflows/terraform-provider.md) to manage the cluster's lifecycle. + +::: + +The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). +Install it with the following commands: + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-linux-amd64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-linux-amd64 /usr/local/bin/constellation +``` + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-linux-arm64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-linux-arm64 /usr/local/bin/constellation +``` + + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-darwin-arm64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-darwin-arm64 /usr/local/bin/constellation +``` + + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-darwin-amd64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-darwin-amd64 /usr/local/bin/constellation +``` + + + + + +1. Download the CLI: + +```bash +Invoke-WebRequest -OutFile ./constellation.exe -Uri 'https://github.com/edgelesssys/constellation/releases/latest/download/constellation-windows-amd64.exe' +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI under `C:\Program Files\Constellation\bin\constellation.exe` + +3. Add the CLI to your PATH: + + 1. Open `Advanced system settings` by searching for the App in the Windows search + 2. Go to the `Advanced` tab + 3. Click `Environment Variables…` + 4. Click variable called `Path` and click `Edit…` + 5. Click `New` + 6. Enter the path to the folder containing the binary you want on your PATH: `C:\Program Files\Constellation\bin` + + + + +:::tip +The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. +::: + +## Set up cloud credentials + +Constellation makes authenticated calls to the CSP API. Therefore, you need to set up Constellation with the credentials for your CSP. + +:::tip +If you don't have a cloud subscription, you can also set up a [local Constellation cluster using virtualization](../getting-started/first-steps-local.md) for testing. +::: + +### Required permissions + + + + +To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. + +To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:DescribeAccountAttributes", + "iam:AddRoleToInstanceProfile", + "iam:AttachRolePolicy", + "iam:CreateInstanceProfile", + "iam:CreatePolicy", + "iam:CreateRole", + "iam:DeleteInstanceProfile", + "iam:DeletePolicy", + "iam:DeletePolicyVersion", + "iam:DeleteRole", + "iam:DetachRolePolicy", + "iam:GetInstanceProfile", + "iam:GetPolicy", + "iam:GetPolicyVersion", + "iam:GetRole", + "iam:ListAttachedRolePolicies", + "iam:ListInstanceProfilesForRole", + "iam:ListPolicyVersions", + "iam:ListRolePolicies", + "iam:PassRole", + "iam:RemoveRoleFromInstanceProfile", + "sts:GetCallerIdentity" + ], + "Resource": "*" + } + ] +} +``` + +The built-in `AdministratorAccess` policy is a superset of these permissions. + +To [create a Constellation cluster](../workflows/create.md), see the permissions of [main.tf](https://github.com/edgelesssys/constellation/blob/main/terraform/infrastructure/iam/aws/main.tf). + +The built-in `PowerUserAccess` policy is a superset of these permissions. + +Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). + + + + +The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: + +* `Microsoft.Attestation` +* `Microsoft.Compute` +* `Microsoft.Insights` +* `Microsoft.ManagedIdentity` +* `Microsoft.Network` + +By default, Constellation tries to register these automatically if they haven't been registered before. + +To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: + +* `*/register/action` \[1] +* `Microsoft.Authorization/roleAssignments/*` +* `Microsoft.Authorization/roleDefinitions/*` +* `Microsoft.ManagedIdentity/userAssignedIdentities/*` +* `Microsoft.Resources/subscriptions/resourcegroups/*` + +The built-in `Owner` role is a superset of these permissions. + +To [create a Constellation cluster](../workflows/create.md), you need the following permissions: + +* `Microsoft.Attestation/attestationProviders/*` +* `Microsoft.Compute/virtualMachineScaleSets/*` +* `Microsoft.Insights/components/*` +* `Microsoft.ManagedIdentity/userAssignedIdentities/*` +* `Microsoft.Network/loadBalancers/*` +* `Microsoft.Network/loadBalancers/backendAddressPools/*` +* `Microsoft.Network/networkSecurityGroups/*` +* `Microsoft.Network/publicIPAddresses/*` +* `Microsoft.Network/virtualNetworks/*` +* `Microsoft.Network/virtualNetworks/subnets/*` +* `Microsoft.Network/natGateways/*` + +The built-in `Contributor` role is a superset of these permissions. + +Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-definitions) and [assigning roles](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments). + +1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. + + + + +Create a new project for Constellation or use an existing one. +Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. + +To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: + +* `iam.serviceAccountKeys.create` +* `iam.serviceAccountKeys.delete` +* `iam.serviceAccountKeys.get` +* `iam.serviceAccounts.create` +* `iam.serviceAccounts.delete` +* `iam.serviceAccounts.get` +* `resourcemanager.projects.getIamPolicy` +* `resourcemanager.projects.setIamPolicy` + +Together, the built-in roles `roles/editor` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. + +To [create a Constellation cluster](../workflows/create.md), you need the following permissions: + +* `compute.addresses.createInternal` +* `compute.addresses.deleteInternal` +* `compute.addresses.get` +* `compute.addresses.useInternal` +* `compute.backendServices.create` +* `compute.backendServices.delete` +* `compute.backendServices.get` +* `compute.backendServices.use` +* `compute.disks.create` +* `compute.firewalls.create` +* `compute.firewalls.delete` +* `compute.firewalls.get` +* `compute.firewalls.update` +* `compute.globalAddresses.create` +* `compute.globalAddresses.delete` +* `compute.globalAddresses.get` +* `compute.globalAddresses.use` +* `compute.globalForwardingRules.create` +* `compute.globalForwardingRules.delete` +* `compute.globalForwardingRules.get` +* `compute.globalForwardingRules.setLabels` +* `compute.globalOperations.get` +* `compute.healthChecks.create` +* `compute.healthChecks.delete` +* `compute.healthChecks.get` +* `compute.healthChecks.useReadOnly` +* `compute.instanceGroupManagers.create` +* `compute.instanceGroupManagers.delete` +* `compute.instanceGroupManagers.get` +* `compute.instanceGroupManagers.update` +* `compute.instanceGroups.create` +* `compute.instanceGroups.delete` +* `compute.instanceGroups.get` +* `compute.instanceGroups.update` +* `compute.instanceGroups.use` +* `compute.instances.create` +* `compute.instances.setLabels` +* `compute.instances.setMetadata` +* `compute.instances.setTags` +* `compute.instanceTemplates.create` +* `compute.instanceTemplates.delete` +* `compute.instanceTemplates.get` +* `compute.instanceTemplates.useReadOnly` +* `compute.networks.create` +* `compute.networks.delete` +* `compute.networks.get` +* `compute.networks.updatePolicy` +* `compute.routers.create` +* `compute.routers.delete` +* `compute.routers.get` +* `compute.routers.update` +* `compute.subnetworks.create` +* `compute.subnetworks.delete` +* `compute.subnetworks.get` +* `compute.subnetworks.use` +* `compute.targetTcpProxies.create` +* `compute.targetTcpProxies.delete` +* `compute.targetTcpProxies.get` +* `compute.targetTcpProxies.use` +* `iam.serviceAccounts.actAs` + +Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. + +Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). + + + + +Constellation on STACKIT requires a User Access Token (UAT) for the OpenStack API and a STACKIT service account. +The UAT already has all required permissions by default. +The STACKIT service account needs the `editor` role to create STACKIT LoadBalancers. +Look at the [STACKIT documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) on how to create the service account and assign the role. + + + + +### Authentication + +You need to authenticate with your CSP. The following lists the required steps for *testing* and *production* environments. + +:::note +The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. +::: + + + + +**Testing** + +You can use the [AWS CloudShell](https://console.aws.amazon.com/cloudshell/home). Make sure you are [authorized to use it](https://docs.aws.amazon.com/cloudshell/latest/userguide/sec-auth-with-identities.html). + +**Production** + +Use the latest version of the [AWS CLI](https://aws.amazon.com/cli/) on a trusted machine: + +```bash +aws configure +``` + +Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). + + + + +**Testing** + +Simply open the [Azure Cloud Shell](https://docs.microsoft.com/en-us/azure/cloud-shell/overview). + +**Production** + +Use the latest version of the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/) on a trusted machine: + +```bash +az login +``` + +Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). + + + + +**Testing** + +You can use the [Google Cloud Shell](https://cloud.google.com/shell). Make sure your [session is authorized](https://cloud.google.com/shell/docs/auth). For example, execute `gsutil` and accept the authorization prompt. + +**Production** + +Use one of the following options on a trusted machine: + +* Use the [`gcloud` CLI](https://cloud.google.com/sdk/gcloud) + + ```bash + gcloud auth application-default login + ``` + + This will ask you to log-in to your Google account and create your credentials. + The Constellation CLI will automatically load these credentials when needed. + +* Set up a service account and pass the credentials manually + + Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. + + + + +You need to authenticate with the infrastructure API (OpenStack) and create a service account (STACKIT API). + +1. [Follow the STACKIT documentation](https://docs.stackit.cloud/stackit/en/step-1-generating-of-user-access-token-11763726.html) for obtaining a User Access Token (UAT) to use the infrastructure API +2. Create a configuration file under `~/.config/openstack/clouds.yaml` (`%AppData%\openstack\clouds.yaml` on Windows) with the credentials from the User Access Token + + ```yaml + clouds: + stackit: + auth: + auth_url: https://keystone.api.iaas.eu01.stackit.cloud/v3 + username: REPLACE_WITH_UAT_USERNAME + password: REPLACE_WITH_UAT_PASSWORD + project_id: REPLACE_WITH_STACKIT_PROJECT_ID + project_name: REPLACE_WITH_STACKIT_PROJECT_NAME + user_domain_name: portal_mvp + project_domain_name: portal_mvp + region_name: RegionOne + identity_api_version: 3 + ``` + +3. [Follow the STACKIT documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) for creating a service account and an access token +4. Assign the `editor` role to the service account by [following the documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) +5. Create a configuration file under `~/.stackit/credentials.json` (`%USERPROFILE%\.stackit\credentials.json` on Windows) + + ```json + {"STACKIT_SERVICE_ACCOUNT_TOKEN":"REPLACE_WITH_TOKEN"} + ``` + + + + + +## Next steps + +You are now ready to [deploy your first confidential Kubernetes cluster and application](first-steps.md). diff --git a/docs/versioned_docs/version-2.17/getting-started/marketplaces.md b/docs/versioned_docs/version-2.17/getting-started/marketplaces.md new file mode 100644 index 000000000..a6763a42a --- /dev/null +++ b/docs/versioned_docs/version-2.17/getting-started/marketplaces.md @@ -0,0 +1,56 @@ +# Using Constellation via Cloud Marketplaces + +Constellation is available through the Marketplaces of AWS, Azure, GCP, and STACKIT. This allows you to create self-managed Constellation clusters that are billed on a pay-per-use basis (hourly, per vCPU) with your CSP account. You can still get direct support by Edgeless Systems. For more information, please [contact us](https://www.edgeless.systems/enterprise-support/). + +This document explains how to run Constellation with the dynamically billed cloud marketplace images. + + + + +To use Constellation's marketplace images, ensure that you are subscribed to the [marketplace offering](https://aws.amazon.com/marketplace/pp/prodview-2mbn65nv57oys) through the web portal. + +Then, enable the use of marketplace images in your Constellation `constellation-conf.yaml` [config file](../workflows/config.md): + +```bash +yq eval -i ".provider.aws.useMarketplaceImage = true" constellation-conf.yaml +``` + + + + +Constellation has a private marketplace plan. Please [contact us](https://www.edgeless.systems/enterprise-support/) to gain access. + +To use a marketplace image, you need to accept the marketplace image's terms once for your subscription with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/vm/image/terms?view=azure-cli-latest): + +```bash +az vm image terms accept --publisher edgelesssystems --offer constellation --plan constellation +``` + +Then, enable the use of marketplace images in your Constellation `constellation-conf.yaml` [config file](../workflows/config.md): + +```bash +yq eval -i ".provider.azure.useMarketplaceImage = true" constellation-conf.yaml +``` + + + + +To use a marketplace image, ensure that the account is entitled to use marketplace images by Edgeless Systems by accepting the terms through the [web portal](https://console.cloud.google.com/marketplace/vm/config/edgeless-systems-public/constellation). + +Then, enable the use of marketplace images in your Constellation `constellation-conf.yaml` [config file](../workflows/config.md): + +```bash +yq eval -i ".provider.gcp.useMarketplaceImage = true" constellation-conf.yaml +``` + + + + +On STACKIT, the selected Constellation image is always a marketplace image. You can find more information on the STACKIT portal. + + + + +Ensure that the cluster uses an official release image version (i.e., `.image=vX.Y.Z` in the `constellation-conf.yaml` file). + +From there, you can proceed with the [cluster creation](../workflows/create.md) as usual. diff --git a/docs/versioned_docs/version-2.17/intro.md b/docs/versioned_docs/version-2.17/intro.md new file mode 100644 index 000000000..0bfe86da9 --- /dev/null +++ b/docs/versioned_docs/version-2.17/intro.md @@ -0,0 +1,34 @@ +--- +slug: / +id: intro +--- +# Introduction + +Welcome to the documentation of Constellation! Constellation is a Kubernetes engine that aims to provide the best possible data security. + +![Constellation concept](/img/concept.svg) + + Constellation shields your entire Kubernetes cluster from the underlying cloud infrastructure. Everything inside is always encrypted, including at runtime in memory. For this, Constellation leverages a technology called *confidential computing* and more specifically Confidential VMs. + +:::tip +See the 📄[whitepaper](https://content.edgeless.systems/hubfs/Confidential%20Computing%20Whitepaper.pdf) for more information on confidential computing. +::: + +## Goals + +From a security perspective, Constellation is designed to keep all data always encrypted and to prevent any access from the underlying (cloud) infrastructure. This includes access from datacenter employees, privileged cloud admins, and attackers coming through the infrastructure. Such attackers could be malicious co-tenants escalating their privileges or hackers who managed to compromise a cloud server. + +From a DevOps perspective, Constellation is designed to work just like what you would expect from a modern Kubernetes engine. + +## Use cases + +Constellation provides unique security [features](overview/confidential-kubernetes.md) and [benefits](overview/security-benefits.md). The core use cases are: + +* Increasing the overall security of your clusters +* Increasing the trustworthiness of your SaaS offerings +* Moving sensitive workloads from on-prem to the cloud +* Meeting regulatory requirements + +## Next steps + +You can learn more about the concept of Confidential Kubernetes, features, security benefits, and performance of Constellation in the *Basics* section. To jump right into the action head to *Getting started*. diff --git a/docs/versioned_docs/version-2.17/overview/clouds.md b/docs/versioned_docs/version-2.17/overview/clouds.md new file mode 100644 index 000000000..b2695d28e --- /dev/null +++ b/docs/versioned_docs/version-2.17/overview/clouds.md @@ -0,0 +1,66 @@ +# Feature status of clouds + +What works on which cloud? Currently, Confidential VMs (CVMs) are available in varying quality on the different clouds and software stacks. + +For Constellation, the ideal environment provides the following: + +1. Ability to run arbitrary software and images inside CVMs +2. CVMs based on AMD SEV-SNP (available in EPYC CPUs since the Milan generation) or Intel TDX (available in Xeon CPUs since the Sapphire Rapids generation) +3. Ability for CVM guests to obtain raw hardware attestation statements +4. Reviewable, open-source firmware inside CVMs +5. Capability of the firmware to attest the integrity of the code it passes control to, e.g., with an embedded virtual TPM (vTPM) + +(1) is a functional must-have. (2)--(5) are required for remote attestation that fully keeps the infrastructure/cloud out. Constellation can work without them or with approximations, but won't protect against certain privileged attackers anymore. + +The following table summarizes the state of features for different infrastructures. + +| **Feature** | **AWS** | **Azure** | **GCP** | **STACKIT** | **OpenStack (Yoga)** | +|-----------------------------------|---------|-----------|---------|--------------|----------------------| +| **1. Custom images** | Yes | Yes | Yes | Yes | Yes | +| **2. SEV-SNP or TDX** | Yes | Yes | Yes | No | Depends on kernel/HV | +| **3. Raw guest attestation** | Yes | Yes | Yes | No | Depends on kernel/HV | +| **4. Reviewable firmware** | Yes | No* | No | No | Depends on kernel/HV | +| **5. Confidential measured boot** | No | Yes | No | No | Depends on kernel/HV | + +## Amazon Web Services (AWS) + +Amazon EC2 [supports AMD SEV-SNP](https://aws.amazon.com/de/about-aws/whats-new/2023/04/amazon-ec2-amd-sev-snp/). +Regarding (3), AWS provides direct access to attestation statements. +However, regarding (5), attestation is partially based on the [NitroTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) for [measured boot](../architecture/attestation.md#measured-boot), which is a vTPM managed by the Nitro hypervisor. +Hence, the hypervisor is currently part of Constellation's TCB. +Regarding (4), the [firmware is open source](https://github.com/aws/uefi) and can be reproducibly built. + +## Microsoft Azure + +With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. +Regarding (3), Azure provides direct access to attestation statements. +The firmware runs in an isolated domain inside the CVM and exposes a vTPM (5), but it's closed source (4). +On SEV-SNP, Azure uses VM Privilege Level (VMPL) isolation for the separation of firmware and the rest of the VM; on TDX, they use TD partitioning. +This firmware is signed by Azure. +The signature is reflected in the attestation statements of CVMs. +Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). + +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. + +## Google Cloud Platform (GCP) + +The [CVMs Generally Available in GCP](https://cloud.google.com/confidential-computing/confidential-vm/docs/confidential-vm-overview#technologies) are based on AMD SEV-ES or SEV-SNP. +Regarding (3), with their SEV-SNP offering Google provides direct access to attestation statements. +However, regarding (5), attestation is partially based on the [Shielded VM vTPM](https://cloud.google.com/compute/shielded-vm/docs/shielded-vm#vtpm) for [measured boot](../architecture/attestation.md#measured-boot), which is a vTPM managed by Google's hypervisor. +Hence, the hypervisor is currently part of Constellation's TCB. +Regarding (4), the CVMs still include closed-source firmware. + +[TDX on Google](https://cloud.google.com/blog/products/identity-security/confidential-vms-on-intel-cpus-your-datas-new-intelligent-defense) is in public preview. +With it, Constellation would have a similar TCB and attestation flow as with the current SEV-SNP offering. + +## STACKIT + +[STACKIT Compute Engine](https://www.stackit.de/en/product/stackit-compute-engine/) supports AMD SEV-ES. A vTPM is used for measured boot, which is a vTPM managed by STACKIT's hypervisor. Hence, the hypervisor is currently part of Constellation's TCB. + +## OpenStack + +OpenStack is an open-source cloud and infrastructure management software. It's used by many smaller CSPs and datacenters. In the latest *Yoga* version, OpenStack has basic support for CVMs. However, much depends on the employed kernel and hypervisor. Features (2)--(4) are likely to be a *Yes* with Linux kernel version 6.2. Thus, going forward, OpenStack on corresponding AMD or Intel hardware will be a viable underpinning for Constellation. + +## Conclusion + +The different clouds and software like the Linux kernel and OpenStack are in the process of building out their support for state-of-the-art CVMs. Azure has already most features in place. For Constellation, the status quo means that the TCB has different shapes on different infrastructures. With broad SEV-SNP support coming to the Linux kernel, we soon expect a normalization of features across infrastructures. diff --git a/docs/versioned_docs/version-2.17/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.17/overview/confidential-kubernetes.md new file mode 100644 index 000000000..bff8c3322 --- /dev/null +++ b/docs/versioned_docs/version-2.17/overview/confidential-kubernetes.md @@ -0,0 +1,42 @@ +# Confidential Kubernetes + +We use the term *Confidential Kubernetes* to refer to the concept of using confidential-computing technology to shield entire Kubernetes clusters from the infrastructure. The three defining properties of this concept are: + +1. **Workload shielding**: the confidentiality and integrity of all workload-related data and code are enforced. +2. **Control plane shielding**: the confidentiality and integrity of the cluster's control plane, state, and workload configuration are enforced. +3. **Attestation and verifiability**: the two properties above can be verified remotely based on hardware-rooted cryptographic certificates. + +Each of the above properties is equally important. Only with all three in conjunction, an entire cluster can be shielded without gaps. + +## Constellation security features + +Constellation implements the Confidential Kubernetes concept with the following security features. + +* **Runtime encryption**: Constellation runs all Kubernetes nodes inside Confidential VMs (CVMs). This gives runtime encryption for the entire cluster. +* **Network and storage encryption**: Constellation augments this with transparent encryption of the [network](../architecture/networking.md), [persistent storage](../architecture/encrypted-storage.md), and other managed storage like [AWS S3](../architecture/encrypted-storage.md#encrypted-s3-object-storage). Thus, workloads and control plane are truly end-to-end encrypted: at rest, in transit, and at runtime. +* **Transparent key management**: Constellation manages the corresponding [cryptographic keys](../architecture/keys.md) inside CVMs. +* **Node attestation and verification**: Constellation verifies the integrity of each new CVM-based node using [remote attestation](../architecture/attestation.md). Only "good" nodes receive the cryptographic keys required to access the network and storage of a cluster. +* **Confidential computing-optimized images**: A node is "good" if it's running a signed Constellation [node image](../architecture/images.md) inside a CVM and is in the expected state. (Node images are hardware-measured during boot. The measurements are reflected in the attestation statements that are produced by nodes and verified by Constellation.) +* **"Whole cluster" attestation**: Towards the DevOps engineer, Constellation provides a single hardware-rooted certificate from which all of the above can be verified. + +With the above, Constellation wraps an entire cluster into one coherent and verifiable *confidential context*. The concept is depicted in the following. + +![Confidential Kubernetes](../_media/concept-constellation.svg) + +## Comparison: Managed Kubernetes with CVMs + +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. + +![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) + +The following table highlights the key differences in terms of features. + +| | Managed Kubernetes with CVMs | Confidential Kubernetes (Constellation✨) | +|-------------------------------------|------------------------------|--------------------------------------------| +| Runtime encryption | Partial (data plane only)| **Yes** | +| Node image verification | No | **Yes** | +| Full cluster attestation | No | **Yes** | +| Transparent network encryption | No | **Yes** | +| Transparent storage encryption | No | **Yes** | +| Confidential key management | No | **Yes** | +| Cloud agnostic / multi-cloud | No | **Yes** | diff --git a/docs/versioned_docs/version-2.17/overview/license.md b/docs/versioned_docs/version-2.17/overview/license.md new file mode 100644 index 000000000..34122c025 --- /dev/null +++ b/docs/versioned_docs/version-2.17/overview/license.md @@ -0,0 +1,33 @@ +# License + +## Source code + +Constellation's source code is available on [GitHub](https://github.com/edgelesssys/constellation) under the [GNU Affero General Public License v3.0](https://github.com/edgelesssys/constellation/blob/main/LICENSE). + +## Binaries + +Edgeless Systems provides ready-to-use and [signed](../architecture/attestation.md#chain-of-trust) binaries of Constellation. This includes the CLI and the [node images](../architecture/images.md). + +These binaries may be used free of charge within the bounds of Constellation's [**Community License**](#community-license). An [**Enterprise License**](#enterprise-license) can be purchased from Edgeless Systems. + +The Constellation CLI displays relevant license information when you initialize your cluster. You are responsible for staying within the bounds of your respective license. Constellation doesn't enforce any limits so as not to endanger your cluster's availability. + +## Terraform provider + +Edgeless Systems provides a [Terraform provider](https://github.com/edgelesssys/terraform-provider-constellation/releases), which may be used free of charge within the bounds of Constellation's [**Community License**](#community-license). An [**Enterprise License**](#enterprise-license) can be purchased from Edgeless Systems. + +You are responsible for staying within the bounds of your respective license. Constellation doesn't enforce any limits so as not to endanger your cluster's availability. + +## Community License + +You are free to use the Constellation binaries provided by Edgeless Systems to create services for internal consumption, evaluation purposes, or non-commercial use. You must not use the Constellation binaries to provide commercial hosted services to third parties. Edgeless Systems gives no warranties and offers no support. + +## Enterprise License + +Enterprise Licenses don't have the above limitations and come with support and additional features. Find out more at the [product website](https://www.edgeless.systems/products/constellation/). + +Once you have received your Enterprise License file, place it in your [Constellation workspace](../architecture/orchestration.md#workspaces) in a file named `constellation.license`. + +## CSP Marketplaces + +Constellation is available through the Marketplaces of AWS, Azure, GCP, and STACKIT. This allows you to create self-managed Constellation clusters that are billed on a pay-per-use basis (hourly, per vCPU) with your CSP account. You can still get direct support by Edgeless Systems. For more information, please [contact us](https://www.edgeless.systems/enterprise-support/). diff --git a/docs/versioned_docs/version-2.17/overview/performance/application.md b/docs/versioned_docs/version-2.17/overview/performance/application.md new file mode 100644 index 000000000..c67d59644 --- /dev/null +++ b/docs/versioned_docs/version-2.17/overview/performance/application.md @@ -0,0 +1,102 @@ +# Application benchmarks + +## HashiCorp Vault + +[HashiCorp Vault](https://www.vaultproject.io/) is a distributed secrets management software that can be deployed to Kubernetes. +HashiCorp maintains a benchmarking tool for vault, [vault-benchmark](https://github.com/hashicorp/vault-benchmark/). +Vault-benchmark generates load on a Vault deployment and measures response times. + +This article describes the results from running vault-benchmark on Constellation, AKS, and GKE. +You can find the setup for producing the data discussed in this article in the [vault-benchmarks](https://github.com/edgelesssys/vault-benchmarks) repository. + +The Vault API used during benchmarking is the [transits secret engine](https://developer.hashicorp.com/vault/docs/secrets/transit). +This allows services to send data to Vault for encryption, decryption, signing, and verification. + +## Results + +On each run, vault-benchmark sends requests and measures the latencies. +The measured latencies are aggregated through various statistical features. +After running the benchmark n times, the arithmetic mean over a subset of the reported statistics is calculated. +The selected features are arithmetic mean, 99th percentile, minimum, and maximum. + +Arithmetic mean gives a general sense of the latency on each target. +The 99th percentile shows performance in (most likely) erroneous states. +Minimum and maximum mark the range within which latency varies each run. + +The benchmark was configured with 1300 workers and 10 seconds per run. +Those numbers were chosen empirically. +The latency was stabilizing at 10 seconds runtime, not changing with further increase. +Increasing the number of workers beyond 1300 leads to request failures, marking the limit Vault was able to handle in this setup. +All results are based on 100 runs. + +The following data was generated while running five replicas, one primary, and four standby nodes. +All numbers are in seconds if not indicated otherwise. +``` +========== Results AKS ========== +Mean: mean: 1.632200, variance: 0.002057 +P99: mean: 5.480679, variance: 2.263700 +Max: mean: 6.651001, variance: 2.808401 +Min: mean: 0.011415, variance: 0.000133 +========== Results GKE ========== +Mean: mean: 1.656435, variance: 0.003615 +P99: mean: 6.030807, variance: 3.955051 +Max: mean: 7.164843, variance: 3.300004 +Min: mean: 0.010233, variance: 0.000111 +========== Results C11n ========== +Mean: mean: 1.651549, variance: 0.001610 +P99: mean: 5.780422, variance: 3.016106 +Max: mean: 6.942997, variance: 3.075796 +Min: mean: 0.013774, variance: 0.000228 +========== AKS vs C11n ========== +Mean: +1.171577 % (AKS is faster) +P99: +5.185495 % (AKS is faster) +Max: +4.205618 % (AKS is faster) +Min: +17.128781 % (AKS is faster) +========== GKE vs C11n ========== +Mean: -0.295851 % (GKE is slower) +P99: -4.331603 % (GKE is slower) +Max: -3.195248 % (GKE is slower) +Min: +25.710886 % (GKE is faster) +``` + +**Interpretation**: Latencies are all within ~5% of each other. +AKS performs slightly better than GKE and Constellation (C11n) in all cases except minimum latency. +Minimum latency is the lowest for GKE. +Compared to GKE, Constellation had slightly lower peak latencies (99th percentile and maximum), indicating that Constellation could have handled slightly more concurrent accesses than GKE. +Overall, performance is at comparable levels across all three distributions. +Based on these numbers, you can use a similarly sized Constellation cluster to run your existing Vault deployment. + +### Visualization + +The following plots visualize the data presented above as [box plots](https://en.wikipedia.org/wiki/Box_plot). +The whiskers denote the minimum and maximum. +The box stretches from the 25th to the 75th percentile, with the dividing bar marking the 50th percentile. +The circles outside the whiskers denote outliers. + +
+Mean Latency + +![Mean Latency](../../_media/benchmark_vault/5replicas/mean_latency.png) + +
+ +
+99th Percentile Latency + +![99th Percentile Latency](../../_media/benchmark_vault/5replicas/p99_latency.png) + +
+ +
+Maximum Latency + +![Maximum Latency](../../_media/benchmark_vault/5replicas/max_latency.png) + +
+ +
+Minimum Latency + +![Minimum Latency](../../_media/benchmark_vault/5replicas/min_latency.png) + +
diff --git a/docs/versioned_docs/version-2.17/overview/performance/compute.md b/docs/versioned_docs/version-2.17/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/versioned_docs/version-2.17/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/versioned_docs/version-2.17/overview/performance/io.md b/docs/versioned_docs/version-2.17/overview/performance/io.md new file mode 100644 index 000000000..3ae796f8a --- /dev/null +++ b/docs/versioned_docs/version-2.17/overview/performance/io.md @@ -0,0 +1,204 @@ +# I/O performance benchmarks + +To assess the overall performance of Constellation, this benchmark evaluates Constellation v2.6.0 in terms of storage I/O using [`fio`](https://fio.readthedocs.io/en/latest/fio_doc.html) and network performance using the [Kubernetes Network Benchmark](https://github.com/InfraBuilder/k8s-bench-suite#knb--kubernetes-network-be). + +This benchmark tested Constellation on Azure and GCP and compared the results against the managed Kubernetes offerings AKS and GKE. + +## Configurations + +### Constellation + +The benchmark was conducted with Constellation v2.6.0, Kubernetes v1.25.7, and Cilium v1.12. +It ran on the following infrastructure configurations. + +Constellation on Azure: + +- Nodes: 3 (1 Control-plane, 2 Worker) +- Machines: `DC4as_v5`: 3rd Generation AMD EPYC 7763v (Milan) processor with 4 Cores, 16 GiB memory +- CVM: `true` +- Region: `West US` +- Zone: `2` + +Constellation on GCP: + +- Nodes: 3 (1 Control-plane, 2 Worker) +- Machines: `n2d-standard-4`: 2nd Generation AMD EPYC (Rome) processor with 4 Cores, 16 GiB of memory +- CVM: `true` +- Zone: `europe-west3-b` + +### AKS + +On AKS, the benchmark used Kubernetes `v1.24.9` and nodes with version `AKSUbuntu-1804gen2containerd-2023.02.15`. +AKS ran with the [`kubenet`](https://learn.microsoft.com/en-us/azure/aks/concepts-network#kubenet-basic-networking) CNI and the [default CSI driver](https://learn.microsoft.com/en-us/azure/aks/azure-disk-csi) for Azure Disk. + +The following infrastructure configurations was used: + +- Nodes: 2 (2 Worker) +- Machines: `D4as_v5`: 3rd Generation AMD EPYC 7763v (Milan) processor with 4 Cores, 16 GiB memory +- CVM: `false` +- Region: `West US` +- Zone: `2` + +### GKE + +On GKE, the benchmark used Kubernetes `v1.24.9` and nodes with version `1.24.9-gke.3200`. +GKE ran with the [`kubenet`](https://cloud.google.com/kubernetes-engine/docs/concepts/network-overview) CNI and the [default CSI driver](https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/gce-pd-csi-driver) for Compute Engine persistent disk. + +The following infrastructure configurations was used: + +- Nodes: 2 (2 Worker) +- Machines: `n2d-standard-4` 2nd Generation AMD EPYC (Rome) processor with 4 Cores, 16 GiB of memory +- CVM: `false` +- Zone: `europe-west3-b` + +## Results + +### Network + +This section gives a thorough analysis of the network performance of Constellation, specifically focusing on measuring TCP and UDP bandwidth. +The benchmark measured the bandwidth of pod-to-pod and pod-to-service connections between two different nodes using [`iperf`](https://iperf.fr/). + +GKE and Constellation on GCP had a maximum network bandwidth of [10 Gbps](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines). +AKS with `Standard_D4as_v5` machines a maximum network bandwidth of [12.5 Gbps](https://learn.microsoft.com/en-us/azure/virtual-machines/dasv5-dadsv5-series#dasv5-series). +The Confidential VM equivalent `Standard_DC4as_v5` currently has a network bandwidth of [1.25 Gbps](https://learn.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series#dcasv5-series-products). +Therefore, to make the test comparable, both AKS and Constellation on Azure were running with `Standard_DC4as_v5` machines and 1.25 Gbps bandwidth. + +Constellation on Azure and AKS used an MTU of 1500. +Constellation on GCP used an MTU of 8896. GKE used an MTU of 1450. + +The difference in network bandwidth can largely be attributed to two factors. + +- Constellation's [network encryption](../../architecture/networking.md) via Cilium and WireGuard, which protects data in-transit. +- [AMD SEV using SWIOTLB bounce buffers](https://lore.kernel.org/all/20200204193500.GA15564@ashkalra_ubuntu_server/T/) for all DMA including network I/O. + +#### Pod-to-Pod + +In this scenario, the client Pod connects directly to the server pod via its IP address. + +```mermaid +flowchart LR + subgraph Node A + Client[Client] + end + subgraph Node B + Server[Server] + end + Client ==>|traffic| Server +``` + +The results for "Pod-to-Pod" on Azure are as follows: + +![Network Pod2Pod Azure benchmark graph](../../_media/benchmark_net_p2p_azure.png) + +The results for "Pod-to-Pod" on GCP are as follows: + +![Network Pod2Pod GCP benchmark graph](../../_media/benchmark_net_p2p_gcp.png) + +#### Pod-to-Service + +In this scenario, the client Pod connects to the server Pod via a ClusterIP service. This is more relevant to real-world use cases. + +```mermaid +flowchart LR + subgraph Node A + Client[Client] ==>|traffic| Service[Service] + end + subgraph Node B + Server[Server] + end + Service ==>|traffic| Server +``` + +The results for "Pod-to-Pod" on Azure are as follows: + +![Network Pod2SVC Azure benchmark graph](../../_media/benchmark_net_p2svc_azure.png) + +The results for "Pod-to-Pod" on GCP are as follows: + +![Network Pod2SVC GCP benchmark graph](../../_media/benchmark_net_p2svc_gcp.png) + +In our recent comparison of Constellation on GCP with GKE, Constellation has 58% less TCP bandwidth. However, UDP bandwidth was slightly better with Constellation, thanks to its higher MTU. + +Similarly, when comparing Constellation on Azure with AKS using CVMs, Constellation achieved approximately 10% less TCP and 40% less UDP bandwidth. + +### Storage I/O + +Azure and GCP offer persistent storage for their Kubernetes services AKS and GKE via the Container Storage Interface (CSI). CSI storage in Kubernetes is available via `PersistentVolumes` (PV) and consumed via `PersistentVolumeClaims` (PVC). +Upon requesting persistent storage through a PVC, GKE and AKS will provision a PV as defined by a default [storage class](https://kubernetes.io/docs/concepts/storage/storage-classes/). +Constellation provides persistent storage on Azure and GCP [that's encrypted on the CSI layer](../../architecture/encrypted-storage.md). +Similarly, upon a PVC request, Constellation will provision a PV via a default storage class. + +For Constellation on Azure and AKS, the benchmark ran with Azure Disk storage [Standard SSD](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#standard-ssds) of 400 GiB size. +The [DC4as machine type](https://learn.microsoft.com/en-us/azure/virtual-machines/dasv5-dadsv5-series#dasv5-series) with four cores provides the following maximum performance: + +- 6400 (20000 burst) IOPS +- 144 MB/s (600 MB/s burst) throughput + +However, the performance is bound by the capabilities of the [512 GiB Standard SSD size](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#standard-ssds) (the size class of 400 GiB volumes): + +- 500 (600 burst) IOPS +- 60 MB/s (150 MB/s burst) throughput + +For Constellation on GCP and GKE, the benchmark ran with Compute Engine Persistent Disk Storage [pd-balanced](https://cloud.google.com/compute/docs/disks) of 400 GiB size. +The N2D machine type with four cores and pd-balanced provides the following [maximum performance](https://cloud.google.com/compute/docs/disks/performance#n2d_vms): + +- 3,000 read IOPS +- 15,000 write IOPS +- 240 MB/s read throughput +- 240 MB/s write throughput + +However, the performance is bound by the capabilities of a [`Zonal balanced PD`](https://cloud.google.com/compute/docs/disks/performance#zonal-persistent-disks) with 400 GiB size: + +- 2400 read IOPS +- 2400 write IOPS +- 112 MB/s read throughput +- 112 MB/s write throughput + +The [`fio`](https://fio.readthedocs.io/en/latest/fio_doc.html) benchmark consists of several tests. +The benchmark used [`Kubestr`](https://github.com/kastenhq/kubestr) to run `fio` in Kubernetes. +The default test performs randomized access patterns that accurately depict worst-case I/O scenarios for most applications. + +The following `fio` settings were used: + +- No Cloud caching +- No OS caching +- Single CPU +- 60 seconds runtime +- 10 seconds ramp-up time +- 10 GiB file +- IOPS: 4 KB blocks and 128 iodepth +- Bandwidth: 1024 KB blocks and 128 iodepth + +For more details, see the [`fio` test configuration](https://github.com/edgelesssys/constellation/blob/main/.github/actions/e2e_benchmark/fio.ini). + +The results for IOPS on Azure are as follows: + +![I/O IOPS Azure benchmark graph](../../_media/benchmark_fio_azure_iops.png) + +The results for IOPS on GCP are as follows: + +![I/O IOPS GCP benchmark graph](../../_media/benchmark_fio_gcp_iops.png) + +The results for bandwidth on Azure are as follows: + +![I/O bandwidth Azure benchmark graph](../../_media/benchmark_fio_azure_bw.png) + +The results for bandwidth on GCP are as follows: + +![I/O bandwidth GCP benchmark graph](../../_media/benchmark_fio_gcp_bw.png) + +On GCP, the results exceed the maximum performance guarantees of the chosen disk type. There are two possible explanations for this. The first is that there may be cloud caching in place that isn't configurable. Alternatively, the underlying provisioned disk size may be larger than what was requested, resulting in higher performance boundaries. + +When comparing Constellation on GCP with GKE, Constellation has similar bandwidth but about 10% less IOPS performance. On Azure, Constellation has similar IOPS performance compared to AKS, where both likely hit the maximum storage performance. However, Constellation has approximately 15% less read and write bandwidth. + +## Conclusion + +Despite the added [security benefits](../security-benefits.md) that Constellation provides, it only incurs a slight performance overhead when compared to managed Kubernetes offerings such as AKS and GKE. In most compute benchmarks, Constellation is on par with it's alternatives. +While it may be slightly slower in certain I/O scenarios due to network and storage encryption, there is ongoing work to reduce this overhead to single digits. + +For instance, storage encryption only adds between 10% to 15% overhead in terms of bandwidth and IOPS. +Meanwhile, the biggest performance impact that Constellation currently faces is network encryption, which can incur up to 58% overhead on a 10 Gbps network. +However, the Cilium team has conducted [benchmarks with Cilium using WireGuard encryption](https://docs.cilium.io/en/latest/operations/performance/benchmark/#encryption-wireguard-ipsec) on a 100 Gbps network that yielded over 15 Gbps. +We're confident that Constellation will provide a similar level of performance with an upcoming release. + +Overall, Constellation strikes a great balance between security and performance, and we're continuously working to improve its performance capabilities while maintaining its high level of security. diff --git a/docs/versioned_docs/version-2.17/overview/performance/performance.md b/docs/versioned_docs/version-2.17/overview/performance/performance.md new file mode 100644 index 000000000..59bf86602 --- /dev/null +++ b/docs/versioned_docs/version-2.17/overview/performance/performance.md @@ -0,0 +1,17 @@ +# Performance analysis of Constellation + +This section provides a comprehensive examination of the performance characteristics of Constellation. + +## Runtime encryption + +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. + +## I/O performance benchmarks + +We evaluated the [I/O performance](io.md) of Constellation, utilizing a collection of synthetic benchmarks targeting networking and storage. +We further compared this performance to native managed Kubernetes offerings from various cloud providers, to better understand how Constellation stands in relation to standard practices. + +## Application benchmarking + +To gauge Constellation's applicability to well-known applications, we performed a [benchmark of HashiCorp Vault](application.md) running on Constellation. +The results were then compared to deployments on the managed Kubernetes offerings from different cloud providers, providing a tangible perspective on Constellation's performance in actual deployment scenarios. diff --git a/docs/versioned_docs/version-2.17/overview/product.md b/docs/versioned_docs/version-2.17/overview/product.md new file mode 100644 index 000000000..4b5d90706 --- /dev/null +++ b/docs/versioned_docs/version-2.17/overview/product.md @@ -0,0 +1,12 @@ +# Product features + +Constellation is a Kubernetes engine that aims to provide the best possible data security in combination with enterprise-grade scalability and reliability features---and a smooth user experience. + +From a security perspective, Constellation implements the [Confidential Kubernetes](confidential-kubernetes.md) concept and corresponding security features, which shield your entire cluster from the underlying infrastructure. + +From an operational perspective, Constellation provides the following key features: + +* **Native support for different clouds**: Constellation works on Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), and STACKIT. Support for OpenStack-based environments is coming with a future release. Constellation securely interfaces with the cloud infrastructure to provide [cluster autoscaling](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler), [dynamic persistent volumes](https://kubernetes.io/docs/concepts/storage/dynamic-provisioning/), and [service load balancing](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer). +* **High availability**: Constellation uses a [multi-master architecture](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/high-availability/) with a [stacked etcd topology](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/ha-topology/#stacked-etcd-topology) to ensure high availability. +* **Integrated Day-2 operations**: Constellation lets you securely [upgrade](../workflows/upgrade.md) your cluster to a new release. It also lets you securely [recover](../workflows/recovery.md) a failed cluster. Both with a single command. +* **Support for Terraform**: Constellation includes a [Terraform provider](../workflows/terraform-provider.md) that lets you manage the full lifecycle of your cluster via Terraform. diff --git a/docs/versioned_docs/version-2.17/overview/security-benefits.md b/docs/versioned_docs/version-2.17/overview/security-benefits.md new file mode 100644 index 000000000..51a8b64f5 --- /dev/null +++ b/docs/versioned_docs/version-2.17/overview/security-benefits.md @@ -0,0 +1,22 @@ +# Security benefits and threat model + +Constellation implements the [Confidential Kubernetes](confidential-kubernetes.md) concept and shields entire Kubernetes deployments from the infrastructure. More concretely, Constellation decreases the size of the trusted computing base (TCB) of a Kubernetes deployment. The TCB is the totality of elements in a computing environment that must be trusted not to be compromised. A smaller TCB results in a smaller attack surface. The following diagram shows how Constellation removes the *cloud & datacenter infrastructure* and the *physical hosts*, including the hypervisor, the host OS, and other components, from the TCB (red). Inside the confidential context (green), Kubernetes remains part of the TCB, but its integrity is attested and can be [verified](../workflows/verify-cluster.md). + +![TCB comparison](../_media/tcb.svg) + +Given this background, the following describes the concrete threat classes that Constellation addresses. + +## Insider access + +Employees and third-party contractors of cloud service providers (CSPs) have access to different layers of the cloud infrastructure. +This opens up a large attack surface where workloads and data can be read, copied, or manipulated. With Constellation, Kubernetes deployments are shielded from the infrastructure and thus such accesses are prevented. + +## Infrastructure-based attacks + +Malicious cloud users ("hackers") may break out of their tenancy and access other tenants' data. Advanced attackers may even be able to establish a permanent foothold within the infrastructure and access data over a longer period. Analogously to the *insider access* scenario, Constellation also prevents access to a deployment's data in this scenario. + +## Supply chain attacks + +Supply chain security is receiving lots of attention recently due to an [increasing number of recorded attacks](https://www.enisa.europa.eu/news/enisa-news/understanding-the-increase-in-supply-chain-security-attacks). For instance, a malicious actor could attempt to tamper Constellation node images (including Kubernetes and other software) before they're loaded in the confidential VMs of a cluster. Constellation uses [remote attestation](../architecture/attestation.md) in conjunction with public [transparency logs](../workflows/verify-cli.md) to prevent this. + +In the future, Constellation will extend this feature to customer workloads. This will enable cluster owners to create auditable policies that precisely define which containers can run in a given deployment. diff --git a/docs/versioned_docs/version-2.17/reference/cli.md b/docs/versioned_docs/version-2.17/reference/cli.md new file mode 100644 index 000000000..a728474e7 --- /dev/null +++ b/docs/versioned_docs/version-2.17/reference/cli.md @@ -0,0 +1,843 @@ +# CLI reference + + + +Use the Constellation CLI to create and manage your clusters. + +Usage: + +``` +constellation [command] +``` +Commands: + +* [config](#constellation-config): Work with the Constellation configuration file + * [generate](#constellation-config-generate): Generate a default configuration and state file + * [fetch-measurements](#constellation-config-fetch-measurements): Fetch measurements for configured cloud provider and image + * [instance-types](#constellation-config-instance-types): Print the supported instance types for all cloud providers + * [kubernetes-versions](#constellation-config-kubernetes-versions): Print the Kubernetes versions supported by this CLI + * [migrate](#constellation-config-migrate): Migrate a configuration file to a new version +* [create](#constellation-create): Create instances on a cloud platform for your Constellation cluster +* [apply](#constellation-apply): Apply a configuration to a Constellation cluster +* [mini](#constellation-mini): Manage MiniConstellation clusters + * [up](#constellation-mini-up): Create and initialize a new MiniConstellation cluster + * [down](#constellation-mini-down): Destroy a MiniConstellation cluster +* [status](#constellation-status): Show status of a Constellation cluster +* [verify](#constellation-verify): Verify the confidential properties of a Constellation cluster +* [upgrade](#constellation-upgrade): Find and apply upgrades to your Constellation cluster + * [check](#constellation-upgrade-check): Check for possible upgrades + * [apply](#constellation-upgrade-apply): Apply an upgrade to a Constellation cluster +* [recover](#constellation-recover): Recover a completely stopped Constellation cluster +* [terminate](#constellation-terminate): Terminate a Constellation cluster +* [iam](#constellation-iam): Work with the IAM configuration on your cloud provider + * [create](#constellation-iam-create): Create IAM configuration on a cloud platform for your Constellation cluster + * [aws](#constellation-iam-create-aws): Create IAM configuration on AWS for your Constellation cluster + * [azure](#constellation-iam-create-azure): Create IAM configuration on Microsoft Azure for your Constellation cluster + * [gcp](#constellation-iam-create-gcp): Create IAM configuration on GCP for your Constellation cluster + * [destroy](#constellation-iam-destroy): Destroy an IAM configuration and delete local Terraform files + * [upgrade](#constellation-iam-upgrade): Find and apply upgrades to your IAM profile + * [apply](#constellation-iam-upgrade-apply): Apply an upgrade to an IAM profile +* [version](#constellation-version): Display version of this CLI +* [init](#constellation-init): Initialize the Constellation cluster + +## constellation config + +Work with the Constellation configuration file + +### Synopsis + +Work with the Constellation configuration file. + +### Options + +``` + -h, --help help for config +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config generate + +Generate a default configuration and state file + +### Synopsis + +Generate a default configuration and state file for your selected cloud provider. + +``` +constellation config generate {aws|azure|gcp|openstack|qemu|stackit} [flags] +``` + +### Options + +``` + -a, --attestation string attestation variant to use {aws-sev-snp|aws-nitro-tpm|azure-sev-snp|azure-tdx|azure-trustedlaunch|gcp-sev-es|gcp-sev-snp|qemu-vtpm}. If not specified, the default for the cloud provider is used + -h, --help help for generate + -k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR (default "v1.29") + -t, --tags strings additional tags for created resources given a list of key=value +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config fetch-measurements + +Fetch measurements for configured cloud provider and image + +### Synopsis + +Fetch measurements for configured cloud provider and image. + +A config needs to be generated first. + +``` +constellation config fetch-measurements [flags] +``` + +### Options + +``` + -h, --help help for fetch-measurements + -s, --signature-url string alternative URL to fetch measurements' signature from + -u, --url string alternative URL to fetch measurements from +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config instance-types + +Print the supported instance types for all cloud providers + +### Synopsis + +Print the supported instance types for all cloud providers. + +``` +constellation config instance-types [flags] +``` + +### Options + +``` + -h, --help help for instance-types +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config kubernetes-versions + +Print the Kubernetes versions supported by this CLI + +### Synopsis + +Print the Kubernetes versions supported by this CLI. + +``` +constellation config kubernetes-versions [flags] +``` + +### Options + +``` + -h, --help help for kubernetes-versions +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config migrate + +Migrate a configuration file to a new version + +### Synopsis + +Migrate a configuration file to a new version. + +``` +constellation config migrate [flags] +``` + +### Options + +``` + -h, --help help for migrate +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation create + +Create instances on a cloud platform for your Constellation cluster + +### Synopsis + +Create instances on a cloud platform for your Constellation cluster. + +``` +constellation create [flags] +``` + +### Options + +``` + -h, --help help for create + -y, --yes create the cluster without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation apply + +Apply a configuration to a Constellation cluster + +### Synopsis + +Apply a configuration to a Constellation cluster to initialize or upgrade the cluster. + +``` +constellation apply [flags] +``` + +### Options + +``` + --conformance enable conformance mode + -h, --help help for apply + --merge-kubeconfig merge Constellation kubeconfig file with default kubeconfig file in $HOME/.kube/config + --skip-helm-wait install helm charts without waiting for deployments to be ready + --skip-phases strings comma-separated list of upgrade phases to skip + one or multiple of { infrastructure | init | attestationconfig | certsans | helm | image | k8s } + -y, --yes run command without further confirmation + WARNING: the command might delete or update existing resources without additional checks. Please read the docs. + +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation mini + +Manage MiniConstellation clusters + +### Synopsis + +Manage MiniConstellation clusters. + +### Options + +``` + -h, --help help for mini +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation mini up + +Create and initialize a new MiniConstellation cluster + +### Synopsis + +Create and initialize a new MiniConstellation cluster. + +A mini cluster consists of a single control-plane and worker node, hosted using QEMU/KVM. + +``` +constellation mini up [flags] +``` + +### Options + +``` + -h, --help help for up + --merge-kubeconfig merge Constellation kubeconfig file with default kubeconfig file in $HOME/.kube/config (default true) +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation mini down + +Destroy a MiniConstellation cluster + +### Synopsis + +Destroy a MiniConstellation cluster. + +``` +constellation mini down [flags] +``` + +### Options + +``` + -h, --help help for down + -y, --yes terminate the cluster without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation status + +Show status of a Constellation cluster + +### Synopsis + +Show the status of a constellation cluster. + +Shows microservice, image, and Kubernetes versions installed in the cluster. Also shows status of current version upgrades. + +``` +constellation status [flags] +``` + +### Options + +``` + -h, --help help for status +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation verify + +Verify the confidential properties of a Constellation cluster + +### Synopsis + +Verify the confidential properties of a Constellation cluster. +If arguments aren't specified, values are read from `constellation-state.yaml`. + +``` +constellation verify [flags] +``` + +### Options + +``` + --cluster-id string expected cluster identifier + -h, --help help for verify + -e, --node-endpoint string endpoint of the node to verify, passed as HOST[:PORT] + -o, --output string print the attestation document in the output format {json|raw} +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation upgrade + +Find and apply upgrades to your Constellation cluster + +### Synopsis + +Find and apply upgrades to your Constellation cluster. + +### Options + +``` + -h, --help help for upgrade +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation upgrade check + +Check for possible upgrades + +### Synopsis + +Check which upgrades can be applied to your Constellation Cluster. + +``` +constellation upgrade check [flags] +``` + +### Options + +``` + -h, --help help for check + --ref string the reference to use for querying new versions (default "-") + --stream string the stream to use for querying new versions (default "stable") + -u, --update-config update the specified config file with the suggested versions +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation upgrade apply + +Apply an upgrade to a Constellation cluster + +### Synopsis + +Apply an upgrade to a Constellation cluster by applying the chosen configuration. + +``` +constellation upgrade apply [flags] +``` + +### Options + +``` + --conformance enable conformance mode + -h, --help help for apply + --skip-helm-wait install helm charts without waiting for deployments to be ready + --skip-phases strings comma-separated list of upgrade phases to skip + one or multiple of { infrastructure | helm | image | k8s } + -y, --yes run upgrades without further confirmation + WARNING: might delete your resources in case you are using cert-manager in your cluster. Please read the docs. + WARNING: might unintentionally overwrite measurements in the running cluster. +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation recover + +Recover a completely stopped Constellation cluster + +### Synopsis + +Recover a Constellation cluster by sending a recovery key to an instance in the boot stage. + +This is only required if instances restart without other instances available for bootstrapping. + +``` +constellation recover [flags] +``` + +### Options + +``` + -e, --endpoint string endpoint of the instance, passed as HOST[:PORT] + -h, --help help for recover +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation terminate + +Terminate a Constellation cluster + +### Synopsis + +Terminate a Constellation cluster. + +The cluster can't be started again, and all persistent storage will be lost. + +``` +constellation terminate [flags] +``` + +### Options + +``` + -h, --help help for terminate + -y, --yes terminate the cluster without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam + +Work with the IAM configuration on your cloud provider + +### Synopsis + +Work with the IAM configuration on your cloud provider. + +### Options + +``` + -h, --help help for iam +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam create + +Create IAM configuration on a cloud platform for your Constellation cluster + +### Synopsis + +Create IAM configuration on a cloud platform for your Constellation cluster. + +### Options + +``` + -h, --help help for create + --update-config update the config file with the specific IAM information + -y, --yes create the IAM configuration without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam create aws + +Create IAM configuration on AWS for your Constellation cluster + +### Synopsis + +Create IAM configuration on AWS for your Constellation cluster. + +``` +constellation iam create aws [flags] +``` + +### Options + +``` + -h, --help help for aws + --prefix string name prefix for all resources (required) + --zone string AWS availability zone the resources will be created in, e.g., us-east-2a (required) + See the Constellation docs for a list of currently supported regions. +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + --update-config update the config file with the specific IAM information + -C, --workspace string path to the Constellation workspace + -y, --yes create the IAM configuration without further confirmation +``` + +## constellation iam create azure + +Create IAM configuration on Microsoft Azure for your Constellation cluster + +### Synopsis + +Create IAM configuration on Microsoft Azure for your Constellation cluster. + +``` +constellation iam create azure [flags] +``` + +### Options + +``` + -h, --help help for azure + --region string region the resources will be created in, e.g., westus (required) + --resourceGroup string name prefix of the two resource groups your cluster / IAM resources will be created in (required) + --servicePrincipal string name of the service principal that will be created (required) +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + --update-config update the config file with the specific IAM information + -C, --workspace string path to the Constellation workspace + -y, --yes create the IAM configuration without further confirmation +``` + +## constellation iam create gcp + +Create IAM configuration on GCP for your Constellation cluster + +### Synopsis + +Create IAM configuration on GCP for your Constellation cluster. + +``` +constellation iam create gcp [flags] +``` + +### Options + +``` + -h, --help help for gcp + --projectID string ID of the GCP project the configuration will be created in (required) + Find it on the welcome screen of your project: https://console.cloud.google.com/welcome + --serviceAccountID string ID for the service account that will be created (required) + Must be 6 to 30 lowercase letters, digits, or hyphens. + --zone string GCP zone the cluster will be deployed in (required) + Find a list of available zones here: https://cloud.google.com/compute/docs/regions-zones#available +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + --update-config update the config file with the specific IAM information + -C, --workspace string path to the Constellation workspace + -y, --yes create the IAM configuration without further confirmation +``` + +## constellation iam destroy + +Destroy an IAM configuration and delete local Terraform files + +### Synopsis + +Destroy an IAM configuration and delete local Terraform files. + +``` +constellation iam destroy [flags] +``` + +### Options + +``` + -h, --help help for destroy + -y, --yes destroy the IAM configuration without asking for confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam upgrade + +Find and apply upgrades to your IAM profile + +### Synopsis + +Find and apply upgrades to your IAM profile. + +### Options + +``` + -h, --help help for upgrade +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam upgrade apply + +Apply an upgrade to an IAM profile + +### Synopsis + +Apply an upgrade to an IAM profile. + +``` +constellation iam upgrade apply [flags] +``` + +### Options + +``` + -h, --help help for apply + -y, --yes run upgrades without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation version + +Display version of this CLI + +### Synopsis + +Display version of this CLI. + +``` +constellation version [flags] +``` + +### Options + +``` + -h, --help help for version +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation init + +Initialize the Constellation cluster + +### Synopsis + +Initialize the Constellation cluster. + +Start your confidential Kubernetes. + +``` +constellation init [flags] +``` + +### Options + +``` + --conformance enable conformance mode + -h, --help help for init + --merge-kubeconfig merge Constellation kubeconfig file with default kubeconfig file in $HOME/.kube/config + --skip-helm-wait install helm charts without waiting for deployments to be ready +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + diff --git a/docs/versioned_docs/version-2.17/reference/migration.md b/docs/versioned_docs/version-2.17/reference/migration.md new file mode 100644 index 000000000..36680eef6 --- /dev/null +++ b/docs/versioned_docs/version-2.17/reference/migration.md @@ -0,0 +1,85 @@ +# Migrations + +This document describes breaking changes and migrations between Constellation releases. +Use [`constellation config migrate`](./cli.md#constellation-config-migrate) to automatically update an old config file to a new format. + +## Migrating from Azure's service principal authentication to managed identity authentication + +- The `provider.azure.appClientID` and `provider.azure.appClientSecret` fields are no longer supported and should be removed. +- To keep using an existing UAMI, add the `Owner` permission with the scope of your `resourceGroup`. +- Otherwise, simply [create new Constellation IAM credentials](../workflows/config.md#creating-an-iam-configuration) and use the created UAMI. +- To migrate the authentication for an existing cluster on Azure to an UAMI with the necessary permissions: + 1. Remove the `aadClientId` and `aadClientSecret` from the azureconfig secret. + 2. Set `useManagedIdentityExtension` to `true` and use the `userAssignedIdentity` from the Constellation config for the value of `userAssignedIdentityID`. + 3. Restart the CSI driver, cloud controller manager, cluster autoscaler, and Constellation operator pods. + + +## Migrating from CLI versions before 2.10 + +- AWS cluster upgrades require additional IAM permissions for the newly introduced `aws-load-balancer-controller`. Please upgrade your IAM roles using `iam upgrade apply`. This will show necessary changes and apply them, if desired. +- The global `nodeGroups` field was added. +- The fields `instanceType`, `stateDiskSizeGB`, and `stateDiskType` for each cloud provider are now part of the configuration of individual node groups. +- The `constellation create` command no longer uses the flags `--control-plane-count` and `--worker-count`. Instead, the initial node count is configured per node group in the `nodeGroups` field. + +## Migrating from CLI versions before 2.9 + +- The `provider.azure.appClientID` and `provider.azure.clientSecretValue` fields were removed to enforce migration to managed identity authentication + +## Migrating from CLI versions before 2.8 + +- The `measurements` field for each cloud service provider was replaced with a global `attestation` field. +- The `confidentialVM`, `idKeyDigest`, and `enforceIdKeyDigest` fields for the Azure cloud service provider were removed in favor of using the global `attestation` field. +- The optional global field `attestationVariant` was replaced by the now required `attestation` field. + +## Migrating from CLI versions before 2.3 + +- The `sshUsers` field was deprecated in v2.2 and has been removed from the configuration in v2.3. + As an alternative for SSH, check the workflow section [Connect to nodes](../workflows/troubleshooting.md#node-shell-access). +- The `image` field for each cloud service provider has been replaced with a global `image` field. Use the following mapping to migrate your configuration: +
+ Show all + + | CSP | old image | new image | + | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | + | AWS | `ami-06b8cbf4837a0a57c` | `v2.2.2` | + | AWS | `ami-02e96dc04a9e438cd` | `v2.2.2` | + | AWS | `ami-028ead928a9034b2f` | `v2.2.2` | + | AWS | `ami-032ac10dd8d8266e3` | `v2.2.1` | + | AWS | `ami-032e0d57cc4395088` | `v2.2.1` | + | AWS | `ami-053c3e49e19b96bdd` | `v2.2.1` | + | AWS | `ami-0e27ebcefc38f648b` | `v2.2.0` | + | AWS | `ami-098cd37f66523b7c3` | `v2.2.0` | + | AWS | `ami-04a87d302e2509aad` | `v2.2.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.2.2` | `v2.2.2` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.2.2` | `v2.2.2` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.2.1` | `v2.2.1` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.2.1` | `v2.2.1` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.2.0` | `v2.2.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.2.0` | `v2.2.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.1.0` | `v2.1.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.1.0` | `v2.1.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.0.0` | `v2.0.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.0.0` | `v2.0.0` | + | GCP | `projects/constellation-images/global/images/constellation-v2-2-2` | `v2.2.2` | + | GCP | `projects/constellation-images/global/images/constellation-v2-2-1` | `v2.2.1` | + | GCP | `projects/constellation-images/global/images/constellation-v2-2-0` | `v2.2.0` | + | GCP | `projects/constellation-images/global/images/constellation-v2-1-0` | `v2.1.0` | + | GCP | `projects/constellation-images/global/images/constellation-v2-0-0` | `v2.0.0` | +
+- The `enforcedMeasurements` field has been removed and merged with the `measurements` field. + - To migrate your config containing a new image (`v2.3` or greater), remove the old `measurements` and `enforcedMeasurements` entries from your config and run `constellation fetch-measurements` + - To migrate your config containing an image older than `v2.3`, remove the `enforcedMeasurements` entry and replace the entries in `measurements` as shown in the example below: + + ```diff + measurements: + - 0: DzXCFGCNk8em5ornNZtKi+Wg6Z7qkQfs5CfE3qTkOc8= + + 0: + + expected: DzXCFGCNk8em5ornNZtKi+Wg6Z7qkQfs5CfE3qTkOc8= + + warnOnly: true + - 8: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + + 8: + + expected: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + + warnOnly: false + -enforcedMeasurements: + - - 8 + ``` diff --git a/docs/versioned_docs/version-2.17/reference/slsa.md b/docs/versioned_docs/version-2.17/reference/slsa.md new file mode 100644 index 000000000..21f4e713c --- /dev/null +++ b/docs/versioned_docs/version-2.17/reference/slsa.md @@ -0,0 +1,73 @@ +# Supply chain levels for software artifacts (SLSA) adoption + +[Supply chain Levels for Software Artifacts, or SLSA (salsa)](https://slsa.dev/) is a framework for improving and grading a project's build system and engineering processes. SLSA focuses on security improvements for source code storage as well as build system definition, execution, and observation. SLSA is structured in [four levels](https://slsa.dev/spec/v0.1/levels). This page describes the adoption of SLSA for Constellation. + +:::info +SLSA is still in alpha status. The presented levels and their requirements might change in the future. We will adopt any changes into our engineering processes, as they get defined. +::: + +## Level 1 - Adopted + +**[Build - Scripted](https://slsa.dev/spec/v0.1/requirements#scripted-build)** + +All build steps are automated via [Bazel](https://github.com/edgelesssys/constellation/tree/main/bazel/ci) and [GitHub Actions](https://github.com/edgelesssys/constellation/tree/main/.github). + +**[Provenance - Available](https://slsa.dev/spec/v0.1/requirements#available)** + +Provenance for the CLI is generated using the [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator). + +## Level 2 - Adopted + +**[Source - Version Controlled](https://slsa.dev/spec/v0.1/requirements#version-controlled)** + +Constellation is hosted on GitHub using git. + +**[Build - Build Service](https://slsa.dev/spec/v0.1/requirements#build-service)** + +All builds are carried out by [GitHub Actions](https://github.com/edgelesssys/constellation/tree/main/.github). + +**[Provenance - Authenticated](https://slsa.dev/spec/v0.1/requirements#authenticated)** + +Provenance for the CLI is signed using the [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator). Learn [how to verify the CLI](../workflows/verify-cli.md) using the signed provenance, before using it for the first time. + +**[Provenance - Service Generated](https://slsa.dev/spec/v0.1/requirements#service-generated)** + +Provenance for the CLI is generated using the [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator) in GitHub Actions. + +## Level 3 - Adopted + +**[Source - Verified History](https://slsa.dev/spec/v0.1/requirements#verified-history)** + +The [Edgeless Systems](https://github.com/edgelesssys) GitHub organization [requires two-factor authentication](https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization) for all members. + +**[Source - Retained Indefinitely](https://slsa.dev/spec/v0.1/requirements#retained-indefinitely)** + +Since we use GitHub to host the repository, an external person can't modify or delete the history. Before a pull request can be merged, an explicit approval from an [Edgeless Systems](https://github.com/edgelesssys) team member is required. + +The same holds true for changes proposed by team members. Each change to `main` needs to be proposed via a pull request and requires at least one approval. + +The [Edgeless Systems](https://github.com/edgelesssys) GitHub organization admins control these settings and are able to make changes to the repository's history should legal requirements necessitate it. These changes require two-party approval following the obliterate policy. + +**[Build - Build as Code](https://slsa.dev/spec/v0.1/requirements#build-as-code)** + +All build files for Constellation are stored in [the same repository](https://github.com/edgelesssys/constellation/tree/main/.github). + +**[Build - Ephemeral Environment](https://slsa.dev/spec/v0.1/requirements#ephemeral-environment)** + +All GitHub Action workflows are executed on [GitHub-hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners). These runners are only available during workflow. + +We currently don't use [self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners). + +**[Build - Isolated](https://slsa.dev/spec/v0.1/requirements#isolated)** + +As outlined in the previous section, we use GitHub-hosted runners, which provide a new, isolated and ephemeral environment for each build. + +Additionally, the [SLSA GitHub generator](https://github.com/slsa-framework/slsa-github-generator#generation-of-provenance) itself is run in an isolated workflow with the artifact hash as defined inputs. + +**[Provenance - Non-falsifiable](https://slsa.dev/spec/v0.1/requirements#non-falsifiable)** + +As outlined by [SLSA GitHub generator](https://github.com/slsa-framework/slsa-github-generator) it already fulfills the non-falsifiable requirements for SLSA Level 3. The generated provenance is signed using [sigstore](https://sigstore.dev/) with an OIDC based proof of identity. + +## Level 4 - In Progress + +We strive to adopt certain aspect of SLSA Level 4 that support our engineering process. At the same time, SLSA is still in alpha status and the biggest changes to SLSA are expected to be around Level 4. diff --git a/docs/versioned_docs/version-2.17/reference/terraform.md b/docs/versioned_docs/version-2.17/reference/terraform.md new file mode 100644 index 000000000..9825a8bb8 --- /dev/null +++ b/docs/versioned_docs/version-2.17/reference/terraform.md @@ -0,0 +1,37 @@ +# Terraform usage + +[Terraform](https://www.terraform.io/) is an Infrastructure as Code (IaC) framework to manage cloud resources. This page explains how Constellation uses it internally and how advanced users may manually use it to have more control over the resource creation. + +:::info +Information on this page is intended for users who are familiar with Terraform. +It's not required for common usage of Constellation. +See the [Terraform documentation](https://developer.hashicorp.com/terraform/docs) if you want to learn more about it. +::: + +## Terraform state files + +Constellation keeps Terraform state files in subdirectories of the workspace together with the corresponding Terraform configuration files and metadata. +The subdirectories are created on the first Constellation CLI action that uses Terraform internally. + +Currently, these subdirectories are: + +* `constellation-terraform` - Terraform state files for the resources of the Constellation cluster +* `constellation-iam-terraform` - Terraform state files for IAM configuration + +As with all commands, commands that work with these files (e.g., `apply`, `terminate`, `iam`) have to be executed from the root of the cluster's [workspace directory](../architecture/orchestration.md#workspaces). You usually don't need and shouldn't manipulate or delete the subdirectories manually. + +## Interacting with Terraform manually + +Manual interaction with Terraform state created by Constellation (i.e., via the Terraform CLI) should only be performed by experienced users. It may lead to unrecoverable loss of cloud resources. For the majority of users and use cases, the interaction done by the [Constellation CLI](cli.md) is sufficient. + +## Terraform debugging + +To debug Terraform issues, the Constellation CLI offers the `tf-log` flag. You can set it to any of [Terraform's log levels](https://developer.hashicorp.com/terraform/internals/debugging): +* `JSON` (JSON-formatted logs at `TRACE` level) +* `TRACE` +* `DEBUG` +* `INFO` +* `WARN` +* `ERROR` + +The log output is written to the `terraform.log` file in the workspace directory. The output is appended to the file on each run. diff --git a/docs/versioned_docs/version-2.17/workflows/cert-manager.md b/docs/versioned_docs/version-2.17/workflows/cert-manager.md new file mode 100644 index 000000000..1d847e8bf --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/cert-manager.md @@ -0,0 +1,13 @@ +# Install cert-manager + +:::caution +If you want to use cert-manager with Constellation, pay attention to the following to avoid potential pitfalls. +::: + +Constellation ships with cert-manager preinstalled. +The default installation is part of the `kube-system` namespace, as all other Constellation-managed microservices. +You are free to install more instances of cert-manager into other namespaces. +However, be aware that any new installation needs to use the same version as the one installed with Constellation or rely on the same CRD versions. +Also remember to set the `installCRDs` value to `false` when installing new cert-manager instances. +It will create problems if you have two installations of cert-manager depending on different versions of the installed CRDs. +CRDs are cluster-wide resources and cert-manager depends on specific versions of those CRDs for each release. diff --git a/docs/versioned_docs/version-2.17/workflows/config.md b/docs/versioned_docs/version-2.17/workflows/config.md new file mode 100644 index 000000000..120bf8ed7 --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/config.md @@ -0,0 +1,353 @@ +# Configure your cluster + +:::info +This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. +::: + + + +--- + +Before you can create your cluster, you need to configure the identity and access management (IAM) for your cloud service provider (CSP) and choose machine types for the nodes. + +## Creating the configuration file + +You can generate a configuration file for your CSP by using the following CLI command: + + + + +```bash +constellation config generate aws +``` + + + + +```bash +constellation config generate azure +``` + + + + +```bash +constellation config generate gcp +``` + + + + +```bash +constellation config generate stackit +``` + + + + +This creates the file `constellation-conf.yaml` in the current directory. + +## Choosing a VM type + +Constellation supports the following VM types: + + + +By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. +Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. +If you are using the default attestation variant `awsSEVSNP`, you can use the instance types described in [AWS's AMD SEV-SNP docs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/snp-requirements.html). +Please mind the region restrictions mentioned in the [Getting started](../getting-started/first-steps.md#create-a-cluster) section. + +If you are using the attestation variant `awsNitroTPM`, you can choose any of the [nitroTPM-enabled instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-prerequisites.html). + +The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. + + + + +By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. + +You can also run `constellation config instance-types` to get the list of all supported options. + + + + +By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. + + + + +By default, Constellation uses `m1a.4cd` VMs (4 vCPUs, 30 GB RAM) to create your cluster. +Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. + +The following instance types are known to be supported: + +| name | vCPUs | GB RAM | +|----------|-------|--------| +| m1a.4cd | 4 | 30 | +| m1a.8cd | 8 | 60 | +| m1a.16cd | 16 | 120 | +| m1a.30cd | 30 | 230 | + +You can choose any of the SEV-enabled instance types. You can find a list of all supported instance types in the [STACKIT documentation](https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html). + +The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. + + + + +Fill the desired VM type into the `instanceType` fields in the `constellation-conf.yml` file. + +## Creating additional node groups + +By default, Constellation creates the node groups `control_plane_default` and `worker_default` for control-plane nodes and workers, respectively. +If you require additional control-plane or worker groups with different instance types, zone placements, or disk sizes, you can add additional node groups to the `constellation-conf.yml` file. +Each node group can be scaled individually. + +Consider the following example for AWS: + +```yaml +nodeGroups: + control_plane_default: + role: control-plane + instanceType: c6a.xlarge + stateDiskSizeGB: 30 + stateDiskType: gp3 + zone: eu-west-1c + initialCount: 3 + worker_default: + role: worker + instanceType: c6a.xlarge + stateDiskSizeGB: 30 + stateDiskType: gp3 + zone: eu-west-1c + initialCount: 2 + high_cpu: + role: worker + instanceType: c6a.24xlarge + stateDiskSizeGB: 128 + stateDiskType: gp3 + zone: eu-west-1c + initialCount: 1 +``` + +This configuration creates an additional node group `high_cpu` with a larger instance type and disk. + +You can use the field `zone` to specify what availability zone nodes of the group are placed in. +On Azure, this field is empty by default and nodes are automatically spread across availability zones. +STACKIT currently offers SEV-enabled CPUs in the `eu01-1`, `eu01-2`, and `eu01-3` zones. +Consult the documentation of your cloud provider for more information: + +* [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) +* [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) +* [GCP](https://cloud.google.com/compute/docs/regions-zones) +* [STACKIT](https://docs.stackit.cloud/stackit/en/regions-and-availability-zones-75137212.html) + +## Choosing a Kubernetes version + +To learn which Kubernetes versions can be installed with your current CLI, you can run `constellation config kubernetes-versions`. +See also Constellation's [Kubernetes support policy](../architecture/versions.md#kubernetes-support-policy). + +## Creating an IAM configuration + +You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. +If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. + + + + +You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). + +```bash +constellation iam create aws --zone=us-east-2a --prefix=constellTest +``` + +This command creates IAM configuration for the AWS zone `us-east-2a` using the prefix `constellTest` for all named resources being created. + +Constellation OS images are currently replicated to the following regions: + +* `eu-central-1` +* `eu-west-1` +* `eu-west-3` +* `us-east-2` +* `ap-south-1` + +If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+AWS+image+region:+xx-xxxx-x). + +You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). + +Paste the output into the corresponding fields of the `constellation-conf.yaml` file. + + + + +You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). + +```bash +constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest +``` + +This command creates IAM configuration on the Azure region `westus` creating a new resource group `constellTest` and a new service principal `spTest`. + +CVMs are available in several Azure regions. Constellation OS images are currently replicated to the following: + +* `germanywestcentral` +* `westus` +* `eastus` +* `northeurope` +* `westeurope` +* `southeastasia` + +If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+Azure+image+region:+xx-xxxx-x). + +You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). + +Paste the output into the corresponding fields of the `constellation-conf.yaml` file. + + + + +You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). + +```bash +constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test +``` + +This command creates IAM configuration in the GCP project `yourproject-12345` on the GCP zone `europe-west2-a` creating a new service account `constell-test`. + +Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `N2D`. + +Paste the output into the corresponding fields of the `constellation-conf.yaml` file. + + + + +STACKIT requires manual creation and configuration of service accounts. Look at the [first steps](../getting-started/first-steps.md) for more information. + + + + +
+Alternatively, you can manually create the IAM configuration on your CSP. + +The following describes the configuration fields and how you obtain the required information or create the required resources. + + + + +* **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. + + Constellation OS images are currently replicated to the following regions: + * `eu-central-1` + * `eu-west-1` + * `eu-west-3` + * `us-east-2` + * `ap-south-1` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+AWS+image+region:+xx-xxxx-x). + + You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). + +* **zone**: The name of your chosen AWS data center availability zone, e.g., `us-east-2a`. + + Learn more about [availability zones in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-availability-zones). + +* **iamProfileControlPlane**: The name of an IAM instance profile attached to all control-plane nodes. + + You can create the resource with [Terraform](https://www.terraform.io/). For that, use the [provided Terraform script](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam) to generate the necessary profile. The profile name will be provided as Terraform output value: `control_plane_instance_profile_name`. + + Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.control_plane_policy`. + +* **iamProfileWorkerNodes**: The name of an IAM instance profile attached to all worker nodes. + + You can create the resource with [Terraform](https://www.terraform.io/). For that, use the [provided Terraform script](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam) to generate the necessary profile. The profile name will be provided as Terraform output value: `worker_nodes_instance_profile_name`. + + Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. + + + + +* **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. + + You can view your subscription UUID via `az account show` and read the `id` field. For more information refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-subscription). + +* **tenant**: The UUID of your Azure tenant, e.g., `3400e5a2-8fe2-492a-886c-38cb66170f25`. + + You can view your tenant UUID via `az account show` and read the `tenant` field. For more information refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-ad-tenant). + +* **location**: The Azure datacenter location you want to deploy your cluster in, e.g., `westus`. + + CVMs are available in several Azure regions. Constellation OS images are currently replicated to the following: + + * `germanywestcentral` + * `westus` + * `eastus` + * `northeurope` + * `westeurope` + * `southeastasia` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+Azure+image+region:+xx-xxxx-x). + + You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). + +* **resourceGroup**: [Create a new resource group in Azure](https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal) for your Constellation cluster. Set this configuration field to the name of the created resource group. + +* **userAssignedIdentity**: [Create a new managed identity in Azure](https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). You should create the identity in a different resource group as all resources within the cluster resource group will be deleted on cluster termination. + + Add three role assignments to the identity: `Owner`, `Virtual Machine Contributor`, and `Application Insights Component Contributor`. The `scope` of all three should refer to the previously created cluster resource group. + + Set the configuration value to the full ID of the created identity, e.g., `/subscriptions/8b8bd01f-efd9-4113-9bd1-c82137c32da7/resourcegroups/constellation-identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/constellation-identity`. You can get it by opening the `JSON View` from the `Overview` section of the identity. + + The user-assigned identity is used by instances of the cluster to access other cloud resources. + For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). + + + + +* **project**: The ID of your GCP project, e.g., `constellation-129857`. + + You can find it on the [welcome screen of your GCP project](https://console.cloud.google.com/welcome). For more information refer to [Google's documentation](https://support.google.com/googleapi/answer/7014113). + +* **region**: The GCP region you want to deploy your cluster in, e.g., `us-west1`. + + You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available). + +* **zone**: The GCP zone you want to deploy your cluster in, e.g., `us-west1-a`. + + You can find a [list of all zones in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available). + +* **serviceAccountKeyPath**: To configure this, you need to create a GCP [service account](https://cloud.google.com/iam/docs/service-accounts) with the following permissions: + + * `Compute Instance Admin (v1) (roles/compute.instanceAdmin.v1)` + * `Compute Network Admin (roles/compute.networkAdmin)` + * `Compute Security Admin (roles/compute.securityAdmin)` + * `Compute Storage Admin (roles/compute.storageAdmin)` + * `Service Account User (roles/iam.serviceAccountUser)` + + Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. + + + + +STACKIT requires manual creation and configuration of service accounts. Look at the [first steps](../getting-started/first-steps.md) for more information. + + + +
+ +Now that you've configured your CSP, you can [create your cluster](./create.md). + +## Deleting an IAM configuration + +You can keep a created IAM configuration and reuse it for new clusters. Alternatively, you can also delete it if you don't want to use it anymore. + +Delete the IAM configuration by executing the following command in the same directory where you executed `constellation iam create` (the directory that contains [`constellation-iam-terraform`](../reference/terraform.md) as a subdirectory): + +```bash +constellation iam destroy +``` + +:::caution +For Azure, deleting the IAM configuration by executing `constellation iam destroy` will delete the whole resource group created by `constellation iam create`. +This also includes any additional resources in the resource group that weren't created by Constellation. +::: diff --git a/docs/versioned_docs/version-2.17/workflows/create.md b/docs/versioned_docs/version-2.17/workflows/create.md new file mode 100644 index 000000000..6074ebb16 --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/create.md @@ -0,0 +1,93 @@ +# Create your cluster + +:::info +This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. +::: + + + +--- + +Creating your cluster happens through multiple phases. +The most significant ones are: + +1. Creating the necessary resources in your cloud environment +2. Bootstrapping the Constellation cluster and setting up a connection +3. Installing the necessary Kubernetes components + +`constellation apply` handles all this in a single command. +You can use the `--skip-phases` flag to skip specific phases of the process. +For example, if you created the infrastructure manually, you can skip the cloud resource creation phase. + +See the [architecture](../architecture/orchestration.md) section for details on the inner workings of this process. + +:::tip +If you don't have a cloud subscription, you can also set up a [local Constellation cluster using virtualization](../getting-started/first-steps-local.md) for testing. +::: + +Before you create the cluster, make sure to have a [valid configuration file](./config.md). + + + + +```bash +constellation apply +``` + +`apply` stores the state of your cluster's cloud resources in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. + + + + +Self-managed infrastructure allows for more flexibility in the setup, by separating the infrastructure setup from the Constellation cluster management. +This provides flexibility in DevOps and can meet potential regulatory requirements. +It's recommended to use Terraform for infrastructure management, but you can use any tool of your choice. + +:::info + + When using Terraform, you can use the [Constellation Terraform provider](./terraform-provider.md) to manage the entire Constellation cluster lifecycle. + +::: + +You can refer to the Terraform files for the selected CSP from the [Constellation GitHub repository](https://github.com/edgelesssys/constellation/tree/main/terraform/infrastructure) for a minimum Constellation cluster configuration. From this base, you can now add, edit, or substitute resources per your own requirements with the infrastructure +management tooling of your choice. You need to keep the essential functionality of the base configuration in order for your cluster to function correctly. + + + +:::info + + On Azure, a manual update to the MAA provider's policy is necessary. + You can apply the update with the following command after creating the infrastructure, with `` being the URL of the MAA provider (i.e., `$(terraform output attestation_url | jq -r)`, when using the minimal Terraform configuration). + + ```bash + constellation maa-patch + ``` + +::: + + + +Make sure all necessary resources are created, e.g., through checking your CSP's portal and retrieve the necessary values, aligned with the outputs (specified in `outputs.tf`) of the base configuration. + +Fill these outputs into the corresponding fields of the `Infrastructure` block inside the `constellation-state.yaml` file. For example, fill the IP or DNS name your cluster can be reached at into the `.Infrastructure.ClusterEndpoint` field. + +With the required cloud resources set up, continue with initializing your cluster. + +```bash +constellation apply --skip-phases=infrastructure +``` + + + + +Finally, configure `kubectl` for your cluster: + +```bash +export KUBECONFIG="$PWD/constellation-admin.conf" +``` + +🏁 That's it. You've successfully created a Constellation cluster. + +### Troubleshooting + +In case `apply` fails, the CLI collects logs from the bootstrapping instance and stores them inside `constellation-cluster.log`. diff --git a/docs/versioned_docs/version-2.17/workflows/lb.md b/docs/versioned_docs/version-2.17/workflows/lb.md new file mode 100644 index 000000000..868e61076 --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/lb.md @@ -0,0 +1,28 @@ +# Expose a service + +Constellation integrates the native load balancers of each CSP. Therefore, to expose a service simply [create a service of type `LoadBalancer`](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer). + +## Internet-facing LB service on AWS + +To expose your application service externally you might want to use a Kubernetes Service of type `LoadBalancer`. On AWS, load-balancing is achieved through the [AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller) as in the managed EKS. + +Since recent versions, the controller deploy an internal LB by default requiring to set an annotation `service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing` to have an internet-facing LB. For more details, see the [official docs](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/guide/service/nlb/). + +For general information on LB with AWS see [Network load balancing on Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/network-load-balancing.html). + +:::caution +Before terminating the cluster, all LB backed services should be deleted, so that the controller can cleanup the related resources. +::: + +## Ingress on AWS + +The AWS Load Balancer Controller also provisions `Ingress` resources of class `alb`. +AWS Application Load Balancers (ALBs) can be configured with a [`target-type`](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/guide/ingress/annotations/#target-type). +The target type `ip` requires using the EKS container network solution, which makes it incompatible with Constellation. +If a service can be exposed on a `NodePort`, the target type `instance` can be used. + +See [Application load balancing on Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html) for more information. + +:::caution +Ingress handlers backed by AWS ALBs reside outside the Constellation cluster, so they shouldn't be handling sensitive traffic! +::: diff --git a/docs/versioned_docs/version-2.17/workflows/recovery.md b/docs/versioned_docs/version-2.17/workflows/recovery.md new file mode 100644 index 000000000..592ae247b --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/recovery.md @@ -0,0 +1,179 @@ +# Recover your cluster + +Recovery of a Constellation cluster means getting it back into a healthy state after too many concurrent node failures in the control plane. +Reasons for an unhealthy cluster can vary from a power outage, or planned reboot, to migration of nodes and regions. +Recovery events are rare, because Constellation is built for high availability and automatically and securely replaces failed nodes. When a node is replaced, Constellation's control plane first verifies the new node before it sends the node the cryptographic keys required to decrypt its [state disk](../architecture/images.md#state-disk). + +Constellation provides a recovery mechanism for cases where the control plane has failed and is unable to replace nodes. +The `constellation recover` command securely connects to all nodes in need of recovery using [attested TLS](../architecture/attestation.md#attested-tls-atls) and provides them with the keys to decrypt their state disks and continue booting. + +## Identify unhealthy clusters + +The first step to recovery is identifying when a cluster becomes unhealthy. +Usually, this can be first observed when the Kubernetes API server becomes unresponsive. + +You can check the health status of the nodes via the cloud service provider (CSP). +Constellation provides logging information on the boot process and status via serial console output. +In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. + + + + +First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. + +Second, check the boot logs of these *Instances*. In the ASG's *Instance management* view, select each desired instance. In the upper right corner, select **Action > Monitor and troubleshoot > Get system log**. + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"gcp"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["192.168.178.4:30090","192.168.178.2:30090"]} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.4:30090"} +{"level":"WARN","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.4:30090: connect: connection refused\"","endpoint":"192.168.178.4:30090"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.2:30090"} +{"level":"WARN","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.2:30090: i/o timeout\"","endpoint":"192.168.178.2:30090"} +{"level":"ERROR","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +In the Azure portal, find the cluster's resource group. +Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. +On the left, go to **Settings** > **Instances** and check that enough members are in a *Running* state. + +Second, check the boot logs of these *Instances*. +In the scale set's *Instances* view, open the details page of the desired instance. +On the left, go to **Support + troubleshooting** > **Serial console**. + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T09:56:41Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"azure"} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["10.9.0.5:30090","10.9.0.6:30090"]} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"10.9.0.5:30090"} +{"level":"WARN","ts":"2022-09-08T09:57:03Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 10.9.0.5:30090: i/o timeout\"","endpoint":"10.9.0.5:30090"} +{"level":"INFO","ts":"2022-09-08T09:57:03Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"10.9.0.6:30090"} +{"level":"WARN","ts":"2022-09-08T09:57:23Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 10.9.0.6:30090: i/o timeout\"","endpoint":"10.9.0.6:30090"} +{"level":"ERROR","ts":"2022-09-08T09:57:23Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +First, check that the control plane *Instance Group* has enough members in a *Ready* state. +In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. + +Second, check the status of the *VM Instances*. +Go to **VM Instances** and open the details of the desired instance. +Check the serial console output of that instance by opening the **Logs** > **Serial port 1 (console)** page: + +![GCP portal serial console link](../_media/recovery-gcp-serial-console-link.png) + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"gcp"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["192.168.178.4:30090","192.168.178.2:30090"]} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.4:30090"} +{"level":"WARN","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.4:30090: connect: connection refused\"","endpoint":"192.168.178.4:30090"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.2:30090"} +{"level":"WARN","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.2:30090: i/o timeout\"","endpoint":"192.168.178.2:30090"} +{"level":"ERROR","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +First, open the STACKIT portal to view all servers in your project. Select individual control plane nodes `--control-plane--` and check that enough members are in a *Running* state. + +Second, check the boot logs of these servers. Click on a server name and select **Overview**. Find the **Machine Setup** section and click on **Web console** > **Open console**. + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"gcp"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["192.168.178.4:30090","192.168.178.2:30090"]} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.4:30090"} +{"level":"WARN","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.4:30090: connect: connection refused\"","endpoint":"192.168.178.4:30090"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.2:30090"} +{"level":"WARN","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.2:30090: i/o timeout\"","endpoint":"192.168.178.2:30090"} +{"level":"ERROR","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +## Recover a cluster + +Recovering a cluster requires the following parameters: + +* The `constellation-state.yaml` file in your working directory or the cluster's endpoint +* The master secret of the cluster + +A cluster can be recovered like this: + +```bash +$ constellation recover +Pushed recovery key. +Pushed recovery key. +Pushed recovery key. +Recovered 3 control-plane nodes. +``` + +In the serial console output of the node you'll see a similar output to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:26:59Z","logger":"recoveryServer","caller":"recoveryserver/server.go:93","msg":"Received recover call"} +{"level":"INFO","ts":"2022-09-08T10:26:59Z","logger":"recoveryServer","caller":"recoveryserver/server.go:125","msg":"Received state disk key and measurement secret, shutting down server"} +{"level":"INFO","ts":"2022-09-08T10:26:59Z","logger":"recoveryServer.gRPC","caller":"zap/server_interceptors.go:61","msg":"finished streaming call with code OK","grpc.start_time":"2022-09-08T10:26:59Z","system":"grpc","span.kind":"server","grpc.service":"recoverproto.API","grpc.method":"Recover","peer.address":"192.0.2.3:41752","grpc.code":"OK","grpc.time_ms":15.701} +{"level":"INFO","ts":"2022-09-08T10:27:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:87","msg":"RejoinClient stopped"} +``` diff --git a/docs/versioned_docs/version-2.17/workflows/s3proxy.md b/docs/versioned_docs/version-2.17/workflows/s3proxy.md new file mode 100644 index 000000000..121e8a461 --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/s3proxy.md @@ -0,0 +1,58 @@ +# Install s3proxy + +Constellation includes a transparent client-side encryption proxy for [AWS S3](https://aws.amazon.com/de/s3/) and compatible stores. +s3proxy encrypts objects before sending them to S3 and automatically decrypts them on retrieval, without requiring changes to your application. +With s3proxy, you can use S3 for storage in a confidential way without having to trust the storage provider. + +## Limitations + +Currently, s3proxy has the following limitations: +- Only `PutObject` and `GetObject` requests are encrypted/decrypted by s3proxy. +By default, s3proxy will block requests that may expose unencrypted data to S3 (e.g. UploadPart). +The `allow-multipart` flag disables request blocking for evaluation purposes. +- Using the [Range](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html#API_GetObject_RequestSyntax) header on `GetObject` is currently not supported and will result in an error. + +These limitations will be removed with future iterations of s3proxy. +If you want to use s3proxy but these limitations stop you from doing so, consider [opening an issue](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&projects=&template=feature_request.yml). + +## Deployment + +You can add the s3proxy to your Constellation cluster as follows: +1. Add the Edgeless Systems chart repository: + ```bash + helm repo add edgeless https://helm.edgeless.systems/stable + helm repo update + ``` +2. Set ACCESS_KEY and ACCESS_SECRET to valid credentials you want s3proxy to use to interact with S3. +3. Deploy s3proxy: + ```bash + helm install s3proxy edgeless/s3proxy --set awsAccessKeyID="$ACCESS_KEY" --set awsSecretAccessKey="$ACCESS_SECRET" + ``` + +If you want to run a demo application, check out the [Filestash with s3proxy](../getting-started/examples/filestash-s3proxy.md) example. + + +## Technical details + +### Encryption + +s3proxy relies on Google's [Tink Cryptographic Library](https://developers.google.com/tink) to implement cryptographic operations securely. +The used cryptographic primitives are [NIST SP 800 38f](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf) for key wrapping and [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)-[GCM](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Galois/counter_(GCM)) with 256 bit keys for data encryption. + +s3proxy uses [envelope encryption](https://cloud.google.com/kms/docs/envelope-encryption) to encrypt objects. +This means s3proxy uses a key encryption key (KEK) issued by the [KeyService](../architecture/microservices.md#keyservice) to encrypt data encryption keys (DEKs). +Each S3 object is encrypted with its own DEK. +The encrypted DEK is then saved as metadata of the encrypted object. +This enables key rotation of the KEK without re-encrypting the data in S3. +The approach also allows access to objects from different locations, as long as each location has access to the KEK. + +### Traffic interception + +To use s3proxy, you have to redirect your outbound S3 traffic to s3proxy. +This can either be done by modifying your client application or by changing the deployment of your application. + +The necessary deployment modifications are to add DNS redirection and a trusted TLS certificate to the client's trust store. +DNS redirection can be defined for each pod, allowing you to use s3proxy for one application without changing other applications in the same cluster. +Adding a trusted TLS certificate is necessary as clients communicate with s3proxy via HTTPS. +To have your client application trust s3proxy's TLS certificate, the certificate has to be added to the client's certificate trust store. +The [Filestash with s3proxy](../getting-started/examples/filestash-s3proxy.md) example shows how to do this. diff --git a/docs/versioned_docs/version-2.17/workflows/sbom.md b/docs/versioned_docs/version-2.17/workflows/sbom.md new file mode 100644 index 000000000..6c1702dee --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/sbom.md @@ -0,0 +1,93 @@ +# Consume software bill of materials (SBOMs) + + + +--- + +Constellation builds produce a [software bill of materials (SBOM)](https://www.ntia.gov/SBOM) for each generated [artifact](../architecture/microservices.md). +You can use SBOMs to make informed decisions about dependencies and vulnerabilities in a given application. Enterprises rely on SBOMs to maintain an inventory of used applications, which allows them to take data-driven approaches to managing risks related to vulnerabilities. + +SBOMs for Constellation are generated using [Syft](https://github.com/anchore/syft), signed using [Cosign](https://github.com/sigstore/cosign), and stored with the produced artifact. + +:::note +The public key for Edgeless Systems' long-term code-signing key is: + +``` +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT +JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== +-----END PUBLIC KEY----- +``` + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +Make sure the key is available in a file named `cosign.pub` to execute the following examples. +::: + +## Verify and download SBOMs + +The following sections detail how to work with each type of artifact to verify and extract the SBOM. + +### Constellation CLI + +The SBOM for Constellation CLI is made available on the [GitHub release page](https://github.com/edgelesssys/constellation/releases). The SBOM (`constellation.spdx.sbom`) and corresponding signature (`constellation.spdx.sbom.sig`) are valid for each Constellation CLI for a given version, regardless of architecture and operating system. + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/download/v2.2.0/constellation.spdx.sbom +curl -LO https://github.com/edgelesssys/constellation/releases/download/v2.2.0/constellation.spdx.sbom.sig +cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig constellation.spdx.sbom +``` + +### Container Images + +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. + +As a consumer, use cosign to download and verify the SBOM: + +```bash +# Verify and download the attestation statement +cosign verify-attestation ghcr.io/edgelesssys/constellation/verification-service@v2.2.0 --type 'https://cyclonedx.org/bom' --key cosign.pub --output-file verification-service.att.json +# Extract SBOM from attestation statement +jq -r .payload verification-service.att.json | base64 -d > verification-service.cyclonedx.sbom +``` + +A successful verification should result in similar output: + +```shell-session +$ cosign verify-attestation ghcr.io/edgelesssys/constellation/verification-service@v2.2.0 --type 'https://cyclonedx.org/bom' --key cosign.pub --output-file verification-service.sbom + +Verification for ghcr.io/edgelesssys/constellation/verification-service@v2.2.0 -- +The following checks were performed on each of these signatures: + - The cosign claims were validated + - The signatures were verified against the specified public key +$ jq -r .payload verification-service.sbom | base64 -d > verification-service.cyclonedx.sbom +``` + +:::note + +This example considers only the `verification-service`. The same approach works for all containers in the [Constellation container registry](https://github.com/orgs/edgelesssys/packages?repo_name=constellation). + +::: + + + +## Vulnerability scanning + +You can use a plethora of tools to consume SBOMs. This section provides suggestions for tools that are popular and known to produce reliable results, but any tool that consumes [SPDX](https://spdx.dev/) or [CycloneDX](https://cyclonedx.org/) files should work. + +Syft is able to [convert between the two formats](https://github.com/anchore/syft#format-conversion-experimental) in case you require a specific type. + +### Grype + +[Grype](https://github.com/anchore/grype) is a CLI tool that lends itself well for integration into CI/CD systems or local developer machines. It's also able to consume the signed attestation statement directly and does the verification in one go. + +```bash +grype att:verification-service.sbom --key cosign.pub --add-cpes-if-none -q +``` + +### Dependency Track + +[Dependency Track](https://dependencytrack.org/) is one of the oldest and most mature solutions when it comes to managing software inventory and vulnerabilities. Once imported, it continuously scans SBOMs for new vulnerabilities. It supports the CycloneDX format and provides direct guidance on how to comply with [U.S. Executive Order 14028](https://docs.dependencytrack.org/usage/executive-order-14028/). diff --git a/docs/versioned_docs/version-2.17/workflows/scale.md b/docs/versioned_docs/version-2.17/workflows/scale.md new file mode 100644 index 000000000..28f19e3f1 --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/scale.md @@ -0,0 +1,122 @@ +# Scale your cluster + +Constellation provides all features of a Kubernetes cluster including scaling and autoscaling. + +## Worker node scaling + +### Autoscaling + +Constellation comes with autoscaling disabled by default. To enable autoscaling, find the scaling group of +worker nodes: + +```bash +kubectl get scalinggroups -o json | yq '.items | .[] | select(.spec.role == "Worker") | [{"name": .metadata.name, "nodeGoupName": .spec.nodeGroupName}]' +``` + +This will output a list of scaling groups with the corresponding cloud provider name (`name`) and the cloud provider agnostic name of the node group (`nodeGroupName`). + +Then, patch the `autoscaling` field of the scaling group resource with the desired `name` to `true`: + +```bash +# Replace with the name of the scaling group you want to enable autoscaling for +worker_group= +kubectl patch scalinggroups $worker_group --patch '{"spec":{"autoscaling": true}}' --type='merge' +kubectl get scalinggroup $worker_group -o jsonpath='{.spec}' | yq -P +``` + +The cluster autoscaler now automatically provisions additional worker nodes so that all pods have a place to run. +You can configure the minimum and maximum number of worker nodes in the scaling group by patching the `min` or +`max` fields of the scaling group resource: + +```bash +kubectl patch scalinggroups $worker_group --patch '{"spec":{"max": 5}}' --type='merge' +kubectl get scalinggroup $worker_group -o jsonpath='{.spec}' | yq -P +``` + +The cluster autoscaler will now never provision more than 5 worker nodes. + +If you want to see the autoscaling in action, try to add a deployment with a lot of replicas, like the +following Nginx deployment. The number of replicas needed to trigger the autoscaling depends on the size of +and count of your worker nodes. Wait for the rollout of the deployment to finish and compare the number of +worker nodes before and after the deployment: + +```bash +kubectl create deployment nginx --image=nginx --replicas 150 +kubectl -n kube-system get nodes +kubectl rollout status deployment nginx +kubectl -n kube-system get nodes +``` + +### Manual scaling + +Alternatively, you can manually scale your cluster up or down: + + + + +1. Go to Auto Scaling Groups and select the worker ASG to scale up. +2. Click **Edit** +3. Set the new (increased) **Desired capacity** and **Update**. + + + + +1. Find your Constellation resource group. +2. Select the `scale-set-workers`. +3. Go to **settings** and **scaling**. +4. Set the new **instance count** and **save**. + + + + +1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). +2. **Edit** the **worker** instance group. +3. Set the new **number of instances** and **save**. + + + + +Dynamic cluster scaling isn't yet supported for STACKIT. +Support will be introduced in one of the upcoming releases. + + + + +## Control-plane node scaling + +Control-plane nodes can **only be scaled manually and only scaled up**! + +To increase the number of control-plane nodes, follow these steps: + + + + +1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. +2. Click **Edit** +3. Set the new (increased) **Desired capacity** and **Update**. + + + + +1. Find your Constellation resource group. +2. Select the `scale-set-controlplanes`. +3. Go to **settings** and **scaling**. +4. Set the new (increased) **instance count** and **save**. + + + + +1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). +2. **Edit** the **control-plane** instance group. +3. Set the new (increased) **number of instances** and **save**. + + + + +Dynamic cluster scaling isn't yet supported for STACKIT. +Support will be introduced in one of the upcoming releases. + + + + +If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.17/workflows/storage.md b/docs/versioned_docs/version-2.17/workflows/storage.md new file mode 100644 index 000000000..a5c52be90 --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/storage.md @@ -0,0 +1,281 @@ +# Use persistent storage + +Persistent storage in Kubernetes requires cloud-specific configuration. +For abstraction of container storage, Kubernetes offers [volumes](https://kubernetes.io/docs/concepts/storage/volumes/), +allowing users to mount storage solutions directly into containers. +The [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) is the standard interface for exposing arbitrary block and file storage systems into containers in Kubernetes. +Cloud service providers (CSPs) offer their own CSI-based solutions for cloud storage. + +## Confidential storage + +Most cloud storage solutions support encryption, such as [GCE Persistent Disks (PD)](https://cloud.google.com/kubernetes-engine/docs/how-to/using-cmek). +Constellation supports the available CSI-based storage options for Kubernetes engines in AWS, Azure, GCP, and STACKIT. +However, their encryption takes place in the storage backend and is managed by the CSP. +Thus, using the default CSI drivers for these storage types means trusting the CSP with your persistent data. + +To address this, Constellation provides CSI drivers for AWS EBS, Azure Disk, GCE PD, and OpenStack Cinder, offering [encryption on the node level](../architecture/keys.md#storage-encryption). They enable transparent encryption for persistent volumes without needing to trust the cloud backend. Plaintext data never leaves the confidential VM context, offering you confidential storage. + +For more details see [encrypted persistent storage](../architecture/encrypted-storage.md). + +## CSI drivers + +Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. + + + + +**Constellation CSI driver for AWS Elastic Block Store** +Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. +Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. + + + + +**Constellation CSI driver for Azure Disk**: +Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. +See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. +Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. + + + + +**Constellation CSI driver for GCP Persistent Disk**: +Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. +Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. + + + + +**Constellation CSI driver for STACKIT / OpenStack Cinder** +Mount [Cinder](https://docs.openstack.org/cinder/latest/) block storage volumes into your Constellation cluster. +Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-cloud-provider-openstack) for more information. + + + + +Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. + +## Installation + +The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. +If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. + + + + +AWS comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [SSDs of `gp3` type](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-volume-types.html) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [SSDs of `gp3` type](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-volume-types.html) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +Azure comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [Standard SSDs](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#standard-ssds) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [Premium SSDs](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#premium-ssds) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +GCP comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [standard persistent disks](https://cloud.google.com/compute/docs/disks#pdspecs) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [performance (SSD) persistent disks](https://cloud.google.com/compute/docs/disks#pdspecs) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +STACKIT comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [disks of `storage_premium_perf1` type](https://docs.stackit.cloud/stackit/en/service-plans-blockstorage-75137974.html) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [disks of `storage_premium_perf1` type](https://docs.stackit.cloud/stackit/en/service-plans-blockstorage-75137974.html) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) + + A [persistent volume claim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) is a request for storage with certain properties. + It can refer to a storage class. + The following creates a persistent volume claim, requesting 20 GB of storage via the `encrypted-rwo` storage class: + + ```bash + cat < + +--- + +You can terminate your cluster using the CLI. For this, you need the Terraform state directory named [`constellation-terraform`](../reference/terraform.md) in the current directory. + +:::danger + +All ephemeral storage and state of your cluster will be lost. Make sure any data is safely stored in persistent storage. Constellation can recreate your cluster and the associated encryption keys, but won't backup your application data automatically. + +::: + + + +Terminate the cluster by running: + +```bash +constellation terminate +``` + +Or without confirmation (e.g., for automation purposes): + +```bash +constellation terminate --yes +``` + +This deletes all resources created by Constellation in your cloud environment. +All local files created by the `apply` command are deleted as well, except for `constellation-mastersecret.json` and the configuration file. + +:::caution + +Termination can fail if additional resources have been created that depend on the ones managed by Constellation. In this case, you need to delete these additional +resources manually. Just run the `terminate` command again afterward to continue the termination process of the cluster. + +::: + + + +Terminate the cluster by running: + +```bash +terraform destroy +``` + +Delete all files that are no longer needed: + +```bash +rm constellation-state.yaml constellation-admin.conf +``` + +Only the `constellation-mastersecret.json` and the configuration file remain. + + + diff --git a/docs/versioned_docs/version-2.17/workflows/terraform-provider.md b/docs/versioned_docs/version-2.17/workflows/terraform-provider.md new file mode 100644 index 000000000..ed8f46eda --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/terraform-provider.md @@ -0,0 +1,129 @@ +# Use the Terraform provider + +The Constellation Terraform provider allows to manage the full lifecycle of a Constellation cluster (namely creation, upgrades, and deletion) via Terraform. +The provider is available through the [Terraform registry](https://registry.terraform.io/providers/edgelesssys/constellation/latest) and is released in lock-step with Constellation releases. + +## Prerequisites + +- a Linux / Mac operating system (ARM64/AMD64) +- a Terraform installation of version `v1.4.4` or above + +## Quick setup + +This example shows how to set up a Constellation cluster with the reference IAM and infrastructure setup. This setup is also used when creating a Constellation cluster through the Constellation CLI. You can either consume the IAM / infrastructure modules through a remote source (recommended) or local files. The latter requires downloading the infrastructure and IAM modules for the corresponding CSP from `terraform-modules.zip` on the [Constellation release page](https://github.com/edgelesssys/constellation/releases/latest) and placing them in the Terraform workspace directory. + +1. Create a directory (workspace) for your Constellation cluster. + + ```bash + mkdir constellation-workspace + cd constellation-workspace + ``` + +2. Use one of the [example configurations for using the Constellation Terraform provider](https://github.com/edgelesssys/constellation/tree/main/terraform-provider-constellation/examples/full) or create a `main.tf` file and fill it with the resources you want to create. The [Constellation Terraform provider documentation](https://registry.terraform.io/providers/edgelesssys/constellation/latest) offers thorough documentation on the resources and their attributes. +3. Initialize and apply the Terraform configuration. + + + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + When creating a cluster on Azure, you need to manually patch the policy of the MAA provider before creating the Constellation cluster, as this feature isn't available in Azure's Terraform provider yet. The Constellation CLI provides a utility for patching, but you + can also do it manually. + + ```bash + terraform init + terraform apply -target module.azure_iam # adjust resource path if not using the example configuration + terraform apply -target module.azure_infrastructure # adjust resource path if not using the example configuration + constellation maa-patch $(terraform output -raw maa_url) # adjust output path / input if not using the example configuration or manually patch the resource + terraform apply -target constellation_cluster.azure_example # adjust resource path if not using the example configuration + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + Use the following policy if manually performing the patch. + + ``` + version= 1.0; + authorizationrules + { + [type=="x-ms-azurevm-default-securebootkeysvalidated", value==false] => deny(); + [type=="x-ms-azurevm-debuggersdisabled", value==false] => deny(); + // The line below was edited to use the MAA provider within Constellation. Do not edit manually. + //[type=="secureboot", value==false] => deny(); + [type=="x-ms-azurevm-signingdisabled", value==false] => deny(); + [type=="x-ms-azurevm-dbvalidated", value==false] => deny(); + [type=="x-ms-azurevm-dbxvalidated", value==false] => deny(); + => permit(); + }; + issuancerules + { + }; + ``` + + + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + +4. Connect to the cluster. + + ```bash + terraform output -raw kubeconfig > constellation-admin.conf + export KUBECONFIG=$(realpath constellation-admin.conf) + ``` + +## Bringing your own infrastructure + +Instead of using the example infrastructure used in the [quick setup](#quick-setup), you can also provide your own infrastructure. +If you need a starting point for a custom infrastructure setup, you can download the infrastructure / IAM Terraform modules for the respective CSP from the Constellation [GitHub releases](https://github.com/edgelesssys/constellation/releases). You can modify and extend the modules per your requirements, while keeping the basic functionality intact. +The module contains: + +- `{csp}`: cloud resources the cluster runs on +- `iam/{csp}`: IAM resources used within the cluster + +When upgrading your cluster, make sure to check the Constellation release notes for potential breaking changes in the reference infrastructure / IAM modules that need to be considered. + +## Cluster upgrades + +:::tip +Also see the [general documentation on cluster upgrades](./upgrade.md). +::: + +The steps for applying the upgrade are as follows: + +1. Update the version constraint of the Constellation Terraform provider in the `required_providers` block in your Terraform configuration. +2. If you explicitly set any of the version attributes of the provider's resources and data sources (e.g. `image_version` or `constellation_microservice_version`), make sure to update them too. Refer to Constellation's [version support policy](https://github.com/edgelesssys/constellation/blob/main/dev-docs/workflows/versions-support.md) for more information on how each Constellation version and its dependencies are supported. +3. Update the IAM / infrastructure configuration. + - For [remote addresses as module sources](https://developer.hashicorp.com/terraform/language/modules/sources#fetching-archives-over-http), update the version number inside the address of the `source` field of the infrastructure / IAM module to the target version. + - For [local paths as module sources](https://developer.hashicorp.com/terraform/language/modules/sources#local-paths) or when [providing your own infrastructure](#bringing-your-own-infrastructure), see the changes made in the reference modules since the upgrade's origin version and adjust your infrastructure / IAM configuration accordingly. +4. Upgrade the Terraform module and provider dependencies and apply the targeted configuration. + +```bash + terraform init -upgrade + terraform apply +``` diff --git a/docs/versioned_docs/version-2.17/workflows/troubleshooting.md b/docs/versioned_docs/version-2.17/workflows/troubleshooting.md new file mode 100644 index 000000000..195bce1cc --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/troubleshooting.md @@ -0,0 +1,151 @@ +# Troubleshooting + +This section aids you in finding problems when working with Constellation. + +## Common issues + +### Issues with creating new clusters + +When you create a new cluster, you should always use the [latest release](https://github.com/edgelesssys/constellation/releases/latest). +If something doesn't work, check out the [known issues](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22). + +### Azure: Resource Providers can't be registered + +On Azure, you may receive the following error when running `apply` or `terminate` with limited IAM permissions: + +```shell-session +Error: Error ensuring Resource Providers are registered. + +Terraform automatically attempts to register the Resource Providers it supports to +ensure it's able to provision resources. + +If you don't have permission to register Resource Providers you may wish to use the +"skip_provider_registration" flag in the Provider block to disable this functionality. + +[...] +``` + +To continue, please ensure that the [required resource providers](../getting-started/install.md#required-permissions) have been registered in your subscription by your administrator. + +Afterward, set `ARM_SKIP_PROVIDER_REGISTRATION=true` as an environment variable and either run `apply` or `terminate` again. +For example: + +```bash +ARM_SKIP_PROVIDER_REGISTRATION=true constellation apply +``` + +Or alternatively, for `terminate`: + +```bash +ARM_SKIP_PROVIDER_REGISTRATION=true constellation terminate +``` + +### Azure: Can't update attestation policy + +On Azure, you may receive the following error when running `apply` from within an Azure environment, e.g., an Azure VM: + +```shell-session +An error occurred: patching policies: updating attestation policy: unexpected status code: 403 Forbidden +``` + +The problem occurs because the Azure SDK we use internally attempts to [authenticate towards the Azure API with the managed identity of your current environment instead of the Azure CLI token](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential). + +We decided not to deviate from this behavior and comply with the ordering of credentials. + +A solution is to add the [required permissions](../getting-started/install.md#required-permissions) to the managed identity of your environment. For example, the managed identity of your Azure VM, instead of the account that you've authenticated with in the Azure CLI. + +If your setup requires a change in the ordering of credentials, please open an issue and explain your desired behavior. + + + +### Nodes fail to join with error `untrusted measurement value` + +This error indicates that a node's [attestation statement](../architecture/attestation.md) contains measurements that don't match the trusted values expected by the [JoinService](../architecture/microservices.md#joinservice). +This may for example happen if the cloud provider updates the VM's firmware such that it influences the [runtime measurements](../architecture/attestation.md#runtime-measurements) in an unforeseen way. +A failed upgrade due to an erroneous attestation config can also cause this error. +You can change the expected measurements to resolve the failure. + +:::caution + +Attestation and trusted measurements are crucial for the security of your cluster. +Be extra careful when manually changing these settings. +When in doubt, check if the encountered [issue is known](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22) or [contact support](https://github.com/edgelesssys/constellation#support). + +::: + +:::tip + +During an upgrade with modified attestation config, a backup of the current configuration is stored in the `join-config` config map in the `kube-system` namespace under the `attestationConfig_backup` key. To restore the old attestation config after a failed upgrade, replace the value of `attestationConfig` with the value from `attestationConfig_backup`: + +```bash +kubectl patch configmaps -n kube-system join-config -p "{\"data\":{\"attestationConfig\":\"$(kubectl get configmaps -n kube-system join-config -o "jsonpath={.data.attestationConfig_backup}")\"}}" +``` + +::: + +You can use the `apply` command to change measurements of a running cluster: + +1. Modify the `measurements` key in your local `constellation-conf.yaml` to the expected values. +2. Run `constellation apply`. + +Keep in mind that running `apply` also applies any version changes from your config to the cluster. + +You can run these commands to learn about the versions currently configured in the cluster: + +- Kubernetes API server version: `kubectl get nodeversion constellation-version -o json -n kube-system | jq .spec.kubernetesClusterVersion` +- image version: `kubectl get nodeversion constellation-version -o json -n kube-system | jq .spec.imageVersion` +- microservices versions: `helm list --filter 'constellation-services' -n kube-system` + +### Upgrading Kubernetes resources fails + +Constellation manages its Kubernetes resources using Helm. +When applying an upgrade, the charts that are about to be installed, and a values override file `overrides.yaml`, +are saved to disk in your current workspace under `constellation-upgrade/upgrade-/helm-charts/`. +If upgrading the charts using the Constellation CLI fails, you can review these charts and try to manually apply the upgrade. + +:::caution + +Changing and manually applying the charts may destroy cluster resources and can lead to broken Constellation deployments. +Proceed with caution and when in doubt, +check if the encountered [issue is known](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22) or [contact support](https://github.com/edgelesssys/constellation#support). + +::: + +## Diagnosing issues + +### Logs + +To get started on diagnosing issues with Constellation, it's often helpful to collect logs from nodes, pods, or other resources in the cluster. Most logs are available through Kubernetes' standard +[logging interfaces](https://kubernetes.io/docs/concepts/cluster-administration/logging/). + +To debug issues occurring at boot time of the nodes, you can use the serial console interface of the CSP while the machine boots to get a read-only view of the boot logs. + +Apart from that, Constellation also offers further [observability integrations](../architecture/observability.md). + +### Node shell access + +Debugging via a shell on a node is [directly supported by Kubernetes](https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/#node-shell-session). + +1. Figure out which node to connect to: + + ```bash + kubectl get nodes + # or to see more information, such as IPs: + kubectl get nodes -o wide + ``` + +2. Connect to the node: + + ```bash + kubectl debug node/constell-worker-xksa0-000000 -it --image=busybox + ``` + + You will be presented with a prompt. + + The nodes file system is mounted at `/host`. + +3. Once finished, clean up the debug pod: + + ```bash + kubectl delete pod node-debugger-constell-worker-xksa0-000000-bjthj + ``` diff --git a/docs/versioned_docs/version-2.17/workflows/trusted-launch.md b/docs/versioned_docs/version-2.17/workflows/trusted-launch.md new file mode 100644 index 000000000..d6d01d8eb --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/trusted-launch.md @@ -0,0 +1,54 @@ +# Use Azure trusted launch VMs + +Constellation also supports [trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch) on Microsoft Azure. Trusted launch VMs don't offer the same level of security as Confidential VMs, but are available in more regions and in larger quantities. The main difference between trusted launch VMs and normal VMs is that the former offer vTPM-based remote attestation. When used with trusted launch VMs, Constellation relies on vTPM-based remote attestation to verify nodes. + +:::caution + +Trusted launch VMs don't provide runtime encryption and don't keep the cloud service provider (CSP) out of your trusted computing base. + +::: + +Constellation supports trusted launch VMs with instance types `Standard_D*_v4` and `Standard_E*_v4`. Run `constellation config instance-types` for a list of all supported instance types. + +## VM images + +Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. + +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. + +After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. +You can use a script to do this: + +```bash +wget https://raw.githubusercontent.com/edgelesssys/constellation/main/hack/importAzure.sh +chmod +x importAzure.sh +AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_IMAGE_FILE=./constellation.img ./importAzure.sh +``` + +The script creates the following resources: + +1. A new image gallery with the default name `constellation-import` +2. A new image definition with the default name `constellation` +3. The actual image with the provided version. In this case `2.2.0` + +Once the import is completed, use the `ID` of the image version in your `constellation-conf.yaml` for the `image` field. Set `confidentialVM` to `false`. + +Fetch the image measurements: + +```bash +IMAGE_VERSION=2.2.0 +URL=https://public-edgeless-constellation.s3.us-east-2.amazonaws.com//communitygalleries/constellationcvm-b3782fa0-0df7-4f2f-963e-fc7fc42663df/images/constellation/versions/$IMAGE_VERSION/measurements.yaml +constellation config fetch-measurements -u$URL -s$URL.sig +``` + +:::info + +The [`constellation apply`](create.md) command will issue a warning because manually imported images aren't recognized as production grade images: + +```shell-session +Configured image doesn't look like a released production image. Double check image before deploying to production. +``` + +Please ignore this warning. + +::: diff --git a/docs/versioned_docs/version-2.17/workflows/upgrade.md b/docs/versioned_docs/version-2.17/workflows/upgrade.md new file mode 100644 index 000000000..7348c0dbc --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/upgrade.md @@ -0,0 +1,110 @@ +# Upgrade your cluster + +Constellation provides an easy way to upgrade all components of your cluster, without disrupting it's availability. +Specifically, you can upgrade the Kubernetes version, the nodes' image, and the Constellation microservices. +You configure the desired versions in your local Constellation configuration and trigger upgrades with the `apply` command. +To learn about available versions you use the `upgrade check` command. +Which versions are available depends on the CLI version you are using. + +## Update the CLI + +Each CLI comes with a set of supported microservice and Kubernetes versions. +Most importantly, a given CLI version can only upgrade a cluster of the previous minor version, but not older ones. +This means that you have to upgrade your CLI and cluster one minor version at a time. + +For example, if you are currently on CLI version v2.6 and the latest version is v2.8, you should + +* upgrade the CLI to v2.7, +* upgrade the cluster to v2.7, +* and only then continue upgrading the CLI (and the cluster) to v2.8 after. + +Also note that if your current Kubernetes version isn't supported by the next CLI version, use your current CLI to upgrade to a newer Kubernetes version first. + +To learn which Kubernetes versions are supported by a particular CLI, run [constellation config kubernetes-versions](../reference/cli.md#constellation-config-kubernetes-versions). + +## Migrate the configuration + +The Constellation configuration file is located in the file `constellation-conf.yaml` in your workspace. +Refer to the [migration reference](../reference/migration.md) to check if you need to update fields in your configuration file. +Use [`constellation config migrate`](../reference/cli.md#constellation-config-migrate) to automatically update an old config file to a new format. + +## Check for upgrades + +To learn which versions the current CLI can upgrade to and what's installed in your cluster, run: + +```bash +# Show possible upgrades +constellation upgrade check + +# Show possible upgrades and write them to config file +constellation upgrade check --update-config +``` + +You can either enter the reported target versions into your config manually or run the above command with the `--update-config` flag. +When using this flag, the `kubernetesVersion`, `image`, `microserviceVersion`, and `attestation` fields are overwritten with the smallest available upgrade. + +## Apply the upgrade + +Once you updated your config with the desired versions, you can trigger the upgrade with this command: + +```bash +constellation apply +``` + +Microservice upgrades will be finished within a few minutes, depending on the cluster size. +If you are interested, you can monitor pods restarting in the `kube-system` namespace with your tool of choice. + +Image and Kubernetes upgrades take longer. +For each node in your cluster, a new node has to be created and joined. +The process usually takes up to ten minutes per node. + +When applying an upgrade, the Helm charts for the upgrade as well as backup files of Constellation-managed Custom Resource Definitions, Custom Resources, and Terraform state are created. +You can use the Terraform state backup to restore previous resources in case an upgrade misconfigured or erroneously deleted a resource. +You can use the Custom Resource (Definition) backup files to restore Custom Resources and Definitions manually (e.g., via `kubectl apply`) if the automatic migration of those resources fails. +You can use the Helm charts to manually apply upgrades to the Kubernetes resources, should an upgrade fail. + +:::note + +For advanced users: the upgrade consists of several phases that can be individually skipped through the `--skip-phases` flag. +The phases are `infrastracture` for the cloud resource management through Terraform, `helm` for the chart management of the microservices, `image` for OS image upgrades, and `k8s` for Kubernetes version upgrades. + +::: + +## Check the status + +Upgrades are asynchronous operations. +After you run `apply`, it will take a while until the upgrade has completed. +To understand if an upgrade is finished, you can run: + +```bash +constellation status +``` + +This command displays the following information: + +* The installed services and their versions +* The image and Kubernetes version the cluster is expecting on each node +* How many nodes are up to date + +Here's an example output: + +```shell-session +Target versions: + Image: v2.6.0 + Kubernetes: v1.25.8 +Service versions: + Cilium: v1.12.1 + cert-manager: v1.10.0 + constellation-operators: v2.6.0 + constellation-services: v2.6.0 +Cluster status: Some node versions are out of date + Image: 23/25 + Kubernetes: 25/25 +``` + +This output indicates that the cluster is running Kubernetes version `1.25.8`, and all nodes have the appropriate binaries installed. +23 out of 25 nodes have already upgraded to the targeted image version of `2.6.0`, while two are still in progress. + +## Apply further upgrades + +After the upgrade is finished, you can run `constellation upgrade check` again to see if there are more upgrades available. If so, repeat the process. diff --git a/docs/versioned_docs/version-2.17/workflows/verify-cli.md b/docs/versioned_docs/version-2.17/workflows/verify-cli.md new file mode 100644 index 000000000..e33569d37 --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/verify-cli.md @@ -0,0 +1,129 @@ +# Verify the CLI + +:::info +This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. +::: + + + +--- + +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. + +:::note +The public key for Edgeless Systems' long-term code-signing key is: + +``` +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT +JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== +-----END PUBLIC KEY----- +``` + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +::: + +The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. + +You should always ensure that (1) your CLI executable was signed with the private key corresponding to the above public key and that (2) there is a corresponding entry in the Rekor transparency log. Both can be done as described in the following. + +:::info +You don't need to verify the Constellation node images. This is done automatically by your CLI and the rest of Constellation. +::: + +## Verify the signature + +:::info +This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. +::: + +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: + +```shell-session +$ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 + +Verified OK +``` + +The above performs an offline verification of the provided public key, signature, and executable. To also verify that a corresponding entry exists in the public Rekor transparency log, add the variable `COSIGN_EXPERIMENTAL=1`: + +```shell-session +$ COSIGN_EXPERIMENTAL=1 cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 + +tlog entry verified with uuid: afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 index: 3477047 +Verified OK +``` + +🏁 You now know that your CLI executable was officially released and signed by Edgeless Systems. + +### Optional: Manually inspect the transparency log + +To further inspect the public Rekor transparency log, [install the Rekor CLI](https://docs.sigstore.dev/logging/installation). A search for the CLI executable should give a single UUID. (Note that this UUID contains the UUID from the previous `cosign` command.) + +```shell-session +$ rekor-cli search --artifact constellation-linux-amd64 + +Found matching entries (listed by UUID): +362f8ecba72f4326afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 +``` + +With this UUID you can get the full entry from the transparency log: + +```shell-session +$ rekor-cli get --uuid=362f8ecba72f4326afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 + +LogID: c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d +Index: 3477047 +IntegratedTime: 2022-09-12T22:28:16Z +UUID: afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 +Body: { + "HashedRekordObj": { + "data": { + "hash": { + "algorithm": "sha256", + "value": "40e137b9b9b8204d672642fd1e181c6d5ccb50cfc5cc7fcbb06a8c2c78f44aff" + } + }, + "signature": { + "content": "MEUCIQCSER3mGj+j5Pr2kOXTlCIHQC3gT30I7qkLr9Awt6eUUQIgcLUKRIlY50UN8JGwVeNgkBZyYD8HMxwC/LFRWoMn180=", + "publicKey": { + "content": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFZjhGMWhwbXdFK1lDRlh6akd0YVFjckw2WFpWVApKbUVlNWlTTHZHMVN5UVNBZXc3V2RNS0Y2bzl0OGUyVEZ1Q2t6bE9oaGx3czJPSFdiaUZabkZXQ0Z3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==" + } + } + } +} +``` + +The field `publicKey` should contain Edgeless Systems' public key in Base64 encoding. + +You can get an exhaustive list of artifact signatures issued by Edgeless Systems via the following command: + +```bash +rekor-cli search --public-key https://edgeless.systems/es.pub --pki-format x509 +``` + +Edgeless Systems monitors this list to detect potential unauthorized use of its private key. + +## Verify the provenance + +Provenance attests that a software artifact was produced by a specific repository and build system invocation. For more information on provenance visit [slsa.dev](https://slsa.dev/provenance/v0.2) and learn about the [adoption of SLSA for Constellation](../reference/slsa.md). + +Just as checking its signature proves that the CLI hasn't been manipulated, checking the provenance proves that the artifact was produced by the expected build process and hasn't been tampered with. + +To verify the provenance, first install the [slsa-verifier](https://github.com/slsa-framework/slsa-verifier). Then make sure you have the provenance file (`constellation.intoto.jsonl`) and Constellation CLI downloaded. Both are available on the [GitHub release page](https://github.com/edgelesssys/constellation/releases). + +:::info +The same provenance file is valid for all Constellation CLI executables of a given version independent of the target platform. +::: + +Use the verifier to perform the check: + +```shell-session +$ slsa-verifier verify-artifact constellation-linux-amd64 \ + --provenance-path constellation.intoto.jsonl \ + --source-uri github.com/edgelesssys/constellation + +Verified signature against tlog entry index 7771317 at URL: https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77af2c04c8b4ae0d5bc5... +Verified build using builder https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v1.2.2 at commit 18e9924b416323c37b9cdfd6cc728de8a947424a +PASSED: Verified SLSA provenance +``` diff --git a/docs/versioned_docs/version-2.17/workflows/verify-cluster.md b/docs/versioned_docs/version-2.17/workflows/verify-cluster.md new file mode 100644 index 000000000..b6595ebf2 --- /dev/null +++ b/docs/versioned_docs/version-2.17/workflows/verify-cluster.md @@ -0,0 +1,97 @@ +# Verify your cluster + +Constellation's [attestation feature](../architecture/attestation.md) allows you, or a third party, to verify the integrity and confidentiality of your Constellation cluster. + +## Fetch measurements + +To verify the integrity of Constellation you need trusted measurements to verify against. For each node image released by Edgeless Systems, there are signed measurements, which you can download using the CLI: + +```bash +constellation config fetch-measurements +``` + +This command performs the following steps: + +1. Download the signed measurements for the configured image. By default, this will use Edgeless Systems' public measurement registry. +2. Verify the signature of the measurements. This will use Edgeless Systems' [public key](https://edgeless.systems/es.pub). +3. Write measurements into configuration file. + +The configuration file then contains a list of `measurements` similar to the following: + +```yaml +# ... +measurements: + 0: + expected: "0f35c214608d93c7a6e68ae7359b4a8be5a0e99eea9107ece427c4dea4e439cf" + warnOnly: false + 4: + expected: "02c7a67c01ec70ffaf23d73a12f749ab150a8ac6dc529bda2fe1096a98bf42ea" + warnOnly: false + 5: + expected: "e6949026b72e5045706cd1318889b3874480f7a3f7c5c590912391a2d15e6975" + warnOnly: true + 8: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false + 9: + expected: "f0a6e8601b00e2fdc57195686cd4ef45eb43a556ac1209b8e25d993213d68384" + warnOnly: false + 11: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false + 12: + expected: "da99eb6cf7c7fbb692067c87fd5ca0b7117dc293578e4fea41f95d3d3d6af5e2" + warnOnly: false + 13: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false + 14: + expected: "d7c4cc7ff7933022f013e03bdee875b91720b5b86cf1753cad830f95e791926f" + warnOnly: true + 15: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false +# ... +``` + +Each entry specifies the expected value of the Constellation node, and whether the measurement should be enforced (`warnOnly: false`), or only a warning should be logged (`warnOnly: true`). +By default, the subset of the [available measurements](../architecture/attestation.md#runtime-measurements) that can be locally reproduced and verified is enforced. + +During attestation, the validating side (CLI or [join service](../architecture/microservices.md#joinservice)) compares each measurement reported by the issuing side (first node or joining node) individually. +For mismatching measurements that have set `warnOnly` to `true` only a warning is emitted. +For mismatching measurements that have set `warnOnly` to `false` an error is emitted and attestation fails. +If attestation fails for a new node, it isn't permitted to join the cluster. + +## The *verify* command + +:::note +The steps below are purely optional. They're automatically executed by `constellation apply` when you initialize your cluster. The `constellation verify` command mostly has an illustrative purpose. +::: + +The `verify` command obtains and verifies an attestation statement from a running Constellation cluster. + +```bash +constellation verify [--cluster-id ...] +``` + +From the attestation statement, the command verifies the following properties: + +* The cluster is using the correct Confidential VM (CVM) type. +* Inside the CVMs, the correct node images are running. The node images are identified through the measurements obtained in the previous step. +* The unique ID of the cluster matches the one from your `constellation-state.yaml` file or passed in via `--cluster-id`. + +Once the above properties are verified, you know that you are talking to the right Constellation cluster and it's in a good and trustworthy shape. + +### Custom arguments + +The `verify` command also allows you to verify any Constellation deployment that you have network access to. For this you need the following: + +* The IP address of a running Constellation cluster's [VerificationService](../architecture/microservices.md#verificationservice). The `VerificationService` is exposed via a `NodePort` service using the external IP address of your cluster. Run `kubectl get nodes -o wide` and look for `EXTERNAL-IP`. +* The cluster's *clusterID*. See [cluster identity](../architecture/keys.md#cluster-identity) for more details. +* A `constellation-conf.yaml` file with the expected measurements of the cluster in your working directory. + +For example: + +```shell-session +constellation verify -e 192.0.2.1 --cluster-id Q29uc3RlbGxhdGlvbkRvY3VtZW50YXRpb25TZWNyZXQ= +``` diff --git a/docs/versioned_docs/version-2.18/_media/SLSA-Badge-full-level3.svg b/docs/versioned_docs/version-2.18/_media/SLSA-Badge-full-level3.svg new file mode 100644 index 000000000..7154d4a13 --- /dev/null +++ b/docs/versioned_docs/version-2.18/_media/SLSA-Badge-full-level3.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_fio_azure_bw.png b/docs/versioned_docs/version-2.18/_media/benchmark_fio_azure_bw.png new file mode 100644 index 000000000..a82ebe2d0 Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_fio_azure_bw.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_fio_azure_iops.png b/docs/versioned_docs/version-2.18/_media/benchmark_fio_azure_iops.png new file mode 100644 index 000000000..1723257a8 Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_fio_azure_iops.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_fio_gcp_bw.png b/docs/versioned_docs/version-2.18/_media/benchmark_fio_gcp_bw.png new file mode 100644 index 000000000..4f0ecc94b Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_fio_gcp_bw.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_fio_gcp_iops.png b/docs/versioned_docs/version-2.18/_media/benchmark_fio_gcp_iops.png new file mode 100644 index 000000000..571086da2 Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_fio_gcp_iops.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_net_p2p_azure.png b/docs/versioned_docs/version-2.18/_media/benchmark_net_p2p_azure.png new file mode 100644 index 000000000..9130349c7 Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_net_p2p_azure.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_net_p2p_gcp.png b/docs/versioned_docs/version-2.18/_media/benchmark_net_p2p_gcp.png new file mode 100644 index 000000000..a41557e96 Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_net_p2p_gcp.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_net_p2svc_azure.png b/docs/versioned_docs/version-2.18/_media/benchmark_net_p2svc_azure.png new file mode 100644 index 000000000..d83e17f5a Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_net_p2svc_azure.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_net_p2svc_gcp.png b/docs/versioned_docs/version-2.18/_media/benchmark_net_p2svc_gcp.png new file mode 100644 index 000000000..55916a1de Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_net_p2svc_gcp.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/max_latency.png b/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/max_latency.png new file mode 100644 index 000000000..696250181 Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/max_latency.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/mean_latency.png b/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/mean_latency.png new file mode 100644 index 000000000..3b43298ac Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/mean_latency.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/min_latency.png b/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/min_latency.png new file mode 100644 index 000000000..1046df67e Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/min_latency.png differ diff --git a/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/p99_latency.png b/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/p99_latency.png new file mode 100644 index 000000000..0190118b2 Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/benchmark_vault/5replicas/p99_latency.png differ diff --git a/docs/versioned_docs/version-2.18/_media/concept-constellation.svg b/docs/versioned_docs/version-2.18/_media/concept-constellation.svg new file mode 100644 index 000000000..30d32bf6d --- /dev/null +++ b/docs/versioned_docs/version-2.18/_media/concept-constellation.svg @@ -0,0 +1,460 @@ + + diff --git a/docs/versioned_docs/version-2.18/_media/concept-managed.svg b/docs/versioned_docs/version-2.18/_media/concept-managed.svg new file mode 100644 index 000000000..5645a608f --- /dev/null +++ b/docs/versioned_docs/version-2.18/_media/concept-managed.svg @@ -0,0 +1,591 @@ + + diff --git a/docs/versioned_docs/version-2.18/_media/constellation_oneline.svg b/docs/versioned_docs/version-2.18/_media/constellation_oneline.svg new file mode 100644 index 000000000..4e354958a --- /dev/null +++ b/docs/versioned_docs/version-2.18/_media/constellation_oneline.svg @@ -0,0 +1,52 @@ + + + + + + + + diff --git a/docs/versioned_docs/version-2.18/_media/example-emojivoto.jpg b/docs/versioned_docs/version-2.18/_media/example-emojivoto.jpg new file mode 100644 index 000000000..4be0d5b26 Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/example-emojivoto.jpg differ diff --git a/docs/versioned_docs/version-2.18/_media/example-online-boutique.jpg b/docs/versioned_docs/version-2.18/_media/example-online-boutique.jpg new file mode 100644 index 000000000..026f0d865 Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/example-online-boutique.jpg differ diff --git a/docs/versioned_docs/version-2.18/_media/recovery-gcp-serial-console-link.png b/docs/versioned_docs/version-2.18/_media/recovery-gcp-serial-console-link.png new file mode 100644 index 000000000..eb67f0e99 Binary files /dev/null and b/docs/versioned_docs/version-2.18/_media/recovery-gcp-serial-console-link.png differ diff --git a/docs/versioned_docs/version-2.18/_media/tcb.svg b/docs/versioned_docs/version-2.18/_media/tcb.svg new file mode 100644 index 000000000..e5bcb5b95 --- /dev/null +++ b/docs/versioned_docs/version-2.18/_media/tcb.svg @@ -0,0 +1,535 @@ + + diff --git a/docs/versioned_docs/version-2.18/architecture/attestation.md b/docs/versioned_docs/version-2.18/architecture/attestation.md new file mode 100644 index 000000000..9bd157460 --- /dev/null +++ b/docs/versioned_docs/version-2.18/architecture/attestation.md @@ -0,0 +1,409 @@ +# Attestation + +This page explains Constellation's attestation process and highlights the cornerstones of its trust model. + +## Terms + +The following lists terms and concepts that help to understand the attestation concept of Constellation. + +### Trusted Platform Module (TPM) + +A TPM chip is a dedicated tamper-resistant crypto-processor. +It can securely store artifacts such as passwords, certificates, encryption keys, or *runtime measurements* (more on this below). +When a TPM is implemented in software, it's typically called a *virtual* TPM (vTPM). + +### Runtime measurement + +A runtime measurement is a cryptographic hash of the memory pages of a so called *runtime component*. Runtime components of interest typically include a system's bootloader or OS kernel. + +### Platform Configuration Register (PCR) + +A Platform Configuration Register (PCR) is a memory location in the TPM that has some unique properties. +To store a new value in a PCR, the existing value is extended with a new value as follows: + +``` +PCR[N] = HASHalg( PCR[N] || ArgumentOfExtend ) +``` + +The PCRs are typically used to store runtime measurements. +The new value of a PCR is always an extension of the existing value. +Thus, storing the measurements of multiple components into the same PCR irreversibly links them together. + +### Measured boot + +Measured boot builds on the concept of chained runtime measurements. +Each component in the boot chain loads and measures the next component into the PCR before executing it. +By comparing the resulting PCR values against trusted reference values, the integrity of the entire boot chain and thereby the running system can be ensured. + +### Remote attestation (RA) + +Remote attestation is the process of verifying certain properties of an application or platform, such as integrity and confidentiality, from a remote location. +In the case of a measured boot, the goal is to obtain a signed attestation statement on the PCR values of the boot measurements. +The statement can then be verified and compared to a set of trusted reference values. +This way, the integrity of the platform can be ensured before sharing secrets with it. + +### Confidential virtual machine (CVM) + +Confidential computing (CC) is the protection of data in-use with hardware-based trusted execution environments (TEEs). +With CVMs, TEEs encapsulate entire virtual machines and isolate them against the hypervisor, other VMs, and direct memory access. +After loading the initial VM image into encrypted memory, the hypervisor calls for a secure processor to measure these initial memory pages. +The secure processor locks these pages and generates an attestation report on the initial page measurements. +CVM memory pages are encrypted with a key that resides inside the secure processor, which makes sure only the guest VM can access them. +The attestation report is signed by the secure processor and can be verified using remote attestation via the certificate authority of the hardware vendor. +Such an attestation statement guarantees the confidentiality and integrity of a CVM. + +### Attested TLS (aTLS) + +In a CC environment, attested TLS (aTLS) can be used to establish secure connections between two parties using the remote attestation features of the CC components. + +aTLS modifies the TLS handshake by embedding an attestation statement into the TLS certificate. +Instead of relying on a certificate authority, aTLS uses this attestation statement to establish trust in the certificate. + +The protocol can be used by clients to verify a server certificate, by a server to verify a client certificate, or for mutual verification (mutual aTLS). + +## Overview + +The challenge for Constellation is to lift a CVM's attestation statement to the Kubernetes software layer and make it end-to-end verifiable. +From there, Constellation needs to expand the attestation from a single CVM to the entire cluster. + +The [*JoinService*](microservices.md#joinservice) and [*VerificationService*](microservices.md#verificationservice) are where all runs together. +Internally, the *JoinService* uses remote attestation to securely join CVM nodes to the cluster. +Externally, the *VerificationService* provides an attestation statement for the cluster's CVMs and configuration. + +The following explains the details of both steps. + +## Node attestation + +The idea is that Constellation nodes should have verifiable integrity from the CVM hardware measurement up to the Kubernetes software layer. +The solution is a verifiable boot chain and an integrity-protected runtime environment. + +Constellation uses measured boot within CVMs, measuring each component in the boot process before executing it. +Outside of CC, this is usually implemented via TPMs. +CVM technologies differ in how they implement runtime measurements, but the general concepts are similar to those of a TPM. +For simplicity, TPM terminology like *PCR* is used in the following. + +When a Constellation node image boots inside a CVM, measured boot is used for all stages and components of the boot chain. +This process goes up to the root filesystem. +The root filesystem is mounted read-only with integrity protection. +For the details on the image and boot stages see the [image architecture](../architecture/images.md) documentation. +Any changes to the image will inevitably also change the corresponding PCR values. +To create a node attestation statement, the Constellation image obtains a CVM attestation statement from the hardware. +This includes the runtime measurements and thereby binds the measured boot results to the CVM hardware measurement. + +In addition to the image measurements, Constellation extends a PCR during the [initialization phase](../workflows/create.md) that irrevocably marks the node as initialized. +The measurement is created using the [*clusterID*](../architecture/keys.md#cluster-identity), tying all future attestation statements to this ID. +Thereby, an attestation statement is unique for every cluster and a node can be identified unambiguously as being initialized. + +To verify an attestation, the hardware's signature and a statement are verified first to establish trust in the contained runtime measurements. +If successful, the measurements are verified against the trusted values of the particular Constellation release version. +Finally, the measurement of the *clusterID* can be compared by calculating it with the [master secret](keys.md#master-secret). + +### Runtime measurements + +Constellation uses runtime measurements to implement the measured boot approach. +As stated above, the underlying hardware technology and guest firmware differ in their implementations of runtime measurements. +The following gives a detailed description of the available measurements in the different cloud environments. + +The runtime measurements consist of two types of values: + +* **Measurements produced by the cloud infrastructure and firmware of the CVM**: +These are measurements of closed-source firmware and other values controlled by the cloud provider. +While not being reproducible for the user, some of them can be compared against previously observed values. +Others may change frequently and aren't suitable for verification. +The [signed image measurements](#chain-of-trust) include measurements that are known, previously observed values. + +* **Measurements produced by the Constellation bootloader and boot chain**: +The Constellation Bootloader takes over from the CVM firmware and [measures the rest of the boot chain](images.md). +The Constellation [Bootstrapper](microservices.md#bootstrapper) is the first user mode component that runs in a Constellation image. +It extends PCR registers with the [IDs](keys.md#cluster-identity) of the cluster marking a node as initialized. + +Constellation allows to specify in the config which measurements should be enforced during the attestation process. +Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. +By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. + + + + +Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. + +The vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +The VMs are attested by obtaining signed PCR values over the VM's boot configuration from the TPM and comparing them to a known, good state (measured boot). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | Firmware | AWS | No | +| 1 | Firmware | AWS | No | +| 2 | Firmware | AWS | No | +| 3 | Firmware | AWS | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | AWS, Constellation Bootloader | Yes | +| 5 | Firmware | AWS | No | +| 6 | Firmware | AWS | No | +| 7 | Secure Boot Policy | AWS, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. +This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +It provides a [measured boot](https://docs.microsoft.com/en-us/azure/security/fundamentals/measured-boot-host-attestation#measured-boot) verification that's based on the trusted launch feature of [Trusted Launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | Firmware | Azure | No | +| 1 | Firmware | Azure | No | +| 2 | Firmware | Azure | No | +| 3 | Firmware | Azure | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | Azure, Constellation Bootloader | Yes | +| 5 | Reserved | Azure | No | +| 6 | VM Unique ID | Azure | No | +| 7 | Secure Boot State | Azure, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. +Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. + +The vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +It provides a [launch attestation report](https://cloud.google.com/compute/confidential-vm/docs/monitoring#about_launch_attestation_report_events) that's based on the measured boot feature of [Shielded VMs](https://cloud.google.com/compute/shielded-vm/docs/shielded-vm#measured-boot). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | CVM version and technology | GCP | No | +| 1 | Firmware | GCP | No | +| 2 | Firmware | GCP | No | +| 3 | Firmware | GCP | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | GCP, Constellation Bootloader | Yes | +| 5 | Disk GUID partition table | GCP | No | +| 6 | Disk GUID partition table | GCP | No | +| 7 | GCP Secure Boot Policy | GCP, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +Constellation uses a hypervisor-based vTPM for runtime measurements. + +The vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +The VMs are attested by obtaining signed PCR values over the VM's boot configuration from the TPM and comparing them to a known, good state (measured boot). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | Firmware | STACKIT | No | +| 1 | Firmware | STACKIT | No | +| 2 | Firmware | STACKIT | No | +| 3 | Firmware | STACKIT | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | STACKIT, Constellation Bootloader | Yes | +| 5 | Firmware | STACKIT | No | +| 6 | Firmware | STACKIT | No | +| 7 | Secure Boot Policy | STACKIT, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +### CVM verification + +To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. +For verification of the CVM technology, Constellation may expose additional options in its config file. + + + + +On AWS, AMD SEV-SNP is used to provide runtime encryption to the VMs. +An SEV-SNP attestation report is used to establish trust in the VM. +You may customize certain parameters for verification of the attestation statement using the Constellation config file. + +* TCB versions + + You can set the minimum version numbers of components in the SEV-SNP TCB. + Use the latest versions to enforce that only machines with the most recent firmware updates are allowed to join the cluster. + Alternatively, you can set a lower minimum version to allow slightly out-of-date machines to still be able to join the cluster. + +* AMD Root Key Certificate + + This certificate is the root of trust for verifying the SEV-SNP certificate chain. + +* AMD Signing Key Certificate + + This is the intermediate certificate for verifying the SEV-SNP report's signature. + If it's not specified, the CLI fetches it from the AMD key distribution server. + + + + +On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. +An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. +You may customize certain parameters for verification of the attestation statement using the Constellation config file. + +* TCB versions + + You can set the minimum version numbers of components in the SEV-SNP TCB. + Use the latest versions to enforce that only machines with the most recent firmware updates are allowed to join the cluster. + Alternatively, you can set a lower minimum version to allow slightly out-of-date machines to still be able to join the cluster. + +* AMD Root Key Certificate + + This certificate is the root of trust for verifying the SEV-SNP certificate chain. + +* Firmware Signer + + This config option allows you to specify how the firmware signer should be verified. + More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. + You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. + + + + +On GCP, AMD SEV-SNP is used to provide runtime encryption to the VMs. +An SEV-SNP attestation report is used to establish trust in the VM. +You may customize certain parameters for verification of the attestation statement using the Constellation config file. + +* TCB versions + + You can set the minimum version numbers of components in the SEV-SNP TCB. + Use the latest versions to enforce that only machines with the most recent firmware updates are allowed to join the cluster. + Alternatively, you can set a lower minimum version to allow slightly out-of-date machines to still be able to join the cluster. + +* AMD Root Key Certificate + + This certificate is the root of trust for verifying the SEV-SNP certificate chain. + +* AMD Signing Key Certificate + + This is the intermediate certificate for verifying the SEV-SNP report's signature. + If it's not specified, the CLI fetches it from the AMD key distribution server. + + + + +On STACKIT, AMD SEV-ES is used to provide runtime encryption to the VMs. +The hypervisor-based vTPM is used to establish trust in the VM via [runtime measurements](#runtime-measurements). +There is no additional configuration available for STACKIT. + + + + +## Cluster attestation + +Cluster-facing, Constellation's [*JoinService*](microservices.md#joinservice) verifies each node joining the cluster given the configured ground truth runtime measurements. +User-facing, the [*VerificationService*](microservices.md#verificationservice) provides an interface to verify a node using remote attestation. +By verifying the first node during the [initialization](microservices.md#bootstrapper) and configuring the ground truth measurements that are subsequently enforced by the *JoinService*, the whole cluster is verified in a transitive way. + +### Cluster-facing attestation + +The *JoinService* is provided with the runtime measurements of the whitelisted Constellation image version as the ground truth. +During the initialization and the cluster bootstrapping, each node connects to the *JoinService* using [aTLS](#attested-tls-atls). +During the handshake, the node transmits an attestation statement including its runtime measurements. +The *JoinService* verifies that statement and compares the measurements against the ground truth. +For details of the initialization process check the [microservice descriptions](microservices.md). + +After the initialization, every node updates its runtime measurements with the *clusterID* value, marking it irreversibly as initialized. +When an initialized node tries to join another cluster, its measurements inevitably mismatch the measurements of an uninitialized node and it will be declined. + +### User-facing attestation + +The [*VerificationService*](microservices.md#verificationservice) provides an endpoint for obtaining its hardware-based remote attestation statement, which includes the runtime measurements. +A user can [verify](../workflows/verify-cluster.md) this statement and compare the measurements against the configured ground truth and, thus, verify the identity and integrity of all Constellation components and the cluster configuration. Subsequently, the user knows that the entire cluster is in the expected state and is trustworthy. + +## Putting it all together + +This section puts the aforementioned concepts together and illustrate how trust into a Constellation cluster is established and maintained. + +### CLI and node images + +It all starts with the CLI executable. The CLI is signed by Edgeless Systems. To ensure non-repudiability for CLI releases, Edgeless Systems publishes corresponding signatures to the public ledger of the [sigstore project](https://www.sigstore.dev/). There's a [step-by-step guide](../workflows/verify-cli.md) on how to verify CLI signatures based on sigstore. + +The CLI contains the latest runtime measurements of the Constellation node image for all supported cloud platforms. In case a different version of the node image is to be used, the corresponding runtime measurements can be fetched using the CLI's [fetch-measurements command](../reference/cli.md#constellation-config-fetch-measurements). This command downloads the runtime measurements and the corresponding signature from cdn.confidential.cloud. See for example the following files corresponding to node image v2.16.3: + +* [Measurements](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json) +* [Signature](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json.sig) + +The CLI contains the long-term public key of Edgeless Systems to verify the signature of downloaded runtime measurements. + +### Cluster creation + +When a cluster is [created](../workflows/create.md), the CLI automatically verifies the runtime measurements of the *first node* using remote attestation. Based on this, the CLI and the first node set up a temporary TLS connection. This [aTLS](#attested-tls-atls) connection is used for two things: + +1. The CLI sends the [master secret](../architecture/keys.md#master-secret) of the to-be-created cluster to the CLI. The master secret is generated by the first node. +2. The first node sends a [kubeconfig file](https://www.redhat.com/sysadmin/kubeconfig) with Kubernetes credentials to the CLI. + +After this, the aTLS connection is closed and the first node bootstraps the Kubernetes cluster. All subsequent interactions between the CLI and the cluster go via the [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) server running inside the cluster. The CLI (and other tools like kubectl) use the credentials referenced by the kubeconfig file to authenticate themselves towards the Kubernetes API server and to establish a mTLS connection. + +The CLI connects to the Kubernetes API to write the runtime measurements for the applicable node image to etcd. The JoinService uses these runtime measurements to verify all nodes that join the cluster subsequently. + +### Chain of trust + +In summary, there's a chain of trust based on cryptographic signatures that goes from the user to the cluster via the CLI. This is illustrated in the following diagram. + +```mermaid +flowchart LR + A[User]-- "verifies" -->B[CLI] + B[CLI]-- "verifies" -->C([Runtime measurements]) + D[Edgeless Systems]-- "signs" -->B[CLI] + D[Edgeless Systems]-- "signs" -->C([Runtime measurements]) + B[CLI]-- "verifies (remote attestation)" -->E[First node] + E[First node]-- "verifies (remote attestation)" -->F[Other nodes] + C([Runtime measurements]) -.-> E[First node] + C([Runtime measurements]) -.-> F[Other nodes] +``` + +### Upgrades + +Whenever a cluster is [upgraded](../workflows/upgrade.md) to a new version of the node image, the CLI sends the corresponding runtime measurements via the Kubernetes API server. The new runtime measurements are stored in etcd within the cluster and replace any previous runtime measurements. The new runtime measurements are then used automatically by the JoinService for the verification of new nodes. + +## References + +[^1]: Linux IMA produces runtime measurements of user-space binaries. +However, these measurements aren't deterministic and thus, PCR\[10] can't be compared to a constant value. +Instead, a policy engine must be used to verify the TPM event log against a policy. diff --git a/docs/versioned_docs/version-2.18/architecture/encrypted-storage.md b/docs/versioned_docs/version-2.18/architecture/encrypted-storage.md new file mode 100644 index 000000000..f047fa4a9 --- /dev/null +++ b/docs/versioned_docs/version-2.18/architecture/encrypted-storage.md @@ -0,0 +1,62 @@ +# Encrypted persistent storage + +Confidential VMs provide runtime memory encryption to protect data in use. +In the context of Kubernetes, this is sufficient for the confidentiality and integrity of stateless services. +Consider a front-end web server, for example, that keeps all connection information cached in main memory. +No sensitive data is ever written to an insecure medium. +However, many real-world applications need some form of state or data-lake service that's connected to a persistent storage device and requires encryption at rest. +As described in [Use persistent storage](../workflows/storage.md), cloud service providers (CSPs) use the container storage interface (CSI) to make their storage solutions available to Kubernetes workloads. +These CSI storage solutions often support some sort of encryption. +For example, Google Cloud [encrypts data at rest by default](https://cloud.google.com/security/encryption/default-encryption), without any action required by the customer. + +## Cloud provider-managed encryption + +CSP-managed storage solutions encrypt the data in the cloud backend before writing it physically to disk. +In the context of confidential computing and Constellation, the CSP and its managed services aren't trusted. +Hence, cloud provider-managed encryption protects your data from offline hardware access to physical storage devices. +It doesn't protect it from anyone with infrastructure-level access to the storage backend or a malicious insider in the cloud platform. +Even with "bring your own key" or similar concepts, the CSP performs the encryption process with access to the keys and plaintext data. + +In the security model of Constellation, securing persistent storage and thereby data at rest requires that all cryptographic operations are performed inside a trusted execution environment. +Consequently, using CSP-managed encryption of persistent storage usually isn't an option. + +## Constellation-managed encryption + +Constellation provides CSI drivers for storage solutions in all major clouds with built-in encryption support. +Block storage provisioned by the CSP is [mapped](https://guix.gnu.org/manual/en/html_node/Mapped-Devices.html) using the [dm-crypt](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-crypt.html), and optionally the [dm-integrity](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-integrity.html), kernel modules, before it's formatted and accessed by the Kubernetes workloads. +All cryptographic operations happen inside the trusted environment of the confidential Constellation node. + +Note that for integrity-protected disks, [volume expansion](https://kubernetes.io/blog/2018/07/12/resizing-persistent-volumes-using-kubernetes/) isn't supported. + +By default the driver uses data encryption keys (DEKs) issued by the Constellation [*KeyService*](microservices.md#keyservice). +The DEKs are in turn derived from the Constellation's key encryption key (KEK), which is directly derived from the [master secret](keys.md#master-secret). +This is the recommended mode of operation, and also requires the least amount of setup by the cluster administrator. + +Alternatively, the driver can be configured to use a key management system to store and access KEKs and DEKs. + +Refer to [keys and cryptography](keys.md) for more details on key management in Constellation. + +Once deployed and configured, the CSI driver ensures transparent encryption and integrity of all persistent volumes provisioned via its storage class. +Data at rest is secured without any additional actions required by the developer. + +## Cryptographic algorithms + +This section gives an overview of the libraries, cryptographic algorithms, and their configurations, used in Constellation's CSI drivers. + +### dm-crypt + +To interact with the dm-crypt kernel module, Constellation uses [libcryptsetup](https://gitlab.com/cryptsetup/cryptsetup/). +New devices are formatted as [LUKS2](https://gitlab.com/cryptsetup/LUKS2-docs/-/tree/master) partitions with a sector size of 4096 bytes. +The used key derivation function is [Argon2id](https://datatracker.ietf.org/doc/html/rfc9106) with the [recommended parameters for memory-constrained environments](https://datatracker.ietf.org/doc/html/rfc9106#section-7.4) of 3 iterations and 64 MiB of memory, utilizing 4 parallel threads. +For encryption Constellation uses AES in XTS-Plain64. The key size is 512 bit. + +### dm-integrity + +To interact with the dm-integrity kernel module, Constellation uses [libcryptsetup](https://gitlab.com/cryptsetup/cryptsetup/). +When enabled, the used data integrity algorithm is [HMAC](https://datatracker.ietf.org/doc/html/rfc2104) with SHA256 as the hash function. +The tag size is 32 Bytes. + +## Encrypted S3 object storage + +Constellation comes with a service that you can use to transparently retrofit client-side encryption to existing applications that use S3 (AWS or compatible) for storage. +To learn more, check out the [s3proxy documentation](../workflows/s3proxy.md). diff --git a/docs/versioned_docs/version-2.18/architecture/images.md b/docs/versioned_docs/version-2.18/architecture/images.md new file mode 100644 index 000000000..8a9c51d36 --- /dev/null +++ b/docs/versioned_docs/version-2.18/architecture/images.md @@ -0,0 +1,49 @@ +# Constellation images + +Constellation uses a minimal version of Fedora as the operating system running inside confidential VMs. This Linux distribution is optimized for containers and designed to be stateless. +The Constellation images provide measured boot and an immutable filesystem. + +## Measured boot + +```mermaid +flowchart LR + Firmware --> Bootloader + Bootloader --> uki + subgraph uki[Unified Kernel Image] + Kernel[Kernel] + initramfs[Initramfs] + cmdline[Kernel Command Line] + end + uki --> rootfs[Root Filesystem] +``` + +Measured boot uses a Trusted Platform Module (TPM) to measure every part of the boot process. This allows for verification of the integrity of a running system at any point in time. To ensure correct measurements of every stage, each stage is responsible to measure the next stage before transitioning. + +### Firmware + +With confidential VMs, the firmware is the root of trust and is measured automatically at boot. After initialization, the firmware will load and measure the bootloader before executing it. + +### Bootloader + +The bootloader is the first modifiable part of the boot chain. The bootloader is tasked with loading the kernel, initramfs and setting the kernel command line. The Constellation bootloader measures these components before starting the kernel. + +### initramfs + +The initramfs is a small filesystem loaded to prepare the actual root filesystem. The Constellation initramfs maps the block device containing the root filesystem with [dm-verity](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html). The initramfs then mounts the root filesystem from the mapped block device. + +dm-verity provides integrity checking using a cryptographic hash tree. When a block is read, its integrity is checked by verifying the tree against a trusted root hash. The initramfs reads this root hash from the previously measured kernel command line. Thus, if any block of the root filesystem's device is modified on disk, trying to read the modified block will result in a kernel panic at runtime. + +After mounting the root filesystem, the initramfs will switch over and start the `init` process of the integrity-protected root filesystem. + +## State disk + +In addition to the read-only root filesystem, each Constellation node has a disk for storing state data. +This disk is mounted readable and writable by the initramfs and contains data that should persist across reboots. +Such data can contain sensitive information and, therefore, must be stored securely. +To that end, the state disk is protected by authenticated encryption. +See the section on [keys and encryption](keys.md#storage-encryption) for more information on the cryptographic primitives in use. + +## Kubernetes components + +During initialization, the [*Bootstrapper*](microservices.md#bootstrapper) downloads and verifies the [Kubernetes components](https://kubernetes.io/docs/concepts/overview/components/) as configured by the user. +They're stored on the state partition and can be updated once new releases need to be installed. diff --git a/docs/versioned_docs/version-2.18/architecture/keys.md b/docs/versioned_docs/version-2.18/architecture/keys.md new file mode 100644 index 000000000..553d9d4e2 --- /dev/null +++ b/docs/versioned_docs/version-2.18/architecture/keys.md @@ -0,0 +1,131 @@ +# Key management and cryptographic primitives + +Constellation protects and isolates your cluster and workloads. +To that end, cryptography is the foundation that ensures the confidentiality and integrity of all components. +Evaluating the security and compliance of Constellation requires a precise understanding of the cryptographic primitives and keys used. +The following gives an overview of the architecture and explains the technical details. + +## Confidential VMs + +Confidential VM (CVM) technology comes with hardware and software components for memory encryption, isolation, and remote attestation. +For details on the implementations and cryptographic soundness, refer to the hardware vendors' documentation and advisories. + +## Master secret + +The master secret is the cryptographic material used for deriving the [*clusterID*](#cluster-identity) and the *key encryption key (KEK)* for [storage encryption](#storage-encryption). +It's generated during the bootstrapping of a Constellation cluster. +It can either be managed by [Constellation](#constellation-managed-key-management) or an [external key management system](#user-managed-key-management). +In case of [recovery](#recovery-and-migration), the master secret allows to decrypt the state and recover a Constellation cluster. + +## Cluster identity + +The identity of a Constellation cluster is represented by cryptographic [measurements](attestation.md#runtime-measurements): + +The **base measurements** represent the identity of a valid, uninitialized Constellation node. +They depend on the node image, but are otherwise the same for every Constellation cluster. +On node boot, they're determined using the CVM's attestation mechanism and [measured boot up to the read-only root filesystem](images.md). + +The **clusterID** represents the identity of a single initialized Constellation cluster. +It's derived from the master secret and a cryptographically random salt and unique for every Constellation cluster. +The [Bootstrapper](microservices.md#bootstrapper) measures the *clusterID* into its own PCR before executing any code not measured as part of the *base measurements*. +See [Node attestation](attestation.md#node-attestation) for details. + +The remote attestation statement of a Constellation cluster combines the *base measurements* and the *clusterID* for a verifiable, unspoofable, unique identity. + +## Network encryption + +Constellation encrypts all cluster network communication using the [container network interface (CNI)](https://github.com/containernetworking/cni). +See [network encryption](networking.md) for more details. + +The Cilium agent running on each node establishes a secure [WireGuard](https://www.wireguard.com/) tunnel between it and all other known nodes in the cluster. +Each node creates its own [Curve25519](http://cr.yp.to/ecdh.html) encryption key pair and distributes its public key via Kubernetes. +A node uses another node's public key to decrypt and encrypt traffic from and to Cilium-managed endpoints running on that node. +Connections are always encrypted peer-to-peer using [ChaCha20](http://cr.yp.to/chacha.html) with [Poly1305](http://cr.yp.to/mac.html). +WireGuard implements [forward secrecy with key rotation every 2 minutes](https://lists.zx2c4.com/pipermail/wireguard/2017-December/002141.html). +Cilium supports [key rotation](https://docs.cilium.io/en/stable/security/network/encryption-ipsec/#key-rotation) for the long-term node keys via Kubernetes secrets. + +## Storage encryption + +Constellation supports transparent encryption of persistent storage. +The Linux kernel's device mapper-based encryption features are used to encrypt the data on the block storage level. +Currently, the following primitives are used for block storage encryption: + +* [dm-crypt](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-crypt.html) +* [dm-integrity](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-integrity.html) + +Adding primitives for integrity protection in the CVM attacker model are under active development and will be available in a future version of Constellation. +See [encrypted storage](encrypted-storage.md) for more details. + +As a cluster administrator, when creating a cluster, you can use the Constellation [installation program](orchestration.md) to select one of the following methods for key management: + +* Constellation-managed key management +* User-managed key management + +### Constellation-managed key management + +#### Key material and key derivation + +During the creation of a Constellation cluster, the cluster's master secret is used to derive a KEK. +This means creating two clusters with the same master secret will yield the same KEK. +Any data encryption key (DEK) is derived from the KEK via HKDF. +Note that the master secret is recommended to be unique for every cluster and shouldn't be reused (except in case of [recovering](../workflows/recovery.md) a cluster). + +#### State and storage + +The KEK is derived from the master secret during the initialization. +Subsequently, all other key material is derived from the KEK. +Given the same KEK, any DEK can be derived deterministically from a given identifier. +Hence, there is no need to store DEKs. They can be derived on demand. +After the KEK was derived, it's stored in memory only and never leaves the CVM context. + +#### Availability + +Constellation-managed key management has the same availability as the underlying Kubernetes cluster. +Therefore, the KEK is stored in the [distributed Kubernetes etcd storage](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/) to allow for unexpected but non-fatal (control-plane) node failure. +The etcd storage is backed by the encrypted and integrity protected [state disk](images.md#state-disk) of the nodes. + +#### Recovery + +Constellation clusters can be recovered in the event of a disaster, even when all node machines have been stopped and need to be rebooted. +For details on the process see the [recovery workflow](../workflows/recovery.md). + +### User-managed key management + +User-managed key management is under active development and will be available soon. +In scenarios where constellation-managed key management isn't an option, this mode allows you to keep full control of your keys. +For example, compliance requirements may force you to keep your KEKs in an on-prem key management system (KMS). + +During the creation of a Constellation cluster, you specify a KEK present in a remote KMS. +This follows the common scheme of "bring your own key" (BYOK). +Constellation will support several KMSs for managing the storage and access of your KEK. +Initially, it will support the following KMSs: + +* [AWS KMS](https://aws.amazon.com/kms/) +* [GCP KMS](https://cloud.google.com/security-key-management) +* [Azure Key Vault](https://azure.microsoft.com/en-us/services/key-vault/#product-overview) +* [KMIP-compatible KMS](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=kmip) + +Storing the keys in Cloud KMS of AWS, Azure, or GCP binds the key usage to the particular cloud identity access management (IAM). +In the future, Constellation will support remote attestation-based access policies for Cloud KMS once available. +Note that using a Cloud KMS limits the isolation and protection to the guarantees of the particular offering. + +KMIP support allows you to use your KMIP-compatible on-prem KMS and keep full control over your keys. +This follows the common scheme of "hold your own key" (HYOK). + +The KEK is used to encrypt per-data "data encryption keys" (DEKs). +DEKs are generated to encrypt your data before storing it on persistent storage. +After being encrypted by the KEK, the DEKs are stored on dedicated cloud storage for persistence. +Currently, Constellation supports the following cloud storage options: + +* [AWS S3](https://aws.amazon.com/s3/) +* [GCP Cloud Storage](https://cloud.google.com/storage) +* [Azure Blob Storage](https://azure.microsoft.com/en-us/services/storage/blobs/#overview) + +The DEKs are only present in plaintext form in the encrypted main memory of the CVMs. +Similarly, the cryptographic operations for encrypting data before writing it to persistent storage are performed in the context of the CVMs. + +#### Recovery and migration + +In the case of a disaster, the KEK can be used to decrypt the DEKs locally and subsequently use them to decrypt and retrieve the data. +In case of migration, configuring the same KEK will provide seamless migration of data. +Thus, only the DEK storage needs to be transferred to the new cluster alongside the encrypted data for seamless migration. diff --git a/docs/versioned_docs/version-2.18/architecture/microservices.md b/docs/versioned_docs/version-2.18/architecture/microservices.md new file mode 100644 index 000000000..90bae783b --- /dev/null +++ b/docs/versioned_docs/version-2.18/architecture/microservices.md @@ -0,0 +1,73 @@ +# Microservices + +Constellation takes care of bootstrapping and initializing a Confidential Kubernetes cluster. +During the lifetime of the cluster, it handles day 2 operations such as key management, remote attestation, and updates. +These features are provided by several microservices: + +* The [Bootstrapper](microservices.md#bootstrapper) initializes a Constellation node and bootstraps the cluster +* The [JoinService](microservices.md#joinservice) joins new nodes to an existing cluster +* The [VerificationService](microservices.md#verificationservice) provides remote attestation functionality +* The [KeyService](microservices.md#keyservice) manages Constellation-internal keys + +The relations between microservices are shown in the following diagram: + +```mermaid +flowchart LR + subgraph admin [Admin's machine] + A[Constellation CLI] + end + subgraph img [Constellation OS image] + B[Constellation OS] + C[Bootstrapper] + end + subgraph Kubernetes + D[JoinService] + E[KeyService] + F[VerificationService] + end + A -- deploys --> + B -- starts --> C + C -- deploys --> D + C -- deploys --> E + C -- deploys --> F +``` + +## Bootstrapper + +The *Bootstrapper* is the first microservice launched after booting a Constellation node image. +It sets up that machine as a Kubernetes node and integrates that node into the Kubernetes cluster. +To this end, the *Bootstrapper* first downloads and verifies the [Kubernetes components](https://kubernetes.io/docs/concepts/overview/components/) at the configured versions. +The *Bootstrapper* tries to find an existing cluster and if successful, communicates with the [JoinService](microservices.md#joinservice) to join the node. +Otherwise, it waits for an initialization request to create a new Kubernetes cluster. + +## JoinService + +The *JoinService* runs as [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) on each control-plane node. +New nodes (at cluster start, or later through autoscaling) send a request to the service over [attested TLS (aTLS)](attestation.md#attested-tls-atls). +The *JoinService* verifies the new node's certificate and attestation statement. +If attestation is successful, the new node is supplied with an encryption key from the [*KeyService*](microservices.md#keyservice) for its state disk, and a Kubernetes bootstrap token. + + +```mermaid +sequenceDiagram + participant New node + participant JoinService + New node->>JoinService: aTLS handshake (server side verification) + JoinService-->>New node: # + New node->>+JoinService: IssueJoinTicket(DiskUUID, NodeName, IsControlPlane) + JoinService->>+KeyService: GetDataKey(DiskUUID) + KeyService-->>-JoinService: DiskEncryptionKey + JoinService-->>-New node: DiskEncryptionKey, KubernetesJoinToken, ... +``` + +## VerificationService + +The *VerificationService* runs as DaemonSet on each node. +It provides user-facing functionality for remote attestation during the cluster's lifetime via an endpoint for [verifying the cluster](attestation.md#cluster-attestation). +Read more about the hardware-based [attestation feature](attestation.md) of Constellation and how to [verify](../workflows/verify-cluster.md) a cluster on the client side. + +## KeyService + +The *KeyService* runs as DaemonSet on each control-plane node. +It implements the key management for the [storage encryption keys](keys.md#storage-encryption) in Constellation. These keys are used for the [state disk](images.md#state-disk) of each node and the [transparently encrypted storage](encrypted-storage.md) for Kubernetes. +Depending on wether the [constellation-managed](keys.md#constellation-managed-key-management) or [user-managed](keys.md#user-managed-key-management) mode is used, the *KeyService* holds the key encryption key (KEK) directly or calls an external key management service (KMS) for key derivation respectively. diff --git a/docs/versioned_docs/version-2.18/architecture/networking.md b/docs/versioned_docs/version-2.18/architecture/networking.md new file mode 100644 index 000000000..e9cbdf029 --- /dev/null +++ b/docs/versioned_docs/version-2.18/architecture/networking.md @@ -0,0 +1,22 @@ +# Network encryption + +Constellation encrypts all pod communication using the [container network interface (CNI)](https://github.com/containernetworking/cni). +To that end, Constellation deploys, configures, and operates the [Cilium](https://cilium.io/) CNI plugin. +Cilium provides [transparent encryption](https://docs.cilium.io/en/stable/security/network/encryption) for all cluster traffic using either IPSec or [WireGuard](https://www.wireguard.com/). +Currently, Constellation only supports WireGuard as the encryption engine. +You can read more about the cryptographic soundness of WireGuard [in their white paper](https://www.wireguard.com/papers/wireguard.pdf). + +Cilium is actively working on implementing a feature called [`host-to-host`](https://github.com/cilium/cilium/pull/19401) encryption mode for WireGuard. +With `host-to-host`, all traffic between nodes will be tunneled via WireGuard (host-to-host, host-to-pod, pod-to-host, pod-to-pod). +Until the `host-to-host` feature is released, Constellation enables `pod-to-pod` encryption. +This mode encrypts all traffic between Kubernetes pods using WireGuard tunnels. + +When using Cilium in the default setup but with encryption enabled, there is a [known issue](https://docs.cilium.io/en/v1.12/gettingstarted/encryption/#egress-traffic-to-not-yet-discovered-remote-endpoints-may-be-unencrypted) +that can cause pod-to-pod traffic to be unencrypted. +To mitigate this issue, Constellation adds a *strict* mode to Cilium's `pod-to-pod` encryption. +This mode changes the default behavior of traffic that's destined for an unknown endpoint to not be send out in plaintext, but instead being dropped. +The strict mode distinguishes between traffic that's send to a pod from traffic that's destined for a cluster-external endpoint by considering the pod's CIDR range. + +Traffic originating from hosts isn't encrypted yet. +This mainly includes health checks from Kubernetes API server. +Also, traffic proxied over the API server via e.g. `kubectl port-forward` isn't encrypted. diff --git a/docs/versioned_docs/version-2.18/architecture/observability.md b/docs/versioned_docs/version-2.18/architecture/observability.md new file mode 100644 index 000000000..0f4daffd4 --- /dev/null +++ b/docs/versioned_docs/version-2.18/architecture/observability.md @@ -0,0 +1,74 @@ +# Observability + +In Kubernetes, observability is the ability to gain insight into the behavior and performance of applications. +It helps identify and resolve issues more effectively, ensuring stability and performance of Kubernetes workloads, reducing downtime and outages, and improving efficiency. +The "three pillars of observability" are logs, metrics, and traces. + +In the context of Confidential Computing, observability is a delicate subject and needs to be applied such that it doesn't leak any sensitive information. +The following gives an overview of where and how you can apply standard observability tools in Constellation. + +## Cloud resource monitoring + +While inaccessible, Constellation's nodes are still visible as black box VMs to the hypervisor. +Resource consumption, such as memory and CPU utilization, can be monitored from the outside and observed via the cloud platforms directly. +Similarly, other resources, such as storage and network and their respective metrics, are visible via the cloud platform. + +## Metrics + +Metrics are numeric representations of data measured over intervals of time. They're essential for understanding system health and gaining insights using telemetry signals. + +By default, Constellation exposes the [metrics for Kubernetes system components](https://kubernetes.io/docs/concepts/cluster-administration/system-metrics/) inside the cluster. +Similarly, the [etcd metrics](https://etcd.io/docs/v3.5/metrics/) endpoints are exposed inside the cluster. +These [metrics endpoints can be disabled](https://kubernetes.io/docs/concepts/cluster-administration/system-metrics/#disabling-metrics). + +You can collect these cluster-internal metrics via tools such as [Prometheus](https://prometheus.io/) or the [Elastic Stack](https://www.elastic.co/de/elastic-stack/). + +Constellation's CNI Cilium also supports [metrics via Prometheus endpoints](https://docs.cilium.io/en/latest/observability/metrics/). +However, in Constellation, they're disabled by default and must be enabled first. + +## Logs + +Logs represent discrete events that usually describe what's happening with your service. +The payload is an actual message emitted from your system along with a metadata section containing a timestamp, labels, and tracking identifiers. + +### System logs + +Detailed system-level logs are accessible via `/var/log` and [journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) on the nodes directly. +They can be collected from there, for example, via [Filebeat and Logstash](https://www.elastic.co/guide/en/beats/filebeat/current/logstash-output.html), which are tools of the [Elastic Stack](https://www.elastic.co/de/elastic-stack/). + +In case of an error during the initialization, the CLI automatically collects the [Bootstrapper](./microservices.md#bootstrapper) logs and returns these as a file for [troubleshooting](../workflows/troubleshooting.md). Here is an example of such an event: + +```shell-session +Cluster initialization failed. This error is not recoverable. +Terminate your cluster and try again. +Fetched bootstrapper logs are stored in "constellation-cluster.log" +``` + +### Kubernetes logs + +Constellation supports the [Kubernetes logging architecture](https://kubernetes.io/docs/concepts/cluster-administration/logging/). +By default, logs are written to the nodes' encrypted state disks. +These include the Pod and container logs and the [system component logs](https://kubernetes.io/docs/concepts/cluster-administration/logging/#system-component-logs). + +[Constellation services](microservices.md) run as Pods inside the `kube-system` namespace and use the standard container logging mechanism. +The same applies for the [Cilium Pods](https://docs.cilium.io/en/latest/operations/troubleshooting/#logs). + +You can collect logs from within the cluster via tools such as [Fluentd](https://github.com/fluent/fluentd), [Loki](https://github.com/grafana/loki), or the [Elastic Stack](https://www.elastic.co/de/elastic-stack/). + +## Traces + +Modern systems are implemented as interconnected complex and distributed microservices. Understanding request flows and system communications is challenging, mainly because all systems in a chain need to be modified to propagate tracing information. Distributed tracing is a new approach to increasing observability and understanding performance bottlenecks. A trace represents consecutive events that reflect an end-to-end request path in a distributed system. + +Constellation supports [traces for Kubernetes system components](https://kubernetes.io/docs/concepts/cluster-administration/system-traces/). +By default, they're disabled and need to be enabled first. + +Similarly, Cilium can be enabled to [export traces](https://cilium.io/use-cases/metrics-export/). + +You can collect these traces via tools such as [Jaeger](https://www.jaegertracing.io/) or [Zipkin](https://zipkin.io/). + +## Integrations + +Platforms and SaaS solutions such as Datadog, logz.io, Dynatrace, or New Relic facilitate the observability challenge for Kubernetes and provide all-in-one SaaS solutions. +They install agents into the cluster that collect metrics, logs, and tracing information and upload them into the data lake of the platform. +Technically, the agent-based approach is compatible with Constellation, and attaching these platforms is straightforward. +However, you need to evaluate if the exported data might violate Constellation's compliance and privacy guarantees by uploading them to a third-party platform. diff --git a/docs/versioned_docs/version-2.18/architecture/orchestration.md b/docs/versioned_docs/version-2.18/architecture/orchestration.md new file mode 100644 index 000000000..3c8d529e7 --- /dev/null +++ b/docs/versioned_docs/version-2.18/architecture/orchestration.md @@ -0,0 +1,83 @@ +# Orchestrating Constellation clusters + +You can use the CLI to create a cluster on the supported cloud platforms. +The CLI provisions the resources in your cloud environment and initiates the initialization of your cluster. +It uses a set of parameters and an optional configuration file to manage your cluster installation. +The CLI is also used for updating your cluster. + +## Workspaces + +Each Constellation cluster has an associated *workspace*. +The workspace is where data such as the Constellation state and config files are stored. +Each workspace is associated with a single cluster and configuration. +The CLI stores state in the local filesystem making the current directory the active workspace. +Multiple clusters require multiple workspaces, hence, multiple directories. +Note that every operation on a cluster always has to be performed from the directory associated with its workspace. + +You may copy files from the workspace to other locations, +but you shouldn't move or delete them while the cluster is still being used. +The Constellation CLI takes care of managing the workspace. +Only when a cluster was terminated, and you are sure the files aren't needed anymore, should you remove a workspace. + +## Cluster creation process + +To allow for fine-grained configuration of your cluster and cloud environment, Constellation supports an extensive configuration file with strong defaults. [Generating the configuration file](../workflows/config.md) is typically the first thing you do in the workspace. + +Altogether, the following files are generated during the creation of a Constellation cluster and stored in the current workspace: + +* a configuration file +* a state file +* a Base64-encoded master secret +* [Terraform artifacts](../reference/terraform.md), stored in subdirectories +* a Kubernetes `kubeconfig` file. + +After the initialization of your cluster, the CLI will provide you with a Kubernetes `kubeconfig` file. +This file grants you access to your Kubernetes cluster and configures the [kubectl](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) tool. +In addition, the cluster's [identifier](orchestration.md#post-installation-configuration) is returned and stored in the state file. + +### Creation process details + +1. The CLI `apply` command first creates the confidential VM (CVM) resources in your cloud environment and configures the network +2. Each CVM boots the Constellation node image and measures every component in the boot chain +3. The first microservice launched in each node is the [*Bootstrapper*](microservices.md#bootstrapper) +4. The *Bootstrapper* waits until it either receives an initialization request or discovers an initialized cluster +5. The CLI then connects to the *Bootstrapper* of a selected node, sends the configuration, and initiates the initialization of the cluster +6. The *Bootstrapper* of **that** node [initializes the Kubernetes cluster](microservices.md#bootstrapper) and deploys the other Constellation [microservices](microservices.md) including the [*JoinService*](microservices.md#joinservice) +7. Subsequently, the *Bootstrappers* of the other nodes discover the initialized cluster and send join requests to the *JoinService* +8. As part of the join request each node includes an attestation statement of its boot measurements as authentication +9. The *JoinService* verifies the attestation statements and joins the nodes to the Kubernetes cluster +10. This process is repeated for every node joining the cluster later (e.g., through autoscaling) + +## Post-installation configuration + +Post-installation the CLI provides a configuration for [accessing the cluster using the Kubernetes API](https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/). +The `kubeconfig` file provides the credentials and configuration for connecting and authenticating to the API server. +Once configured, orchestrate the Kubernetes cluster via `kubectl`. + +After the initialization, the CLI will present you with a couple of tokens: + +* The [*master secret*](keys.md#master-secret) (stored in the `constellation-mastersecret.json` file by default) +* The [*clusterID*](keys.md#cluster-identity) of your cluster in Base64 encoding + +You can read more about these values and their meaning in the guide on [cluster identity](keys.md#cluster-identity). + +The *master secret* must be kept secret and can be used to [recover your cluster](../workflows/recovery.md). +Instead of managing this secret manually, you can [use your key management solution of choice](keys.md#user-managed-key-management) with Constellation. + +The *clusterID* uniquely identifies a cluster and can be used to [verify your cluster](../workflows/verify-cluster.md). + +## Upgrades + +Constellation images and microservices may need to be upgraded to new versions during the lifetime of a cluster. +Constellation implements a rolling update mechanism ensuring no downtime of the control or data plane. +You can upgrade a Constellation cluster with a single operation by using the CLI. +For step-by-step instructions on how to do this, refer to [Upgrade your cluster](../workflows/upgrade.md). + +### Attestation of upgrades + +With every new image, corresponding measurements are released. +During an update procedure, the CLI provides new measurements to the [JoinService](microservices.md#joinservice) securely. +New measurements for an updated image are automatically pulled and verified by the CLI following the [supply chain security concept](attestation.md#chain-of-trust) of Constellation. +The [attestation section](attestation.md#cluster-facing-attestation) describes in detail how these measurements are then used by the JoinService for the attestation of nodes. + + diff --git a/docs/versioned_docs/version-2.18/architecture/overview.md b/docs/versioned_docs/version-2.18/architecture/overview.md new file mode 100644 index 000000000..386f93b2f --- /dev/null +++ b/docs/versioned_docs/version-2.18/architecture/overview.md @@ -0,0 +1,30 @@ +# Overview + +Constellation is a cloud-based confidential orchestration platform. +The foundation of Constellation is Kubernetes and therefore shares the same technology stack and architecture principles. +To learn more about Constellation and Kubernetes, see [product overview](../overview/product.md). + +## About orchestration and updates + +As a cluster administrator, you can use the [Constellation CLI](orchestration.md) to install and deploy a cluster. +Updates are provided in accordance with the [support policy](versions.md). + +## About microservices and attestation + +Constellation manages the nodes and network in your cluster. All nodes are bootstrapped by the [*Bootstrapper*](microservices.md#bootstrapper). They're verified and authenticated by the [*JoinService*](microservices.md#joinservice) before being added to the cluster and the network. Finally, the entire cluster can be verified via the [*VerificationService*](microservices.md#verificationservice) using [remote attestation](attestation.md). + +## About node images and verified boot + +Constellation comes with operating system images for Kubernetes control-plane and worker nodes. +They're highly optimized for running containerized workloads and specifically prepared for running inside confidential VMs. +You can learn more about [the images](images.md) and how verified boot ensures their integrity during boot and beyond. + +## About key management and cryptographic primitives + +Encryption of data at-rest, in-transit, and in-use is the fundamental building block for confidential computing and Constellation. Learn more about the [keys and cryptographic primitives](keys.md) used in Constellation, [encrypted persistent storage](encrypted-storage.md), and [network encryption](networking.md). + +## About observability + +Observability in Kubernetes refers to the capability to troubleshoot issues using telemetry signals such as logs, metrics, and traces. +In the realm of Confidential Computing, it's crucial that observability aligns with confidentiality, necessitating careful implementation. +Learn more about the [observability capabilities in Constellation](./observability.md). diff --git a/docs/versioned_docs/version-2.18/architecture/versions.md b/docs/versioned_docs/version-2.18/architecture/versions.md new file mode 100644 index 000000000..30d9d28e2 --- /dev/null +++ b/docs/versioned_docs/version-2.18/architecture/versions.md @@ -0,0 +1,21 @@ +# Versions and support policy + +All components of Constellation use a three-digit version number of the form `v..`. +The components are released in lock step, usually on the first Tuesday of every month. This release primarily introduces new features, but may also include security or performance improvements. The `MINOR` version will be incremented as part of this release. + +Additional `PATCH` releases may be created on demand, to fix security issues or bugs before the next `MINOR` release window. + +New releases are published on [GitHub](https://github.com/edgelesssys/constellation/releases). + +## Kubernetes support policy + +Constellation is aligned to the [version support policy of Kubernetes](https://kubernetes.io/releases/version-skew-policy/#supported-versions), and therefore usually supports the most recent three minor versions. +When a new minor version of Kubernetes is released, support is added to the next Constellation release, and that version then supports four Kubernetes versions. +Subsequent Constellation releases drop support for the oldest (and deprecated) Kubernetes version. + +The following Kubernetes versions are currently supported: + + +* v1.28.13 +* v1.29.8 +* v1.30.4 diff --git a/docs/versioned_docs/version-2.18/getting-started/examples.md b/docs/versioned_docs/version-2.18/getting-started/examples.md new file mode 100644 index 000000000..fded84980 --- /dev/null +++ b/docs/versioned_docs/version-2.18/getting-started/examples.md @@ -0,0 +1,6 @@ +# Examples + +After you [installed the CLI](install.md) and [created your first cluster](first-steps.md), you're ready to deploy applications. Why not start with one of the following examples? +* [Emojivoto](examples/emojivoto.md): a simple but fun web application +* [Online Boutique](examples/online-boutique.md): an e-commerce demo application by Google consisting of 11 separate microservices +* [Horizontal Pod Autoscaling](examples/horizontal-scaling.md): an example demonstrating Constellation's autoscaling capabilities diff --git a/docs/versioned_docs/version-2.18/getting-started/examples/emojivoto.md b/docs/versioned_docs/version-2.18/getting-started/examples/emojivoto.md new file mode 100644 index 000000000..2bbe27917 --- /dev/null +++ b/docs/versioned_docs/version-2.18/getting-started/examples/emojivoto.md @@ -0,0 +1,22 @@ +# Emojivoto +[Emojivoto](https://github.com/BuoyantIO/emojivoto) is a simple and fun application that's well suited to test the basic functionality of your cluster. + + + +emojivoto - Web UI + + + +1. Deploy the application: + ```bash + kubectl apply -k github.com/BuoyantIO/emojivoto/kustomize/deployment + ``` +2. Wait until it becomes available: + ```bash + kubectl wait --for=condition=available --timeout=60s -n emojivoto --all deployments + ``` +3. Forward the web service to your machine: + ```bash + kubectl -n emojivoto port-forward svc/web-svc 8080:80 + ``` +4. Visit [http://localhost:8080](http://localhost:8080) diff --git a/docs/versioned_docs/version-2.18/getting-started/examples/filestash-s3proxy.md b/docs/versioned_docs/version-2.18/getting-started/examples/filestash-s3proxy.md new file mode 100644 index 000000000..b9a394256 --- /dev/null +++ b/docs/versioned_docs/version-2.18/getting-started/examples/filestash-s3proxy.md @@ -0,0 +1,107 @@ + +# Deploying Filestash + +Filestash is a web frontend for different storage backends, including S3. +It's a useful application to showcase s3proxy in action. + +1. Deploy s3proxy as described in [Deployment](../../workflows/s3proxy.md#deployment). +2. Create a deployment file for Filestash with one pod: + +```sh +cat << EOF > "deployment-filestash.yaml" +apiVersion: apps/v1 +kind: Deployment +metadata: + name: filestash +spec: + replicas: 1 + selector: + matchLabels: + app: filestash + template: + metadata: + labels: + app: filestash + spec: + hostAliases: + - ip: $(kubectl get svc s3proxy-service -o=jsonpath='{.spec.clusterIP}') + hostnames: + - "s3.us-east-1.amazonaws.com" + - "s3.us-east-2.amazonaws.com" + - "s3.us-west-1.amazonaws.com" + - "s3.us-west-2.amazonaws.com" + - "s3.eu-north-1.amazonaws.com" + - "s3.eu-south-1.amazonaws.com" + - "s3.eu-south-2.amazonaws.com" + - "s3.eu-west-1.amazonaws.com" + - "s3.eu-west-2.amazonaws.com" + - "s3.eu-west-3.amazonaws.com" + - "s3.eu-central-1.amazonaws.com" + - "s3.eu-central-2.amazonaws.com" + - "s3.ap-northeast-1.amazonaws.com" + - "s3.ap-northeast-2.amazonaws.com" + - "s3.ap-northeast-3.amazonaws.com" + - "s3.ap-east-1.amazonaws.com" + - "s3.ap-southeast-1.amazonaws.com" + - "s3.ap-southeast-2.amazonaws.com" + - "s3.ap-southeast-3.amazonaws.com" + - "s3.ap-southeast-4.amazonaws.com" + - "s3.ap-south-1.amazonaws.com" + - "s3.ap-south-2.amazonaws.com" + - "s3.me-south-1.amazonaws.com" + - "s3.me-central-1.amazonaws.com" + - "s3.il-central-1.amazonaws.com" + - "s3.af-south-1.amazonaws.com" + - "s3.ca-central-1.amazonaws.com" + - "s3.sa-east-1.amazonaws.com" + containers: + - name: filestash + image: machines/filestash:latest + ports: + - containerPort: 8334 + volumeMounts: + - name: ca-cert + mountPath: /etc/ssl/certs/kube-ca.crt + subPath: kube-ca.crt + volumes: + - name: ca-cert + secret: + secretName: s3proxy-tls + items: + - key: ca.crt + path: kube-ca.crt +EOF +``` + +The pod spec includes the `hostAliases` key, which adds an entry to the pod's `/etc/hosts`. +The entry forwards all requests for any of the currently defined AWS regions to the Kubernetes service `s3proxy-service`. +If you followed the s3proxy [Deployment](../../workflows/s3proxy.md#deployment) guide, this service points to a s3proxy pod. + +The deployment specifies all regions explicitly to prevent accidental data leaks. +If one of your buckets were located in a region that's not part of the `hostAliases` key, traffic towards those buckets would not be redirected to s3proxy. +Similarly, if you want to exclude data for specific regions from going through s3proxy you can remove those regions from the deployment. + +The spec also includes a volume mount for the TLS certificate and adds it to the pod's certificate trust store. +The volume is called `ca-cert`. +The key `ca.crt` of that volume is mounted to `/etc/ssl/certs/kube-ca.crt`, which is the default certificate trust store location for that container's OpenSSL library. +Not adding the CA certificate will result in TLS authentication errors. + +3. Apply the file: `kubectl apply -f deployment-filestash.yaml` + +Afterward, you can use a port forward to access the Filestash pod: +`kubectl port-forward pod/$(kubectl get pod --selector='app=filestash' -o=jsonpath='{.items[*].metadata.name}') 8334:8334` + +4. After browsing to `localhost:8443`, Filestash will ask you to set an administrator password. +After setting it, you can directly leave the admin area by clicking the blue cloud symbol in the top left corner. +Subsequently, you can select S3 as storage backend and enter your credentials. +This will bring you to an overview of your buckets. +If you want to deploy Filestash in production, take a look at its [documentation](https://www.filestash.app/docs/). + +5. To see the logs of s3proxy intercepting requests made to S3, run: `kubectl logs -f pod/$(kubectl get pod --selector='app=s3proxy' -o=jsonpath='{.items[*].metadata.name}')` +Look out for log messages labeled `intercepting`. +There is one such log message for each message that's encrypted, decrypted, or blocked. + +6. Once you have uploaded a file with Filestash, you should be able to view the file in Filestash. +However, if you go to the AWS S3 [Web UI](https://s3.console.aws.amazon.com/s3/home) and download the file you just uploaded in Filestash, you won't be able to read it. +Another way to spot encrypted files without downloading them is to click on a file, scroll to the Metadata section, and look for the header named `x-amz-meta-constellation-encryption`. +This header holds the encrypted data encryption key of the object and is only present on objects that are encrypted by s3proxy. diff --git a/docs/versioned_docs/version-2.18/getting-started/examples/horizontal-scaling.md b/docs/versioned_docs/version-2.18/getting-started/examples/horizontal-scaling.md new file mode 100644 index 000000000..dfaf9e742 --- /dev/null +++ b/docs/versioned_docs/version-2.18/getting-started/examples/horizontal-scaling.md @@ -0,0 +1,98 @@ +# Horizontal Pod Autoscaling +This example demonstrates Constellation's autoscaling capabilities. It's based on the Kubernetes [HorizontalPodAutoscaler Walkthrough](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). During the following steps, Constellation will spawn new VMs on demand, verify them, add them to the cluster, and delete them again when the load has settled down. + +## Requirements +The cluster needs to be initialized with Kubernetes 1.23 or later. In addition, [autoscaling must be enabled](../../workflows/scale.md) to enable Constellation to assign new nodes dynamically. + +Just for this example specifically, the cluster should have as few worker nodes in the beginning as possible. Start with a small cluster with only *one* low-powered node for the control-plane node and *one* low-powered worker node. + +:::info +We tested the example using instances of types `Standard_DC4as_v5` on Azure and `n2d-standard-4` on GCP. +::: + +## Setup + +1. Install the Kubernetes Metrics Server: + ```bash + kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml + ``` + +2. Deploy the HPA example server that's supposed to be scaled under load. + + This manifest is similar to the one from the Kubernetes HPA walkthrough, but with increased CPU limits and requests to facilitate the triggering of node scaling events. + ```bash + cat < + +Online Boutique - Web UI + + + +1. Create a namespace: + ```bash + kubectl create ns boutique + ``` +2. Deploy the application: + ```bash + kubectl apply -n boutique -f https://github.com/GoogleCloudPlatform/microservices-demo/raw/main/release/kubernetes-manifests.yaml + ``` +3. Wait for all services to become available: + ```bash + kubectl wait --for=condition=available --timeout=300s -n boutique --all deployments + ``` +4. Get the frontend's external IP address: + ```shell-session + $ kubectl get service frontend-external -n boutique | awk '{print $4}' + EXTERNAL-IP + + ``` + (`` is a placeholder for the IP assigned by your CSP.) +5. Enter the IP from the result in your browser to browse the online shop. diff --git a/docs/versioned_docs/version-2.18/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.18/getting-started/first-steps-local.md new file mode 100644 index 000000000..98f0302de --- /dev/null +++ b/docs/versioned_docs/version-2.18/getting-started/first-steps-local.md @@ -0,0 +1,277 @@ +# First steps with a local cluster + +A local cluster lets you deploy and test Constellation without a cloud subscription. +You have two options: + +* Use MiniConstellation to automatically deploy a two-node cluster. +* For more fine-grained control, create the cluster using the QEMU provider. + +Both options use virtualization to create a local cluster with control-plane nodes and worker nodes. They **don't** require hardware with Confidential VM (CVM) support. For attestation, they currently use a software-based vTPM provided by KVM/QEMU. + +You need an x64 machine with a Linux OS. +You can use a VM, but it needs nested virtualization. + +## Prerequisites + +* Machine requirements: + * An x86-64 CPU with at least 4 cores (6 cores are recommended) + * At least 4 GB RAM (6 GB are recommended) + * 20 GB of free disk space + * Hardware virtualization enabled in the BIOS/UEFI (often referred to as Intel VT-x or AMD-V/SVM) / nested-virtualization support when using a VM +* Software requirements: + * Linux OS with [KVM kernel module](https://www.linux-kvm.org/page/Main_Page) + * Recommended: Ubuntu 22.04 LTS + * [Docker](https://docs.docker.com/engine/install/) + * [xsltproc](https://gitlab.gnome.org/GNOME/libxslt/-/wikis/home) + * (Optional) [virsh](https://www.libvirt.org/manpages/virsh.html) to observe and access your nodes + +### Software installation on Ubuntu + +```bash +# install Docker +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null +sudo apt update +sudo apt install docker-ce +# install other dependencies +sudo apt install xsltproc +sudo snap install kubectl --classic +# install Constellation CLI +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-linux-amd64 +sudo install constellation-linux-amd64 /usr/local/bin/constellation +# do not drop forwarded packages +sudo iptables -P FORWARD ACCEPT +``` + +## Create a cluster + + + + + +With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). + + +:::caution + +MiniConstellation has specific soft- and hardware requirements such as a Linux OS running on an x86-64 CPU. Pay attention to all [prerequisites](#prerequisites) when setting up. + +::: + +:::note + +Since MiniConstellation runs on your local system, cloud features such as load balancing, +attaching persistent storage, or autoscaling aren't available. + +::: + +The following creates your MiniConstellation cluster (may take up to 10 minutes to complete): + +```bash +constellation mini up +``` + +This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. +All `constellation` commands concerning this cluster need to be issued from this directory. + + + + +With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. + +:::caution + +Constellation on QEMU has specific soft- and hardware requirements such as a Linux OS running on an x86-64 CPU. Pay attention to all [prerequisites](#prerequisites) when setting up. + +::: + +:::note + +Since Constellation on QEMU runs on your local system, cloud features such as load balancing, +attaching persistent storage, or autoscaling aren't available. + +::: + +1. To set up your local cluster, you need to create a configuration file for Constellation first. + + ```bash + constellation config generate qemu + ``` + + This creates a [configuration file](../workflows/config.md) for QEMU called `constellation-conf.yaml`. After that, your current folder also becomes your [workspace](../architecture/orchestration.md#workspaces). All `constellation` commands for your cluster need to be executed from this directory. + +2. Now you can create your cluster and its nodes. `constellation apply` uses the options set in `constellation-conf.yaml`. + + ```bash + constellation apply -y + ``` + + The Output should look like the following: + + ```shell-session + $ constellation apply -y + Checking for infrastructure changes + The following Constellation cluster will be created: + 3 control-plane nodes of type 2-vCPUs will be created. + 1 worker node of type 2-vCPUs will be created. + Creating + Cloud infrastructure created successfully. + Your Constellation master secret was successfully written to ./constellation-mastersecret.json + Connecting + Initializing cluster + Installing Kubernetes components + Your Constellation cluster was successfully initialized. + + Constellation cluster identifier g6iMP5wRU1b7mpOz2WEISlIYSfdAhB0oNaOg6XEwKFY= + Kubernetes configuration constellation-admin.conf + + You can now connect to your cluster by executing: + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + + The cluster's identifier will be different in your output. + Keep `constellation-mastersecret.json` somewhere safe. + This will allow you to [recover your cluster](../workflows/recovery.md) in case of a disaster. + + :::info + + Depending on your setup, `constellation apply` may take 10+ minutes to complete. + + ::: + +3. Configure kubectl + + ```bash + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + + + + +## Connect to the cluster + +Your cluster initially consists of a single control-plane node: + +```shell-session +$ kubectl get nodes +NAME STATUS ROLES AGE VERSION +control-plane-0 Ready control-plane 66s v1.24.6 +``` + +Additional nodes will request to join the cluster shortly. Before each additional node is allowed to join the cluster, its state is verified using remote attestation by the [JoinService](../architecture/microservices.md#joinservice). +If verification passes successfully, the new node receives keys and certificates to join the cluster. + +You can follow this process by viewing the logs of the JoinService: + +```shell-session +$ kubectl logs -n kube-system daemonsets/join-service -f +{"level":"INFO","ts":"2022-10-14T09:32:20Z","caller":"cmd/main.go:48","msg":"Constellation Node Join Service","version":"2.1.0","cloudProvider":"qemu"} +{"level":"INFO","ts":"2022-10-14T09:32:20Z","logger":"validator","caller":"watcher/validator.go:96","msg":"Updating expected measurements"} +... +``` + +Once all nodes have joined your cluster, it may take a couple of minutes for all resources to become available. +You can check on the state of your cluster by running the following: + +```shell-session +$ kubectl get nodes +NAME STATUS ROLES AGE VERSION +control-plane-0 Ready control-plane 2m59s v1.24.6 +worker-0 Ready 32s v1.24.6 +``` + +## Deploy a sample application + +1. Deploy the [emojivoto app](https://github.com/BuoyantIO/emojivoto) + + ```bash + kubectl apply -k github.com/BuoyantIO/emojivoto/kustomize/deployment + ``` + +2. Expose the frontend service locally + + ```bash + kubectl wait --for=condition=available --timeout=60s -n emojivoto --all deployments + kubectl -n emojivoto port-forward svc/web-svc 8080:80 & + curl http://localhost:8080 + kill %1 + ``` + +## Terminate your cluster + + + + +Once you are done, you can clean up the created resources using the following command: + +```bash +constellation mini down +``` + +This will destroy your cluster and clean up your workspace. +The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. + + + + +Once you are done, you can clean up the created resources using the following command: + +```bash +constellation terminate +``` + +This should give the following output: + +```shell-session +$ constellation terminate +You are about to terminate a Constellation cluster. +All of its associated resources will be DESTROYED. +This action is irreversible and ALL DATA WILL BE LOST. +Do you want to continue? [y/n]: +``` + +Confirm with `y` to terminate the cluster: + +```shell-session +Terminating ... +Your Constellation cluster was terminated successfully. +``` + +This will destroy your cluster and clean up your workspace. +The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. + + + + +## Troubleshooting + +Make sure to use the [latest release](https://github.com/edgelesssys/constellation/releases/latest) and check out the [known issues](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22). + +### VMs have no internet access / CLI remains in "Initializing cluster" state + +`iptables` rules may prevent your VMs from accessing the internet. +Make sure your rules aren't dropping forwarded packages. + +List your rules: + +```bash +sudo iptables -S +``` + +The output may look similar to the following: + +```shell-session +-P INPUT ACCEPT +-P FORWARD DROP +-P OUTPUT ACCEPT +-N DOCKER +-N DOCKER-ISOLATION-STAGE-1 +-N DOCKER-ISOLATION-STAGE-2 +-N DOCKER-USER +``` + +If your `FORWARD` chain is set to `DROP`, you need to update your rules: + +```bash +sudo iptables -P FORWARD ACCEPT +``` diff --git a/docs/versioned_docs/version-2.18/getting-started/first-steps.md b/docs/versioned_docs/version-2.18/getting-started/first-steps.md new file mode 100644 index 000000000..128ac2849 --- /dev/null +++ b/docs/versioned_docs/version-2.18/getting-started/first-steps.md @@ -0,0 +1,229 @@ +# First steps with Constellation + +The following steps guide you through the process of creating a cluster and deploying a sample app. This example assumes that you have successfully [installed and set up Constellation](install.md), +and have access to a cloud subscription. + +:::tip +If you don't have a cloud subscription, you can also set up a [local Constellation cluster using virtualization](../getting-started/first-steps-local.md) for testing. +::: + +:::note +If you encounter any problem with the following steps, make sure to use the [latest release](https://github.com/edgelesssys/constellation/releases/latest) and check out the [known issues](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22). +::: + +## Create a cluster + +1. Create the [configuration file](../workflows/config.md) and state file for your cloud provider. If you are following the steps of this guide, there is no need to edit the file. + + + + + ```bash + constellation config generate aws + ``` + + + + + ```bash + constellation config generate azure + ``` + + + + + ```bash + constellation config generate gcp + ``` + + + + + ```bash + constellation config generate stackit + ``` + + + + +2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). + + + + + ```bash + constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config + ``` + + This command creates IAM configuration for the AWS zone `us-east-2a` using the prefix `constellTest` for all named resources being created. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. + + Depending on the attestation variant selected on config generation, different regions are available. + AMD SEV-SNP machines (requires the default attestation variant `awsSEVSNP`) are currently available in the following regions: + * `eu-west-1` + * `us-east-2` + + You can find a list of regions that support AMD SEV-SNP in [AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/snp-requirements.html). + + NitroTPM machines (requires the attestation variant `awsNitroTPM`) are available in all regions. + Constellation OS images are currently replicated to the following regions: + * `eu-central-1` + * `eu-west-1` + * `eu-west-3` + * `us-east-2` + * `ap-south-1` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+AWS+image+region:+xx-xxxx-x). + + You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). + + + + + ```bash + constellation iam create azure --subscriptionID 00000000-0000-0000-0000-000000000000 --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config + ``` + + This command creates IAM configuration on the Azure region `westus` creating a new resource group `constellTest` and a new service principal `spTest`. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. + + CVMs are available in several Azure regions. Constellation OS images are currently replicated to the following: + + * `germanywestcentral` + * `westus` + * `eastus` + * `northeurope` + * `westeurope` + * `southeastasia` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+Azure+image+region:+xx-xxxx-x). + + You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). + + + + + ```bash + constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config + ``` + + This command creates IAM configuration in the GCP project `yourproject-12345` on the GCP zone `europe-west2-a` creating a new service account `constell-test`. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. + + Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. + + + + + To use Constellation on STACKIT, the cluster will use the User Access Token (UAT) that's generated [during the install step](./install.md). + After creating the accounts, fill in the STACKIT details in `constellation-conf.yaml` under `provider.openstack`: + + * `stackitProjectID`: STACKIT project id (can be found after login on the [STACKIT portal](https://portal.stackit.cloud)) + + + + + :::tip + To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). + ::: + + + +3. Create the cluster. `constellation apply` uses options set in `constellation-conf.yaml`. + If you want to manually manage your cloud resources, for example by using [Terraform](../reference/terraform.md), follow the corresponding instructions in the [Create workflow](../workflows/create.md). + + :::tip + + On Azure, you may need to wait 15+ minutes at this point for role assignments to propagate. + + ::: + + ```bash + constellation apply -y + ``` + + This should look similar to the following: + + ```shell-session + $ constellation apply -y + Checking for infrastructure changes + The following Constellation cluster will be created: + 3 control-plane nodes of type n2d-standard-4 will be created. + 1 worker node of type n2d-standard-4 will be created. + Creating + Cloud infrastructure created successfully + Your Constellation master secret was successfully written to ./constellation-mastersecret.json + Connecting + Initializing cluster + Installing Kubernetes components + Your Constellation cluster was successfully initialized. + + Constellation cluster identifier g6iMP5wRU1b7mpOz2WEISlIYSfdAhB0oNaOg6XEwKFY= + Kubernetes configuration constellation-admin.conf + + You can now connect to your cluster by executing: + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + + The cluster's identifier will be different in your output. + Keep `constellation-mastersecret.json` somewhere safe. + This will allow you to [recover your cluster](../workflows/recovery.md) in case of a disaster. + + :::info + + Depending on your CSP and region, `constellation apply` may take 10+ minutes to complete. + + ::: + +4. Configure kubectl. + + ```bash + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + +## Deploy a sample application + +1. Deploy the [emojivoto app](https://github.com/BuoyantIO/emojivoto) + + ```bash + kubectl apply -k github.com/BuoyantIO/emojivoto/kustomize/deployment + ``` + +2. Expose the frontend service locally + + ```bash + kubectl wait --for=condition=available --timeout=60s -n emojivoto --all deployments + kubectl -n emojivoto port-forward svc/web-svc 8080:80 & + curl http://localhost:8080 + kill %1 + ``` + +## Terminate your cluster + +Use the CLI to terminate your cluster. If you manually used [Terraform](../reference/terraform.md) to manage your cloud resources, follow the corresponding instructions in the [Terminate workflow](../workflows/terminate.md). + +```bash +constellation terminate +``` + +This should give the following output: + +```shell-session +$ constellation terminate +You are about to terminate a Constellation cluster. +All of its associated resources will be DESTROYED. +This action is irreversible and ALL DATA WILL BE LOST. +Do you want to continue? [y/n]: +``` + +Confirm with `y` to terminate the cluster: + +```shell-session +Terminating ... +Your Constellation cluster was terminated successfully. +``` + +Optionally, you can also [delete your IAM resources](../workflows/config.md#deleting-an-iam-configuration). diff --git a/docs/versioned_docs/version-2.18/getting-started/install.md b/docs/versioned_docs/version-2.18/getting-started/install.md new file mode 100644 index 000000000..d52e43476 --- /dev/null +++ b/docs/versioned_docs/version-2.18/getting-started/install.md @@ -0,0 +1,429 @@ +# Installation and setup + +Constellation runs entirely in your cloud environment and can be controlled via a dedicated [command-line interface (CLI)](../reference/cli.md) or a [Terraform provider](../workflows/terraform-provider.md). + +## Prerequisites + +Make sure the following requirements are met: + +* Your machine is running Linux, macOS, or Windows +* You have admin rights on your machine +* [kubectl](https://kubernetes.io/docs/tasks/tools/) is installed +* Your CSP is Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), or STACKIT + +## Install the Constellation CLI + +:::tip + +If you prefer to use Terraform, you can alternatively use the [Terraform provider](../workflows/terraform-provider.md) to manage the cluster's lifecycle. + +::: + +The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). +Install it with the following commands: + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-linux-amd64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-linux-amd64 /usr/local/bin/constellation +``` + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-linux-arm64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-linux-arm64 /usr/local/bin/constellation +``` + + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-darwin-arm64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-darwin-arm64 /usr/local/bin/constellation +``` + + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-darwin-amd64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-darwin-amd64 /usr/local/bin/constellation +``` + + + + + +1. Download the CLI: + +```bash +Invoke-WebRequest -OutFile ./constellation.exe -Uri 'https://github.com/edgelesssys/constellation/releases/latest/download/constellation-windows-amd64.exe' +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI under `C:\Program Files\Constellation\bin\constellation.exe` + +3. Add the CLI to your PATH: + + 1. Open `Advanced system settings` by searching for the App in the Windows search + 2. Go to the `Advanced` tab + 3. Click `Environment Variables…` + 4. Click variable called `Path` and click `Edit…` + 5. Click `New` + 6. Enter the path to the folder containing the binary you want on your PATH: `C:\Program Files\Constellation\bin` + + + + +:::tip +The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. +::: + +## Set up cloud credentials + +Constellation makes authenticated calls to the CSP API. Therefore, you need to set up Constellation with the credentials for your CSP. + +:::tip +If you don't have a cloud subscription, you can also set up a [local Constellation cluster using virtualization](../getting-started/first-steps-local.md) for testing. +::: + +### Required permissions + + + + +To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. + +To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:DescribeAccountAttributes", + "iam:AddRoleToInstanceProfile", + "iam:AttachRolePolicy", + "iam:CreateInstanceProfile", + "iam:CreatePolicy", + "iam:CreateRole", + "iam:DeleteInstanceProfile", + "iam:DeletePolicy", + "iam:DeletePolicyVersion", + "iam:DeleteRole", + "iam:DetachRolePolicy", + "iam:GetInstanceProfile", + "iam:GetPolicy", + "iam:GetPolicyVersion", + "iam:GetRole", + "iam:ListAttachedRolePolicies", + "iam:ListInstanceProfilesForRole", + "iam:ListPolicyVersions", + "iam:ListRolePolicies", + "iam:PassRole", + "iam:RemoveRoleFromInstanceProfile", + "sts:GetCallerIdentity" + ], + "Resource": "*" + } + ] +} +``` + +The built-in `AdministratorAccess` policy is a superset of these permissions. + +To [create a Constellation cluster](../workflows/create.md), see the permissions of [main.tf](https://github.com/edgelesssys/constellation/blob/main/terraform/infrastructure/iam/aws/main.tf). + +The built-in `PowerUserAccess` policy is a superset of these permissions. + +Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). + + + + +The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: + +* `Microsoft.Attestation` +* `Microsoft.Compute` +* `Microsoft.Insights` +* `Microsoft.ManagedIdentity` +* `Microsoft.Network` + +By default, Constellation tries to register these automatically if they haven't been registered before. + +To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: + +* `*/register/action` \[1] +* `Microsoft.Authorization/roleAssignments/*` +* `Microsoft.Authorization/roleDefinitions/*` +* `Microsoft.ManagedIdentity/userAssignedIdentities/*` +* `Microsoft.Resources/subscriptions/resourcegroups/*` + +The built-in `Owner` role is a superset of these permissions. + +To [create a Constellation cluster](../workflows/create.md), you need the following permissions: + +* `Microsoft.Attestation/attestationProviders/*` +* `Microsoft.Compute/virtualMachineScaleSets/*` +* `Microsoft.Insights/components/*` +* `Microsoft.ManagedIdentity/userAssignedIdentities/*` +* `Microsoft.Network/loadBalancers/*` +* `Microsoft.Network/loadBalancers/backendAddressPools/*` +* `Microsoft.Network/networkSecurityGroups/*` +* `Microsoft.Network/publicIPAddresses/*` +* `Microsoft.Network/virtualNetworks/*` +* `Microsoft.Network/virtualNetworks/subnets/*` +* `Microsoft.Network/natGateways/*` + +The built-in `Contributor` role is a superset of these permissions. + +Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-definitions) and [assigning roles](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments). + +1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. + + + + +Create a new project for Constellation or use an existing one. +Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. + +To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: + +* `iam.serviceAccountKeys.create` +* `iam.serviceAccountKeys.delete` +* `iam.serviceAccountKeys.get` +* `iam.serviceAccounts.create` +* `iam.serviceAccounts.delete` +* `iam.serviceAccounts.get` +* `resourcemanager.projects.getIamPolicy` +* `resourcemanager.projects.setIamPolicy` + +Together, the built-in roles `roles/editor` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. + +To [create a Constellation cluster](../workflows/create.md), you need the following permissions: + +* `compute.addresses.createInternal` +* `compute.addresses.deleteInternal` +* `compute.addresses.get` +* `compute.addresses.useInternal` +* `compute.backendServices.create` +* `compute.backendServices.delete` +* `compute.backendServices.get` +* `compute.backendServices.use` +* `compute.disks.create` +* `compute.firewalls.create` +* `compute.firewalls.delete` +* `compute.firewalls.get` +* `compute.firewalls.update` +* `compute.globalAddresses.create` +* `compute.globalAddresses.delete` +* `compute.globalAddresses.get` +* `compute.globalAddresses.use` +* `compute.globalForwardingRules.create` +* `compute.globalForwardingRules.delete` +* `compute.globalForwardingRules.get` +* `compute.globalForwardingRules.setLabels` +* `compute.globalOperations.get` +* `compute.healthChecks.create` +* `compute.healthChecks.delete` +* `compute.healthChecks.get` +* `compute.healthChecks.useReadOnly` +* `compute.instanceGroupManagers.create` +* `compute.instanceGroupManagers.delete` +* `compute.instanceGroupManagers.get` +* `compute.instanceGroupManagers.update` +* `compute.instanceGroups.create` +* `compute.instanceGroups.delete` +* `compute.instanceGroups.get` +* `compute.instanceGroups.update` +* `compute.instanceGroups.use` +* `compute.instances.create` +* `compute.instances.setLabels` +* `compute.instances.setMetadata` +* `compute.instances.setTags` +* `compute.instanceTemplates.create` +* `compute.instanceTemplates.delete` +* `compute.instanceTemplates.get` +* `compute.instanceTemplates.useReadOnly` +* `compute.networks.create` +* `compute.networks.delete` +* `compute.networks.get` +* `compute.networks.updatePolicy` +* `compute.routers.create` +* `compute.routers.delete` +* `compute.routers.get` +* `compute.routers.update` +* `compute.subnetworks.create` +* `compute.subnetworks.delete` +* `compute.subnetworks.get` +* `compute.subnetworks.use` +* `compute.targetTcpProxies.create` +* `compute.targetTcpProxies.delete` +* `compute.targetTcpProxies.get` +* `compute.targetTcpProxies.use` +* `iam.serviceAccounts.actAs` + +Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. + +Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). + + + + +Constellation on STACKIT requires a User Access Token (UAT) for the OpenStack API and a STACKIT service account. +The UAT already has all required permissions by default. +The STACKIT service account needs the `editor` role to create STACKIT LoadBalancers. +Look at the [STACKIT documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) on how to create the service account and assign the role. + + + + +### Authentication + +You need to authenticate with your CSP. The following lists the required steps for *testing* and *production* environments. + +:::note +The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. +::: + + + + +**Testing** + +You can use the [AWS CloudShell](https://console.aws.amazon.com/cloudshell/home). Make sure you are [authorized to use it](https://docs.aws.amazon.com/cloudshell/latest/userguide/sec-auth-with-identities.html). + +**Production** + +Use the latest version of the [AWS CLI](https://aws.amazon.com/cli/) on a trusted machine: + +```bash +aws configure +``` + +Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). + + + + +**Testing** + +Simply open the [Azure Cloud Shell](https://docs.microsoft.com/en-us/azure/cloud-shell/overview). + +**Production** + +Use the latest version of the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/) on a trusted machine: + +```bash +az login +``` + +Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). + + + + +**Testing** + +You can use the [Google Cloud Shell](https://cloud.google.com/shell). Make sure your [session is authorized](https://cloud.google.com/shell/docs/auth). For example, execute `gsutil` and accept the authorization prompt. + +**Production** + +Use one of the following options on a trusted machine: + +* Use the [`gcloud` CLI](https://cloud.google.com/sdk/gcloud) + + ```bash + gcloud auth application-default login + ``` + + This will ask you to log-in to your Google account and create your credentials. + The Constellation CLI will automatically load these credentials when needed. + +* Set up a service account and pass the credentials manually + + Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. + + + + +You need to authenticate with the infrastructure API (OpenStack) and create a service account (STACKIT API). + +1. [Follow the STACKIT documentation](https://docs.stackit.cloud/stackit/en/step-1-generating-of-user-access-token-11763726.html) for obtaining a User Access Token (UAT) to use the infrastructure API +2. Create a configuration file under `~/.config/openstack/clouds.yaml` (`%AppData%\openstack\clouds.yaml` on Windows) with the credentials from the User Access Token + + ```yaml + clouds: + stackit: + auth: + auth_url: https://keystone.api.iaas.eu01.stackit.cloud/v3 + username: REPLACE_WITH_UAT_USERNAME + password: REPLACE_WITH_UAT_PASSWORD + project_id: REPLACE_WITH_STACKIT_PROJECT_ID + project_name: REPLACE_WITH_STACKIT_PROJECT_NAME + user_domain_name: portal_mvp + project_domain_name: portal_mvp + region_name: RegionOne + identity_api_version: 3 + ``` + +3. [Follow the STACKIT documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) for creating a service account and an access token +4. Assign the `editor` role to the service account by [following the documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) +5. Create a configuration file under `~/.stackit/credentials.json` (`%USERPROFILE%\.stackit\credentials.json` on Windows) + + ```json + {"STACKIT_SERVICE_ACCOUNT_TOKEN":"REPLACE_WITH_TOKEN"} + ``` + + + + + +## Next steps + +You are now ready to [deploy your first confidential Kubernetes cluster and application](first-steps.md). diff --git a/docs/versioned_docs/version-2.18/getting-started/marketplaces.md b/docs/versioned_docs/version-2.18/getting-started/marketplaces.md new file mode 100644 index 000000000..a6763a42a --- /dev/null +++ b/docs/versioned_docs/version-2.18/getting-started/marketplaces.md @@ -0,0 +1,56 @@ +# Using Constellation via Cloud Marketplaces + +Constellation is available through the Marketplaces of AWS, Azure, GCP, and STACKIT. This allows you to create self-managed Constellation clusters that are billed on a pay-per-use basis (hourly, per vCPU) with your CSP account. You can still get direct support by Edgeless Systems. For more information, please [contact us](https://www.edgeless.systems/enterprise-support/). + +This document explains how to run Constellation with the dynamically billed cloud marketplace images. + + + + +To use Constellation's marketplace images, ensure that you are subscribed to the [marketplace offering](https://aws.amazon.com/marketplace/pp/prodview-2mbn65nv57oys) through the web portal. + +Then, enable the use of marketplace images in your Constellation `constellation-conf.yaml` [config file](../workflows/config.md): + +```bash +yq eval -i ".provider.aws.useMarketplaceImage = true" constellation-conf.yaml +``` + + + + +Constellation has a private marketplace plan. Please [contact us](https://www.edgeless.systems/enterprise-support/) to gain access. + +To use a marketplace image, you need to accept the marketplace image's terms once for your subscription with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/vm/image/terms?view=azure-cli-latest): + +```bash +az vm image terms accept --publisher edgelesssystems --offer constellation --plan constellation +``` + +Then, enable the use of marketplace images in your Constellation `constellation-conf.yaml` [config file](../workflows/config.md): + +```bash +yq eval -i ".provider.azure.useMarketplaceImage = true" constellation-conf.yaml +``` + + + + +To use a marketplace image, ensure that the account is entitled to use marketplace images by Edgeless Systems by accepting the terms through the [web portal](https://console.cloud.google.com/marketplace/vm/config/edgeless-systems-public/constellation). + +Then, enable the use of marketplace images in your Constellation `constellation-conf.yaml` [config file](../workflows/config.md): + +```bash +yq eval -i ".provider.gcp.useMarketplaceImage = true" constellation-conf.yaml +``` + + + + +On STACKIT, the selected Constellation image is always a marketplace image. You can find more information on the STACKIT portal. + + + + +Ensure that the cluster uses an official release image version (i.e., `.image=vX.Y.Z` in the `constellation-conf.yaml` file). + +From there, you can proceed with the [cluster creation](../workflows/create.md) as usual. diff --git a/docs/versioned_docs/version-2.18/intro.md b/docs/versioned_docs/version-2.18/intro.md new file mode 100644 index 000000000..0bfe86da9 --- /dev/null +++ b/docs/versioned_docs/version-2.18/intro.md @@ -0,0 +1,34 @@ +--- +slug: / +id: intro +--- +# Introduction + +Welcome to the documentation of Constellation! Constellation is a Kubernetes engine that aims to provide the best possible data security. + +![Constellation concept](/img/concept.svg) + + Constellation shields your entire Kubernetes cluster from the underlying cloud infrastructure. Everything inside is always encrypted, including at runtime in memory. For this, Constellation leverages a technology called *confidential computing* and more specifically Confidential VMs. + +:::tip +See the 📄[whitepaper](https://content.edgeless.systems/hubfs/Confidential%20Computing%20Whitepaper.pdf) for more information on confidential computing. +::: + +## Goals + +From a security perspective, Constellation is designed to keep all data always encrypted and to prevent any access from the underlying (cloud) infrastructure. This includes access from datacenter employees, privileged cloud admins, and attackers coming through the infrastructure. Such attackers could be malicious co-tenants escalating their privileges or hackers who managed to compromise a cloud server. + +From a DevOps perspective, Constellation is designed to work just like what you would expect from a modern Kubernetes engine. + +## Use cases + +Constellation provides unique security [features](overview/confidential-kubernetes.md) and [benefits](overview/security-benefits.md). The core use cases are: + +* Increasing the overall security of your clusters +* Increasing the trustworthiness of your SaaS offerings +* Moving sensitive workloads from on-prem to the cloud +* Meeting regulatory requirements + +## Next steps + +You can learn more about the concept of Confidential Kubernetes, features, security benefits, and performance of Constellation in the *Basics* section. To jump right into the action head to *Getting started*. diff --git a/docs/versioned_docs/version-2.18/overview/clouds.md b/docs/versioned_docs/version-2.18/overview/clouds.md new file mode 100644 index 000000000..b2695d28e --- /dev/null +++ b/docs/versioned_docs/version-2.18/overview/clouds.md @@ -0,0 +1,66 @@ +# Feature status of clouds + +What works on which cloud? Currently, Confidential VMs (CVMs) are available in varying quality on the different clouds and software stacks. + +For Constellation, the ideal environment provides the following: + +1. Ability to run arbitrary software and images inside CVMs +2. CVMs based on AMD SEV-SNP (available in EPYC CPUs since the Milan generation) or Intel TDX (available in Xeon CPUs since the Sapphire Rapids generation) +3. Ability for CVM guests to obtain raw hardware attestation statements +4. Reviewable, open-source firmware inside CVMs +5. Capability of the firmware to attest the integrity of the code it passes control to, e.g., with an embedded virtual TPM (vTPM) + +(1) is a functional must-have. (2)--(5) are required for remote attestation that fully keeps the infrastructure/cloud out. Constellation can work without them or with approximations, but won't protect against certain privileged attackers anymore. + +The following table summarizes the state of features for different infrastructures. + +| **Feature** | **AWS** | **Azure** | **GCP** | **STACKIT** | **OpenStack (Yoga)** | +|-----------------------------------|---------|-----------|---------|--------------|----------------------| +| **1. Custom images** | Yes | Yes | Yes | Yes | Yes | +| **2. SEV-SNP or TDX** | Yes | Yes | Yes | No | Depends on kernel/HV | +| **3. Raw guest attestation** | Yes | Yes | Yes | No | Depends on kernel/HV | +| **4. Reviewable firmware** | Yes | No* | No | No | Depends on kernel/HV | +| **5. Confidential measured boot** | No | Yes | No | No | Depends on kernel/HV | + +## Amazon Web Services (AWS) + +Amazon EC2 [supports AMD SEV-SNP](https://aws.amazon.com/de/about-aws/whats-new/2023/04/amazon-ec2-amd-sev-snp/). +Regarding (3), AWS provides direct access to attestation statements. +However, regarding (5), attestation is partially based on the [NitroTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) for [measured boot](../architecture/attestation.md#measured-boot), which is a vTPM managed by the Nitro hypervisor. +Hence, the hypervisor is currently part of Constellation's TCB. +Regarding (4), the [firmware is open source](https://github.com/aws/uefi) and can be reproducibly built. + +## Microsoft Azure + +With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. +Regarding (3), Azure provides direct access to attestation statements. +The firmware runs in an isolated domain inside the CVM and exposes a vTPM (5), but it's closed source (4). +On SEV-SNP, Azure uses VM Privilege Level (VMPL) isolation for the separation of firmware and the rest of the VM; on TDX, they use TD partitioning. +This firmware is signed by Azure. +The signature is reflected in the attestation statements of CVMs. +Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). + +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. + +## Google Cloud Platform (GCP) + +The [CVMs Generally Available in GCP](https://cloud.google.com/confidential-computing/confidential-vm/docs/confidential-vm-overview#technologies) are based on AMD SEV-ES or SEV-SNP. +Regarding (3), with their SEV-SNP offering Google provides direct access to attestation statements. +However, regarding (5), attestation is partially based on the [Shielded VM vTPM](https://cloud.google.com/compute/shielded-vm/docs/shielded-vm#vtpm) for [measured boot](../architecture/attestation.md#measured-boot), which is a vTPM managed by Google's hypervisor. +Hence, the hypervisor is currently part of Constellation's TCB. +Regarding (4), the CVMs still include closed-source firmware. + +[TDX on Google](https://cloud.google.com/blog/products/identity-security/confidential-vms-on-intel-cpus-your-datas-new-intelligent-defense) is in public preview. +With it, Constellation would have a similar TCB and attestation flow as with the current SEV-SNP offering. + +## STACKIT + +[STACKIT Compute Engine](https://www.stackit.de/en/product/stackit-compute-engine/) supports AMD SEV-ES. A vTPM is used for measured boot, which is a vTPM managed by STACKIT's hypervisor. Hence, the hypervisor is currently part of Constellation's TCB. + +## OpenStack + +OpenStack is an open-source cloud and infrastructure management software. It's used by many smaller CSPs and datacenters. In the latest *Yoga* version, OpenStack has basic support for CVMs. However, much depends on the employed kernel and hypervisor. Features (2)--(4) are likely to be a *Yes* with Linux kernel version 6.2. Thus, going forward, OpenStack on corresponding AMD or Intel hardware will be a viable underpinning for Constellation. + +## Conclusion + +The different clouds and software like the Linux kernel and OpenStack are in the process of building out their support for state-of-the-art CVMs. Azure has already most features in place. For Constellation, the status quo means that the TCB has different shapes on different infrastructures. With broad SEV-SNP support coming to the Linux kernel, we soon expect a normalization of features across infrastructures. diff --git a/docs/versioned_docs/version-2.18/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.18/overview/confidential-kubernetes.md new file mode 100644 index 000000000..bff8c3322 --- /dev/null +++ b/docs/versioned_docs/version-2.18/overview/confidential-kubernetes.md @@ -0,0 +1,42 @@ +# Confidential Kubernetes + +We use the term *Confidential Kubernetes* to refer to the concept of using confidential-computing technology to shield entire Kubernetes clusters from the infrastructure. The three defining properties of this concept are: + +1. **Workload shielding**: the confidentiality and integrity of all workload-related data and code are enforced. +2. **Control plane shielding**: the confidentiality and integrity of the cluster's control plane, state, and workload configuration are enforced. +3. **Attestation and verifiability**: the two properties above can be verified remotely based on hardware-rooted cryptographic certificates. + +Each of the above properties is equally important. Only with all three in conjunction, an entire cluster can be shielded without gaps. + +## Constellation security features + +Constellation implements the Confidential Kubernetes concept with the following security features. + +* **Runtime encryption**: Constellation runs all Kubernetes nodes inside Confidential VMs (CVMs). This gives runtime encryption for the entire cluster. +* **Network and storage encryption**: Constellation augments this with transparent encryption of the [network](../architecture/networking.md), [persistent storage](../architecture/encrypted-storage.md), and other managed storage like [AWS S3](../architecture/encrypted-storage.md#encrypted-s3-object-storage). Thus, workloads and control plane are truly end-to-end encrypted: at rest, in transit, and at runtime. +* **Transparent key management**: Constellation manages the corresponding [cryptographic keys](../architecture/keys.md) inside CVMs. +* **Node attestation and verification**: Constellation verifies the integrity of each new CVM-based node using [remote attestation](../architecture/attestation.md). Only "good" nodes receive the cryptographic keys required to access the network and storage of a cluster. +* **Confidential computing-optimized images**: A node is "good" if it's running a signed Constellation [node image](../architecture/images.md) inside a CVM and is in the expected state. (Node images are hardware-measured during boot. The measurements are reflected in the attestation statements that are produced by nodes and verified by Constellation.) +* **"Whole cluster" attestation**: Towards the DevOps engineer, Constellation provides a single hardware-rooted certificate from which all of the above can be verified. + +With the above, Constellation wraps an entire cluster into one coherent and verifiable *confidential context*. The concept is depicted in the following. + +![Confidential Kubernetes](../_media/concept-constellation.svg) + +## Comparison: Managed Kubernetes with CVMs + +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. + +![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) + +The following table highlights the key differences in terms of features. + +| | Managed Kubernetes with CVMs | Confidential Kubernetes (Constellation✨) | +|-------------------------------------|------------------------------|--------------------------------------------| +| Runtime encryption | Partial (data plane only)| **Yes** | +| Node image verification | No | **Yes** | +| Full cluster attestation | No | **Yes** | +| Transparent network encryption | No | **Yes** | +| Transparent storage encryption | No | **Yes** | +| Confidential key management | No | **Yes** | +| Cloud agnostic / multi-cloud | No | **Yes** | diff --git a/docs/versioned_docs/version-2.18/overview/license.md b/docs/versioned_docs/version-2.18/overview/license.md new file mode 100644 index 000000000..34122c025 --- /dev/null +++ b/docs/versioned_docs/version-2.18/overview/license.md @@ -0,0 +1,33 @@ +# License + +## Source code + +Constellation's source code is available on [GitHub](https://github.com/edgelesssys/constellation) under the [GNU Affero General Public License v3.0](https://github.com/edgelesssys/constellation/blob/main/LICENSE). + +## Binaries + +Edgeless Systems provides ready-to-use and [signed](../architecture/attestation.md#chain-of-trust) binaries of Constellation. This includes the CLI and the [node images](../architecture/images.md). + +These binaries may be used free of charge within the bounds of Constellation's [**Community License**](#community-license). An [**Enterprise License**](#enterprise-license) can be purchased from Edgeless Systems. + +The Constellation CLI displays relevant license information when you initialize your cluster. You are responsible for staying within the bounds of your respective license. Constellation doesn't enforce any limits so as not to endanger your cluster's availability. + +## Terraform provider + +Edgeless Systems provides a [Terraform provider](https://github.com/edgelesssys/terraform-provider-constellation/releases), which may be used free of charge within the bounds of Constellation's [**Community License**](#community-license). An [**Enterprise License**](#enterprise-license) can be purchased from Edgeless Systems. + +You are responsible for staying within the bounds of your respective license. Constellation doesn't enforce any limits so as not to endanger your cluster's availability. + +## Community License + +You are free to use the Constellation binaries provided by Edgeless Systems to create services for internal consumption, evaluation purposes, or non-commercial use. You must not use the Constellation binaries to provide commercial hosted services to third parties. Edgeless Systems gives no warranties and offers no support. + +## Enterprise License + +Enterprise Licenses don't have the above limitations and come with support and additional features. Find out more at the [product website](https://www.edgeless.systems/products/constellation/). + +Once you have received your Enterprise License file, place it in your [Constellation workspace](../architecture/orchestration.md#workspaces) in a file named `constellation.license`. + +## CSP Marketplaces + +Constellation is available through the Marketplaces of AWS, Azure, GCP, and STACKIT. This allows you to create self-managed Constellation clusters that are billed on a pay-per-use basis (hourly, per vCPU) with your CSP account. You can still get direct support by Edgeless Systems. For more information, please [contact us](https://www.edgeless.systems/enterprise-support/). diff --git a/docs/versioned_docs/version-2.18/overview/performance/application.md b/docs/versioned_docs/version-2.18/overview/performance/application.md new file mode 100644 index 000000000..c67d59644 --- /dev/null +++ b/docs/versioned_docs/version-2.18/overview/performance/application.md @@ -0,0 +1,102 @@ +# Application benchmarks + +## HashiCorp Vault + +[HashiCorp Vault](https://www.vaultproject.io/) is a distributed secrets management software that can be deployed to Kubernetes. +HashiCorp maintains a benchmarking tool for vault, [vault-benchmark](https://github.com/hashicorp/vault-benchmark/). +Vault-benchmark generates load on a Vault deployment and measures response times. + +This article describes the results from running vault-benchmark on Constellation, AKS, and GKE. +You can find the setup for producing the data discussed in this article in the [vault-benchmarks](https://github.com/edgelesssys/vault-benchmarks) repository. + +The Vault API used during benchmarking is the [transits secret engine](https://developer.hashicorp.com/vault/docs/secrets/transit). +This allows services to send data to Vault for encryption, decryption, signing, and verification. + +## Results + +On each run, vault-benchmark sends requests and measures the latencies. +The measured latencies are aggregated through various statistical features. +After running the benchmark n times, the arithmetic mean over a subset of the reported statistics is calculated. +The selected features are arithmetic mean, 99th percentile, minimum, and maximum. + +Arithmetic mean gives a general sense of the latency on each target. +The 99th percentile shows performance in (most likely) erroneous states. +Minimum and maximum mark the range within which latency varies each run. + +The benchmark was configured with 1300 workers and 10 seconds per run. +Those numbers were chosen empirically. +The latency was stabilizing at 10 seconds runtime, not changing with further increase. +Increasing the number of workers beyond 1300 leads to request failures, marking the limit Vault was able to handle in this setup. +All results are based on 100 runs. + +The following data was generated while running five replicas, one primary, and four standby nodes. +All numbers are in seconds if not indicated otherwise. +``` +========== Results AKS ========== +Mean: mean: 1.632200, variance: 0.002057 +P99: mean: 5.480679, variance: 2.263700 +Max: mean: 6.651001, variance: 2.808401 +Min: mean: 0.011415, variance: 0.000133 +========== Results GKE ========== +Mean: mean: 1.656435, variance: 0.003615 +P99: mean: 6.030807, variance: 3.955051 +Max: mean: 7.164843, variance: 3.300004 +Min: mean: 0.010233, variance: 0.000111 +========== Results C11n ========== +Mean: mean: 1.651549, variance: 0.001610 +P99: mean: 5.780422, variance: 3.016106 +Max: mean: 6.942997, variance: 3.075796 +Min: mean: 0.013774, variance: 0.000228 +========== AKS vs C11n ========== +Mean: +1.171577 % (AKS is faster) +P99: +5.185495 % (AKS is faster) +Max: +4.205618 % (AKS is faster) +Min: +17.128781 % (AKS is faster) +========== GKE vs C11n ========== +Mean: -0.295851 % (GKE is slower) +P99: -4.331603 % (GKE is slower) +Max: -3.195248 % (GKE is slower) +Min: +25.710886 % (GKE is faster) +``` + +**Interpretation**: Latencies are all within ~5% of each other. +AKS performs slightly better than GKE and Constellation (C11n) in all cases except minimum latency. +Minimum latency is the lowest for GKE. +Compared to GKE, Constellation had slightly lower peak latencies (99th percentile and maximum), indicating that Constellation could have handled slightly more concurrent accesses than GKE. +Overall, performance is at comparable levels across all three distributions. +Based on these numbers, you can use a similarly sized Constellation cluster to run your existing Vault deployment. + +### Visualization + +The following plots visualize the data presented above as [box plots](https://en.wikipedia.org/wiki/Box_plot). +The whiskers denote the minimum and maximum. +The box stretches from the 25th to the 75th percentile, with the dividing bar marking the 50th percentile. +The circles outside the whiskers denote outliers. + +
+Mean Latency + +![Mean Latency](../../_media/benchmark_vault/5replicas/mean_latency.png) + +
+ +
+99th Percentile Latency + +![99th Percentile Latency](../../_media/benchmark_vault/5replicas/p99_latency.png) + +
+ +
+Maximum Latency + +![Maximum Latency](../../_media/benchmark_vault/5replicas/max_latency.png) + +
+ +
+Minimum Latency + +![Minimum Latency](../../_media/benchmark_vault/5replicas/min_latency.png) + +
diff --git a/docs/versioned_docs/version-2.18/overview/performance/compute.md b/docs/versioned_docs/version-2.18/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/versioned_docs/version-2.18/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/versioned_docs/version-2.18/overview/performance/io.md b/docs/versioned_docs/version-2.18/overview/performance/io.md new file mode 100644 index 000000000..3ae796f8a --- /dev/null +++ b/docs/versioned_docs/version-2.18/overview/performance/io.md @@ -0,0 +1,204 @@ +# I/O performance benchmarks + +To assess the overall performance of Constellation, this benchmark evaluates Constellation v2.6.0 in terms of storage I/O using [`fio`](https://fio.readthedocs.io/en/latest/fio_doc.html) and network performance using the [Kubernetes Network Benchmark](https://github.com/InfraBuilder/k8s-bench-suite#knb--kubernetes-network-be). + +This benchmark tested Constellation on Azure and GCP and compared the results against the managed Kubernetes offerings AKS and GKE. + +## Configurations + +### Constellation + +The benchmark was conducted with Constellation v2.6.0, Kubernetes v1.25.7, and Cilium v1.12. +It ran on the following infrastructure configurations. + +Constellation on Azure: + +- Nodes: 3 (1 Control-plane, 2 Worker) +- Machines: `DC4as_v5`: 3rd Generation AMD EPYC 7763v (Milan) processor with 4 Cores, 16 GiB memory +- CVM: `true` +- Region: `West US` +- Zone: `2` + +Constellation on GCP: + +- Nodes: 3 (1 Control-plane, 2 Worker) +- Machines: `n2d-standard-4`: 2nd Generation AMD EPYC (Rome) processor with 4 Cores, 16 GiB of memory +- CVM: `true` +- Zone: `europe-west3-b` + +### AKS + +On AKS, the benchmark used Kubernetes `v1.24.9` and nodes with version `AKSUbuntu-1804gen2containerd-2023.02.15`. +AKS ran with the [`kubenet`](https://learn.microsoft.com/en-us/azure/aks/concepts-network#kubenet-basic-networking) CNI and the [default CSI driver](https://learn.microsoft.com/en-us/azure/aks/azure-disk-csi) for Azure Disk. + +The following infrastructure configurations was used: + +- Nodes: 2 (2 Worker) +- Machines: `D4as_v5`: 3rd Generation AMD EPYC 7763v (Milan) processor with 4 Cores, 16 GiB memory +- CVM: `false` +- Region: `West US` +- Zone: `2` + +### GKE + +On GKE, the benchmark used Kubernetes `v1.24.9` and nodes with version `1.24.9-gke.3200`. +GKE ran with the [`kubenet`](https://cloud.google.com/kubernetes-engine/docs/concepts/network-overview) CNI and the [default CSI driver](https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/gce-pd-csi-driver) for Compute Engine persistent disk. + +The following infrastructure configurations was used: + +- Nodes: 2 (2 Worker) +- Machines: `n2d-standard-4` 2nd Generation AMD EPYC (Rome) processor with 4 Cores, 16 GiB of memory +- CVM: `false` +- Zone: `europe-west3-b` + +## Results + +### Network + +This section gives a thorough analysis of the network performance of Constellation, specifically focusing on measuring TCP and UDP bandwidth. +The benchmark measured the bandwidth of pod-to-pod and pod-to-service connections between two different nodes using [`iperf`](https://iperf.fr/). + +GKE and Constellation on GCP had a maximum network bandwidth of [10 Gbps](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines). +AKS with `Standard_D4as_v5` machines a maximum network bandwidth of [12.5 Gbps](https://learn.microsoft.com/en-us/azure/virtual-machines/dasv5-dadsv5-series#dasv5-series). +The Confidential VM equivalent `Standard_DC4as_v5` currently has a network bandwidth of [1.25 Gbps](https://learn.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series#dcasv5-series-products). +Therefore, to make the test comparable, both AKS and Constellation on Azure were running with `Standard_DC4as_v5` machines and 1.25 Gbps bandwidth. + +Constellation on Azure and AKS used an MTU of 1500. +Constellation on GCP used an MTU of 8896. GKE used an MTU of 1450. + +The difference in network bandwidth can largely be attributed to two factors. + +- Constellation's [network encryption](../../architecture/networking.md) via Cilium and WireGuard, which protects data in-transit. +- [AMD SEV using SWIOTLB bounce buffers](https://lore.kernel.org/all/20200204193500.GA15564@ashkalra_ubuntu_server/T/) for all DMA including network I/O. + +#### Pod-to-Pod + +In this scenario, the client Pod connects directly to the server pod via its IP address. + +```mermaid +flowchart LR + subgraph Node A + Client[Client] + end + subgraph Node B + Server[Server] + end + Client ==>|traffic| Server +``` + +The results for "Pod-to-Pod" on Azure are as follows: + +![Network Pod2Pod Azure benchmark graph](../../_media/benchmark_net_p2p_azure.png) + +The results for "Pod-to-Pod" on GCP are as follows: + +![Network Pod2Pod GCP benchmark graph](../../_media/benchmark_net_p2p_gcp.png) + +#### Pod-to-Service + +In this scenario, the client Pod connects to the server Pod via a ClusterIP service. This is more relevant to real-world use cases. + +```mermaid +flowchart LR + subgraph Node A + Client[Client] ==>|traffic| Service[Service] + end + subgraph Node B + Server[Server] + end + Service ==>|traffic| Server +``` + +The results for "Pod-to-Pod" on Azure are as follows: + +![Network Pod2SVC Azure benchmark graph](../../_media/benchmark_net_p2svc_azure.png) + +The results for "Pod-to-Pod" on GCP are as follows: + +![Network Pod2SVC GCP benchmark graph](../../_media/benchmark_net_p2svc_gcp.png) + +In our recent comparison of Constellation on GCP with GKE, Constellation has 58% less TCP bandwidth. However, UDP bandwidth was slightly better with Constellation, thanks to its higher MTU. + +Similarly, when comparing Constellation on Azure with AKS using CVMs, Constellation achieved approximately 10% less TCP and 40% less UDP bandwidth. + +### Storage I/O + +Azure and GCP offer persistent storage for their Kubernetes services AKS and GKE via the Container Storage Interface (CSI). CSI storage in Kubernetes is available via `PersistentVolumes` (PV) and consumed via `PersistentVolumeClaims` (PVC). +Upon requesting persistent storage through a PVC, GKE and AKS will provision a PV as defined by a default [storage class](https://kubernetes.io/docs/concepts/storage/storage-classes/). +Constellation provides persistent storage on Azure and GCP [that's encrypted on the CSI layer](../../architecture/encrypted-storage.md). +Similarly, upon a PVC request, Constellation will provision a PV via a default storage class. + +For Constellation on Azure and AKS, the benchmark ran with Azure Disk storage [Standard SSD](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#standard-ssds) of 400 GiB size. +The [DC4as machine type](https://learn.microsoft.com/en-us/azure/virtual-machines/dasv5-dadsv5-series#dasv5-series) with four cores provides the following maximum performance: + +- 6400 (20000 burst) IOPS +- 144 MB/s (600 MB/s burst) throughput + +However, the performance is bound by the capabilities of the [512 GiB Standard SSD size](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#standard-ssds) (the size class of 400 GiB volumes): + +- 500 (600 burst) IOPS +- 60 MB/s (150 MB/s burst) throughput + +For Constellation on GCP and GKE, the benchmark ran with Compute Engine Persistent Disk Storage [pd-balanced](https://cloud.google.com/compute/docs/disks) of 400 GiB size. +The N2D machine type with four cores and pd-balanced provides the following [maximum performance](https://cloud.google.com/compute/docs/disks/performance#n2d_vms): + +- 3,000 read IOPS +- 15,000 write IOPS +- 240 MB/s read throughput +- 240 MB/s write throughput + +However, the performance is bound by the capabilities of a [`Zonal balanced PD`](https://cloud.google.com/compute/docs/disks/performance#zonal-persistent-disks) with 400 GiB size: + +- 2400 read IOPS +- 2400 write IOPS +- 112 MB/s read throughput +- 112 MB/s write throughput + +The [`fio`](https://fio.readthedocs.io/en/latest/fio_doc.html) benchmark consists of several tests. +The benchmark used [`Kubestr`](https://github.com/kastenhq/kubestr) to run `fio` in Kubernetes. +The default test performs randomized access patterns that accurately depict worst-case I/O scenarios for most applications. + +The following `fio` settings were used: + +- No Cloud caching +- No OS caching +- Single CPU +- 60 seconds runtime +- 10 seconds ramp-up time +- 10 GiB file +- IOPS: 4 KB blocks and 128 iodepth +- Bandwidth: 1024 KB blocks and 128 iodepth + +For more details, see the [`fio` test configuration](https://github.com/edgelesssys/constellation/blob/main/.github/actions/e2e_benchmark/fio.ini). + +The results for IOPS on Azure are as follows: + +![I/O IOPS Azure benchmark graph](../../_media/benchmark_fio_azure_iops.png) + +The results for IOPS on GCP are as follows: + +![I/O IOPS GCP benchmark graph](../../_media/benchmark_fio_gcp_iops.png) + +The results for bandwidth on Azure are as follows: + +![I/O bandwidth Azure benchmark graph](../../_media/benchmark_fio_azure_bw.png) + +The results for bandwidth on GCP are as follows: + +![I/O bandwidth GCP benchmark graph](../../_media/benchmark_fio_gcp_bw.png) + +On GCP, the results exceed the maximum performance guarantees of the chosen disk type. There are two possible explanations for this. The first is that there may be cloud caching in place that isn't configurable. Alternatively, the underlying provisioned disk size may be larger than what was requested, resulting in higher performance boundaries. + +When comparing Constellation on GCP with GKE, Constellation has similar bandwidth but about 10% less IOPS performance. On Azure, Constellation has similar IOPS performance compared to AKS, where both likely hit the maximum storage performance. However, Constellation has approximately 15% less read and write bandwidth. + +## Conclusion + +Despite the added [security benefits](../security-benefits.md) that Constellation provides, it only incurs a slight performance overhead when compared to managed Kubernetes offerings such as AKS and GKE. In most compute benchmarks, Constellation is on par with it's alternatives. +While it may be slightly slower in certain I/O scenarios due to network and storage encryption, there is ongoing work to reduce this overhead to single digits. + +For instance, storage encryption only adds between 10% to 15% overhead in terms of bandwidth and IOPS. +Meanwhile, the biggest performance impact that Constellation currently faces is network encryption, which can incur up to 58% overhead on a 10 Gbps network. +However, the Cilium team has conducted [benchmarks with Cilium using WireGuard encryption](https://docs.cilium.io/en/latest/operations/performance/benchmark/#encryption-wireguard-ipsec) on a 100 Gbps network that yielded over 15 Gbps. +We're confident that Constellation will provide a similar level of performance with an upcoming release. + +Overall, Constellation strikes a great balance between security and performance, and we're continuously working to improve its performance capabilities while maintaining its high level of security. diff --git a/docs/versioned_docs/version-2.18/overview/performance/performance.md b/docs/versioned_docs/version-2.18/overview/performance/performance.md new file mode 100644 index 000000000..59bf86602 --- /dev/null +++ b/docs/versioned_docs/version-2.18/overview/performance/performance.md @@ -0,0 +1,17 @@ +# Performance analysis of Constellation + +This section provides a comprehensive examination of the performance characteristics of Constellation. + +## Runtime encryption + +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. + +## I/O performance benchmarks + +We evaluated the [I/O performance](io.md) of Constellation, utilizing a collection of synthetic benchmarks targeting networking and storage. +We further compared this performance to native managed Kubernetes offerings from various cloud providers, to better understand how Constellation stands in relation to standard practices. + +## Application benchmarking + +To gauge Constellation's applicability to well-known applications, we performed a [benchmark of HashiCorp Vault](application.md) running on Constellation. +The results were then compared to deployments on the managed Kubernetes offerings from different cloud providers, providing a tangible perspective on Constellation's performance in actual deployment scenarios. diff --git a/docs/versioned_docs/version-2.18/overview/product.md b/docs/versioned_docs/version-2.18/overview/product.md new file mode 100644 index 000000000..4b5d90706 --- /dev/null +++ b/docs/versioned_docs/version-2.18/overview/product.md @@ -0,0 +1,12 @@ +# Product features + +Constellation is a Kubernetes engine that aims to provide the best possible data security in combination with enterprise-grade scalability and reliability features---and a smooth user experience. + +From a security perspective, Constellation implements the [Confidential Kubernetes](confidential-kubernetes.md) concept and corresponding security features, which shield your entire cluster from the underlying infrastructure. + +From an operational perspective, Constellation provides the following key features: + +* **Native support for different clouds**: Constellation works on Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), and STACKIT. Support for OpenStack-based environments is coming with a future release. Constellation securely interfaces with the cloud infrastructure to provide [cluster autoscaling](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler), [dynamic persistent volumes](https://kubernetes.io/docs/concepts/storage/dynamic-provisioning/), and [service load balancing](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer). +* **High availability**: Constellation uses a [multi-master architecture](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/high-availability/) with a [stacked etcd topology](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/ha-topology/#stacked-etcd-topology) to ensure high availability. +* **Integrated Day-2 operations**: Constellation lets you securely [upgrade](../workflows/upgrade.md) your cluster to a new release. It also lets you securely [recover](../workflows/recovery.md) a failed cluster. Both with a single command. +* **Support for Terraform**: Constellation includes a [Terraform provider](../workflows/terraform-provider.md) that lets you manage the full lifecycle of your cluster via Terraform. diff --git a/docs/versioned_docs/version-2.18/overview/security-benefits.md b/docs/versioned_docs/version-2.18/overview/security-benefits.md new file mode 100644 index 000000000..51a8b64f5 --- /dev/null +++ b/docs/versioned_docs/version-2.18/overview/security-benefits.md @@ -0,0 +1,22 @@ +# Security benefits and threat model + +Constellation implements the [Confidential Kubernetes](confidential-kubernetes.md) concept and shields entire Kubernetes deployments from the infrastructure. More concretely, Constellation decreases the size of the trusted computing base (TCB) of a Kubernetes deployment. The TCB is the totality of elements in a computing environment that must be trusted not to be compromised. A smaller TCB results in a smaller attack surface. The following diagram shows how Constellation removes the *cloud & datacenter infrastructure* and the *physical hosts*, including the hypervisor, the host OS, and other components, from the TCB (red). Inside the confidential context (green), Kubernetes remains part of the TCB, but its integrity is attested and can be [verified](../workflows/verify-cluster.md). + +![TCB comparison](../_media/tcb.svg) + +Given this background, the following describes the concrete threat classes that Constellation addresses. + +## Insider access + +Employees and third-party contractors of cloud service providers (CSPs) have access to different layers of the cloud infrastructure. +This opens up a large attack surface where workloads and data can be read, copied, or manipulated. With Constellation, Kubernetes deployments are shielded from the infrastructure and thus such accesses are prevented. + +## Infrastructure-based attacks + +Malicious cloud users ("hackers") may break out of their tenancy and access other tenants' data. Advanced attackers may even be able to establish a permanent foothold within the infrastructure and access data over a longer period. Analogously to the *insider access* scenario, Constellation also prevents access to a deployment's data in this scenario. + +## Supply chain attacks + +Supply chain security is receiving lots of attention recently due to an [increasing number of recorded attacks](https://www.enisa.europa.eu/news/enisa-news/understanding-the-increase-in-supply-chain-security-attacks). For instance, a malicious actor could attempt to tamper Constellation node images (including Kubernetes and other software) before they're loaded in the confidential VMs of a cluster. Constellation uses [remote attestation](../architecture/attestation.md) in conjunction with public [transparency logs](../workflows/verify-cli.md) to prevent this. + +In the future, Constellation will extend this feature to customer workloads. This will enable cluster owners to create auditable policies that precisely define which containers can run in a given deployment. diff --git a/docs/versioned_docs/version-2.18/reference/cli.md b/docs/versioned_docs/version-2.18/reference/cli.md new file mode 100644 index 000000000..99acef520 --- /dev/null +++ b/docs/versioned_docs/version-2.18/reference/cli.md @@ -0,0 +1,844 @@ +# CLI reference + + + +Use the Constellation CLI to create and manage your clusters. + +Usage: + +``` +constellation [command] +``` +Commands: + +* [config](#constellation-config): Work with the Constellation configuration file + * [generate](#constellation-config-generate): Generate a default configuration and state file + * [fetch-measurements](#constellation-config-fetch-measurements): Fetch measurements for configured cloud provider and image + * [instance-types](#constellation-config-instance-types): Print the supported instance types for all cloud providers + * [kubernetes-versions](#constellation-config-kubernetes-versions): Print the Kubernetes versions supported by this CLI + * [migrate](#constellation-config-migrate): Migrate a configuration file to a new version +* [create](#constellation-create): Create instances on a cloud platform for your Constellation cluster +* [apply](#constellation-apply): Apply a configuration to a Constellation cluster +* [mini](#constellation-mini): Manage MiniConstellation clusters + * [up](#constellation-mini-up): Create and initialize a new MiniConstellation cluster + * [down](#constellation-mini-down): Destroy a MiniConstellation cluster +* [status](#constellation-status): Show status of a Constellation cluster +* [verify](#constellation-verify): Verify the confidential properties of a Constellation cluster +* [upgrade](#constellation-upgrade): Find and apply upgrades to your Constellation cluster + * [check](#constellation-upgrade-check): Check for possible upgrades + * [apply](#constellation-upgrade-apply): Apply an upgrade to a Constellation cluster +* [recover](#constellation-recover): Recover a completely stopped Constellation cluster +* [terminate](#constellation-terminate): Terminate a Constellation cluster +* [iam](#constellation-iam): Work with the IAM configuration on your cloud provider + * [create](#constellation-iam-create): Create IAM configuration on a cloud platform for your Constellation cluster + * [aws](#constellation-iam-create-aws): Create IAM configuration on AWS for your Constellation cluster + * [azure](#constellation-iam-create-azure): Create IAM configuration on Microsoft Azure for your Constellation cluster + * [gcp](#constellation-iam-create-gcp): Create IAM configuration on GCP for your Constellation cluster + * [destroy](#constellation-iam-destroy): Destroy an IAM configuration and delete local Terraform files + * [upgrade](#constellation-iam-upgrade): Find and apply upgrades to your IAM profile + * [apply](#constellation-iam-upgrade-apply): Apply an upgrade to an IAM profile +* [version](#constellation-version): Display version of this CLI +* [init](#constellation-init): Initialize the Constellation cluster + +## constellation config + +Work with the Constellation configuration file + +### Synopsis + +Work with the Constellation configuration file. + +### Options + +``` + -h, --help help for config +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config generate + +Generate a default configuration and state file + +### Synopsis + +Generate a default configuration and state file for your selected cloud provider. + +``` +constellation config generate {aws|azure|gcp|openstack|qemu|stackit} [flags] +``` + +### Options + +``` + -a, --attestation string attestation variant to use {aws-sev-snp|aws-nitro-tpm|azure-sev-snp|azure-tdx|azure-trustedlaunch|gcp-sev-snp|gcp-sev-es|qemu-vtpm}. If not specified, the default for the cloud provider is used + -h, --help help for generate + -k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR (default "v1.29") + -t, --tags strings additional tags for created resources given a list of key=value +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config fetch-measurements + +Fetch measurements for configured cloud provider and image + +### Synopsis + +Fetch measurements for configured cloud provider and image. + +A config needs to be generated first. + +``` +constellation config fetch-measurements [flags] +``` + +### Options + +``` + -h, --help help for fetch-measurements + -s, --signature-url string alternative URL to fetch measurements' signature from + -u, --url string alternative URL to fetch measurements from +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config instance-types + +Print the supported instance types for all cloud providers + +### Synopsis + +Print the supported instance types for all cloud providers. + +``` +constellation config instance-types [flags] +``` + +### Options + +``` + -h, --help help for instance-types +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config kubernetes-versions + +Print the Kubernetes versions supported by this CLI + +### Synopsis + +Print the Kubernetes versions supported by this CLI. + +``` +constellation config kubernetes-versions [flags] +``` + +### Options + +``` + -h, --help help for kubernetes-versions +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config migrate + +Migrate a configuration file to a new version + +### Synopsis + +Migrate a configuration file to a new version. + +``` +constellation config migrate [flags] +``` + +### Options + +``` + -h, --help help for migrate +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation create + +Create instances on a cloud platform for your Constellation cluster + +### Synopsis + +Create instances on a cloud platform for your Constellation cluster. + +``` +constellation create [flags] +``` + +### Options + +``` + -h, --help help for create + -y, --yes create the cluster without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation apply + +Apply a configuration to a Constellation cluster + +### Synopsis + +Apply a configuration to a Constellation cluster to initialize or upgrade the cluster. + +``` +constellation apply [flags] +``` + +### Options + +``` + --conformance enable conformance mode + -h, --help help for apply + --merge-kubeconfig merge Constellation kubeconfig file with default kubeconfig file in $HOME/.kube/config + --skip-helm-wait install helm charts without waiting for deployments to be ready + --skip-phases strings comma-separated list of upgrade phases to skip + one or multiple of { infrastructure | init | attestationconfig | certsans | helm | image | k8s } + -y, --yes run command without further confirmation + WARNING: the command might delete or update existing resources without additional checks. Please read the docs. + +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation mini + +Manage MiniConstellation clusters + +### Synopsis + +Manage MiniConstellation clusters. + +### Options + +``` + -h, --help help for mini +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation mini up + +Create and initialize a new MiniConstellation cluster + +### Synopsis + +Create and initialize a new MiniConstellation cluster. + +A mini cluster consists of a single control-plane and worker node, hosted using QEMU/KVM. + +``` +constellation mini up [flags] +``` + +### Options + +``` + -h, --help help for up + --merge-kubeconfig merge Constellation kubeconfig file with default kubeconfig file in $HOME/.kube/config (default true) +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation mini down + +Destroy a MiniConstellation cluster + +### Synopsis + +Destroy a MiniConstellation cluster. + +``` +constellation mini down [flags] +``` + +### Options + +``` + -h, --help help for down + -y, --yes terminate the cluster without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation status + +Show status of a Constellation cluster + +### Synopsis + +Show the status of a constellation cluster. + +Shows microservice, image, and Kubernetes versions installed in the cluster. Also shows status of current version upgrades. + +``` +constellation status [flags] +``` + +### Options + +``` + -h, --help help for status +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation verify + +Verify the confidential properties of a Constellation cluster + +### Synopsis + +Verify the confidential properties of a Constellation cluster. +If arguments aren't specified, values are read from `constellation-state.yaml`. + +``` +constellation verify [flags] +``` + +### Options + +``` + --cluster-id string expected cluster identifier + -h, --help help for verify + -e, --node-endpoint string endpoint of the node to verify, passed as HOST[:PORT] + -o, --output string print the attestation document in the output format {json|raw} +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation upgrade + +Find and apply upgrades to your Constellation cluster + +### Synopsis + +Find and apply upgrades to your Constellation cluster. + +### Options + +``` + -h, --help help for upgrade +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation upgrade check + +Check for possible upgrades + +### Synopsis + +Check which upgrades can be applied to your Constellation Cluster. + +``` +constellation upgrade check [flags] +``` + +### Options + +``` + -h, --help help for check + --ref string the reference to use for querying new versions (default "-") + --stream string the stream to use for querying new versions (default "stable") + -u, --update-config update the specified config file with the suggested versions +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation upgrade apply + +Apply an upgrade to a Constellation cluster + +### Synopsis + +Apply an upgrade to a Constellation cluster by applying the chosen configuration. + +``` +constellation upgrade apply [flags] +``` + +### Options + +``` + --conformance enable conformance mode + -h, --help help for apply + --skip-helm-wait install helm charts without waiting for deployments to be ready + --skip-phases strings comma-separated list of upgrade phases to skip + one or multiple of { infrastructure | helm | image | k8s } + -y, --yes run upgrades without further confirmation + WARNING: might delete your resources in case you are using cert-manager in your cluster. Please read the docs. + WARNING: might unintentionally overwrite measurements in the running cluster. +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation recover + +Recover a completely stopped Constellation cluster + +### Synopsis + +Recover a Constellation cluster by sending a recovery key to an instance in the boot stage. + +This is only required if instances restart without other instances available for bootstrapping. + +``` +constellation recover [flags] +``` + +### Options + +``` + -e, --endpoint string endpoint of the instance, passed as HOST[:PORT] + -h, --help help for recover +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation terminate + +Terminate a Constellation cluster + +### Synopsis + +Terminate a Constellation cluster. + +The cluster can't be started again, and all persistent storage will be lost. + +``` +constellation terminate [flags] +``` + +### Options + +``` + -h, --help help for terminate + -y, --yes terminate the cluster without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam + +Work with the IAM configuration on your cloud provider + +### Synopsis + +Work with the IAM configuration on your cloud provider. + +### Options + +``` + -h, --help help for iam +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam create + +Create IAM configuration on a cloud platform for your Constellation cluster + +### Synopsis + +Create IAM configuration on a cloud platform for your Constellation cluster. + +### Options + +``` + -h, --help help for create + --update-config update the config file with the specific IAM information + -y, --yes create the IAM configuration without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam create aws + +Create IAM configuration on AWS for your Constellation cluster + +### Synopsis + +Create IAM configuration on AWS for your Constellation cluster. + +``` +constellation iam create aws [flags] +``` + +### Options + +``` + -h, --help help for aws + --prefix string name prefix for all resources (required) + --zone string AWS availability zone the resources will be created in, e.g., us-east-2a (required) + See the Constellation docs for a list of currently supported regions. +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + --update-config update the config file with the specific IAM information + -C, --workspace string path to the Constellation workspace + -y, --yes create the IAM configuration without further confirmation +``` + +## constellation iam create azure + +Create IAM configuration on Microsoft Azure for your Constellation cluster + +### Synopsis + +Create IAM configuration on Microsoft Azure for your Constellation cluster. + +``` +constellation iam create azure [flags] +``` + +### Options + +``` + -h, --help help for azure + --region string region the resources will be created in, e.g., westus (required) + --resourceGroup string name prefix of the two resource groups your cluster / IAM resources will be created in (required) + --servicePrincipal string name of the service principal that will be created (required) + --subscriptionID string subscription ID of the Azure account. Required if the 'ARM_SUBSCRIPTION_ID' environment variable is not set +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + --update-config update the config file with the specific IAM information + -C, --workspace string path to the Constellation workspace + -y, --yes create the IAM configuration without further confirmation +``` + +## constellation iam create gcp + +Create IAM configuration on GCP for your Constellation cluster + +### Synopsis + +Create IAM configuration on GCP for your Constellation cluster. + +``` +constellation iam create gcp [flags] +``` + +### Options + +``` + -h, --help help for gcp + --projectID string ID of the GCP project the configuration will be created in (required) + Find it on the welcome screen of your project: https://console.cloud.google.com/welcome + --serviceAccountID string ID for the service account that will be created (required) + Must be 6 to 30 lowercase letters, digits, or hyphens. + --zone string GCP zone the cluster will be deployed in (required) + Find a list of available zones here: https://cloud.google.com/compute/docs/regions-zones#available +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + --update-config update the config file with the specific IAM information + -C, --workspace string path to the Constellation workspace + -y, --yes create the IAM configuration without further confirmation +``` + +## constellation iam destroy + +Destroy an IAM configuration and delete local Terraform files + +### Synopsis + +Destroy an IAM configuration and delete local Terraform files. + +``` +constellation iam destroy [flags] +``` + +### Options + +``` + -h, --help help for destroy + -y, --yes destroy the IAM configuration without asking for confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam upgrade + +Find and apply upgrades to your IAM profile + +### Synopsis + +Find and apply upgrades to your IAM profile. + +### Options + +``` + -h, --help help for upgrade +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam upgrade apply + +Apply an upgrade to an IAM profile + +### Synopsis + +Apply an upgrade to an IAM profile. + +``` +constellation iam upgrade apply [flags] +``` + +### Options + +``` + -h, --help help for apply + -y, --yes run upgrades without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation version + +Display version of this CLI + +### Synopsis + +Display version of this CLI. + +``` +constellation version [flags] +``` + +### Options + +``` + -h, --help help for version +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation init + +Initialize the Constellation cluster + +### Synopsis + +Initialize the Constellation cluster. + +Start your confidential Kubernetes. + +``` +constellation init [flags] +``` + +### Options + +``` + --conformance enable conformance mode + -h, --help help for init + --merge-kubeconfig merge Constellation kubeconfig file with default kubeconfig file in $HOME/.kube/config + --skip-helm-wait install helm charts without waiting for deployments to be ready +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + diff --git a/docs/versioned_docs/version-2.18/reference/migration.md b/docs/versioned_docs/version-2.18/reference/migration.md new file mode 100644 index 000000000..36680eef6 --- /dev/null +++ b/docs/versioned_docs/version-2.18/reference/migration.md @@ -0,0 +1,85 @@ +# Migrations + +This document describes breaking changes and migrations between Constellation releases. +Use [`constellation config migrate`](./cli.md#constellation-config-migrate) to automatically update an old config file to a new format. + +## Migrating from Azure's service principal authentication to managed identity authentication + +- The `provider.azure.appClientID` and `provider.azure.appClientSecret` fields are no longer supported and should be removed. +- To keep using an existing UAMI, add the `Owner` permission with the scope of your `resourceGroup`. +- Otherwise, simply [create new Constellation IAM credentials](../workflows/config.md#creating-an-iam-configuration) and use the created UAMI. +- To migrate the authentication for an existing cluster on Azure to an UAMI with the necessary permissions: + 1. Remove the `aadClientId` and `aadClientSecret` from the azureconfig secret. + 2. Set `useManagedIdentityExtension` to `true` and use the `userAssignedIdentity` from the Constellation config for the value of `userAssignedIdentityID`. + 3. Restart the CSI driver, cloud controller manager, cluster autoscaler, and Constellation operator pods. + + +## Migrating from CLI versions before 2.10 + +- AWS cluster upgrades require additional IAM permissions for the newly introduced `aws-load-balancer-controller`. Please upgrade your IAM roles using `iam upgrade apply`. This will show necessary changes and apply them, if desired. +- The global `nodeGroups` field was added. +- The fields `instanceType`, `stateDiskSizeGB`, and `stateDiskType` for each cloud provider are now part of the configuration of individual node groups. +- The `constellation create` command no longer uses the flags `--control-plane-count` and `--worker-count`. Instead, the initial node count is configured per node group in the `nodeGroups` field. + +## Migrating from CLI versions before 2.9 + +- The `provider.azure.appClientID` and `provider.azure.clientSecretValue` fields were removed to enforce migration to managed identity authentication + +## Migrating from CLI versions before 2.8 + +- The `measurements` field for each cloud service provider was replaced with a global `attestation` field. +- The `confidentialVM`, `idKeyDigest`, and `enforceIdKeyDigest` fields for the Azure cloud service provider were removed in favor of using the global `attestation` field. +- The optional global field `attestationVariant` was replaced by the now required `attestation` field. + +## Migrating from CLI versions before 2.3 + +- The `sshUsers` field was deprecated in v2.2 and has been removed from the configuration in v2.3. + As an alternative for SSH, check the workflow section [Connect to nodes](../workflows/troubleshooting.md#node-shell-access). +- The `image` field for each cloud service provider has been replaced with a global `image` field. Use the following mapping to migrate your configuration: +
+ Show all + + | CSP | old image | new image | + | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | + | AWS | `ami-06b8cbf4837a0a57c` | `v2.2.2` | + | AWS | `ami-02e96dc04a9e438cd` | `v2.2.2` | + | AWS | `ami-028ead928a9034b2f` | `v2.2.2` | + | AWS | `ami-032ac10dd8d8266e3` | `v2.2.1` | + | AWS | `ami-032e0d57cc4395088` | `v2.2.1` | + | AWS | `ami-053c3e49e19b96bdd` | `v2.2.1` | + | AWS | `ami-0e27ebcefc38f648b` | `v2.2.0` | + | AWS | `ami-098cd37f66523b7c3` | `v2.2.0` | + | AWS | `ami-04a87d302e2509aad` | `v2.2.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.2.2` | `v2.2.2` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.2.2` | `v2.2.2` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.2.1` | `v2.2.1` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.2.1` | `v2.2.1` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.2.0` | `v2.2.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.2.0` | `v2.2.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.1.0` | `v2.1.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.1.0` | `v2.1.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.0.0` | `v2.0.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.0.0` | `v2.0.0` | + | GCP | `projects/constellation-images/global/images/constellation-v2-2-2` | `v2.2.2` | + | GCP | `projects/constellation-images/global/images/constellation-v2-2-1` | `v2.2.1` | + | GCP | `projects/constellation-images/global/images/constellation-v2-2-0` | `v2.2.0` | + | GCP | `projects/constellation-images/global/images/constellation-v2-1-0` | `v2.1.0` | + | GCP | `projects/constellation-images/global/images/constellation-v2-0-0` | `v2.0.0` | +
+- The `enforcedMeasurements` field has been removed and merged with the `measurements` field. + - To migrate your config containing a new image (`v2.3` or greater), remove the old `measurements` and `enforcedMeasurements` entries from your config and run `constellation fetch-measurements` + - To migrate your config containing an image older than `v2.3`, remove the `enforcedMeasurements` entry and replace the entries in `measurements` as shown in the example below: + + ```diff + measurements: + - 0: DzXCFGCNk8em5ornNZtKi+Wg6Z7qkQfs5CfE3qTkOc8= + + 0: + + expected: DzXCFGCNk8em5ornNZtKi+Wg6Z7qkQfs5CfE3qTkOc8= + + warnOnly: true + - 8: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + + 8: + + expected: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + + warnOnly: false + -enforcedMeasurements: + - - 8 + ``` diff --git a/docs/versioned_docs/version-2.18/reference/slsa.md b/docs/versioned_docs/version-2.18/reference/slsa.md new file mode 100644 index 000000000..21f4e713c --- /dev/null +++ b/docs/versioned_docs/version-2.18/reference/slsa.md @@ -0,0 +1,73 @@ +# Supply chain levels for software artifacts (SLSA) adoption + +[Supply chain Levels for Software Artifacts, or SLSA (salsa)](https://slsa.dev/) is a framework for improving and grading a project's build system and engineering processes. SLSA focuses on security improvements for source code storage as well as build system definition, execution, and observation. SLSA is structured in [four levels](https://slsa.dev/spec/v0.1/levels). This page describes the adoption of SLSA for Constellation. + +:::info +SLSA is still in alpha status. The presented levels and their requirements might change in the future. We will adopt any changes into our engineering processes, as they get defined. +::: + +## Level 1 - Adopted + +**[Build - Scripted](https://slsa.dev/spec/v0.1/requirements#scripted-build)** + +All build steps are automated via [Bazel](https://github.com/edgelesssys/constellation/tree/main/bazel/ci) and [GitHub Actions](https://github.com/edgelesssys/constellation/tree/main/.github). + +**[Provenance - Available](https://slsa.dev/spec/v0.1/requirements#available)** + +Provenance for the CLI is generated using the [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator). + +## Level 2 - Adopted + +**[Source - Version Controlled](https://slsa.dev/spec/v0.1/requirements#version-controlled)** + +Constellation is hosted on GitHub using git. + +**[Build - Build Service](https://slsa.dev/spec/v0.1/requirements#build-service)** + +All builds are carried out by [GitHub Actions](https://github.com/edgelesssys/constellation/tree/main/.github). + +**[Provenance - Authenticated](https://slsa.dev/spec/v0.1/requirements#authenticated)** + +Provenance for the CLI is signed using the [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator). Learn [how to verify the CLI](../workflows/verify-cli.md) using the signed provenance, before using it for the first time. + +**[Provenance - Service Generated](https://slsa.dev/spec/v0.1/requirements#service-generated)** + +Provenance for the CLI is generated using the [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator) in GitHub Actions. + +## Level 3 - Adopted + +**[Source - Verified History](https://slsa.dev/spec/v0.1/requirements#verified-history)** + +The [Edgeless Systems](https://github.com/edgelesssys) GitHub organization [requires two-factor authentication](https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization) for all members. + +**[Source - Retained Indefinitely](https://slsa.dev/spec/v0.1/requirements#retained-indefinitely)** + +Since we use GitHub to host the repository, an external person can't modify or delete the history. Before a pull request can be merged, an explicit approval from an [Edgeless Systems](https://github.com/edgelesssys) team member is required. + +The same holds true for changes proposed by team members. Each change to `main` needs to be proposed via a pull request and requires at least one approval. + +The [Edgeless Systems](https://github.com/edgelesssys) GitHub organization admins control these settings and are able to make changes to the repository's history should legal requirements necessitate it. These changes require two-party approval following the obliterate policy. + +**[Build - Build as Code](https://slsa.dev/spec/v0.1/requirements#build-as-code)** + +All build files for Constellation are stored in [the same repository](https://github.com/edgelesssys/constellation/tree/main/.github). + +**[Build - Ephemeral Environment](https://slsa.dev/spec/v0.1/requirements#ephemeral-environment)** + +All GitHub Action workflows are executed on [GitHub-hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners). These runners are only available during workflow. + +We currently don't use [self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners). + +**[Build - Isolated](https://slsa.dev/spec/v0.1/requirements#isolated)** + +As outlined in the previous section, we use GitHub-hosted runners, which provide a new, isolated and ephemeral environment for each build. + +Additionally, the [SLSA GitHub generator](https://github.com/slsa-framework/slsa-github-generator#generation-of-provenance) itself is run in an isolated workflow with the artifact hash as defined inputs. + +**[Provenance - Non-falsifiable](https://slsa.dev/spec/v0.1/requirements#non-falsifiable)** + +As outlined by [SLSA GitHub generator](https://github.com/slsa-framework/slsa-github-generator) it already fulfills the non-falsifiable requirements for SLSA Level 3. The generated provenance is signed using [sigstore](https://sigstore.dev/) with an OIDC based proof of identity. + +## Level 4 - In Progress + +We strive to adopt certain aspect of SLSA Level 4 that support our engineering process. At the same time, SLSA is still in alpha status and the biggest changes to SLSA are expected to be around Level 4. diff --git a/docs/versioned_docs/version-2.18/reference/terraform.md b/docs/versioned_docs/version-2.18/reference/terraform.md new file mode 100644 index 000000000..9825a8bb8 --- /dev/null +++ b/docs/versioned_docs/version-2.18/reference/terraform.md @@ -0,0 +1,37 @@ +# Terraform usage + +[Terraform](https://www.terraform.io/) is an Infrastructure as Code (IaC) framework to manage cloud resources. This page explains how Constellation uses it internally and how advanced users may manually use it to have more control over the resource creation. + +:::info +Information on this page is intended for users who are familiar with Terraform. +It's not required for common usage of Constellation. +See the [Terraform documentation](https://developer.hashicorp.com/terraform/docs) if you want to learn more about it. +::: + +## Terraform state files + +Constellation keeps Terraform state files in subdirectories of the workspace together with the corresponding Terraform configuration files and metadata. +The subdirectories are created on the first Constellation CLI action that uses Terraform internally. + +Currently, these subdirectories are: + +* `constellation-terraform` - Terraform state files for the resources of the Constellation cluster +* `constellation-iam-terraform` - Terraform state files for IAM configuration + +As with all commands, commands that work with these files (e.g., `apply`, `terminate`, `iam`) have to be executed from the root of the cluster's [workspace directory](../architecture/orchestration.md#workspaces). You usually don't need and shouldn't manipulate or delete the subdirectories manually. + +## Interacting with Terraform manually + +Manual interaction with Terraform state created by Constellation (i.e., via the Terraform CLI) should only be performed by experienced users. It may lead to unrecoverable loss of cloud resources. For the majority of users and use cases, the interaction done by the [Constellation CLI](cli.md) is sufficient. + +## Terraform debugging + +To debug Terraform issues, the Constellation CLI offers the `tf-log` flag. You can set it to any of [Terraform's log levels](https://developer.hashicorp.com/terraform/internals/debugging): +* `JSON` (JSON-formatted logs at `TRACE` level) +* `TRACE` +* `DEBUG` +* `INFO` +* `WARN` +* `ERROR` + +The log output is written to the `terraform.log` file in the workspace directory. The output is appended to the file on each run. diff --git a/docs/versioned_docs/version-2.18/workflows/cert-manager.md b/docs/versioned_docs/version-2.18/workflows/cert-manager.md new file mode 100644 index 000000000..1d847e8bf --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/cert-manager.md @@ -0,0 +1,13 @@ +# Install cert-manager + +:::caution +If you want to use cert-manager with Constellation, pay attention to the following to avoid potential pitfalls. +::: + +Constellation ships with cert-manager preinstalled. +The default installation is part of the `kube-system` namespace, as all other Constellation-managed microservices. +You are free to install more instances of cert-manager into other namespaces. +However, be aware that any new installation needs to use the same version as the one installed with Constellation or rely on the same CRD versions. +Also remember to set the `installCRDs` value to `false` when installing new cert-manager instances. +It will create problems if you have two installations of cert-manager depending on different versions of the installed CRDs. +CRDs are cluster-wide resources and cert-manager depends on specific versions of those CRDs for each release. diff --git a/docs/versioned_docs/version-2.18/workflows/config.md b/docs/versioned_docs/version-2.18/workflows/config.md new file mode 100644 index 000000000..95f791acd --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/config.md @@ -0,0 +1,353 @@ +# Configure your cluster + +:::info +This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. +::: + + + +--- + +Before you can create your cluster, you need to configure the identity and access management (IAM) for your cloud service provider (CSP) and choose machine types for the nodes. + +## Creating the configuration file + +You can generate a configuration file for your CSP by using the following CLI command: + + + + +```bash +constellation config generate aws +``` + + + + +```bash +constellation config generate azure +``` + + + + +```bash +constellation config generate gcp +``` + + + + +```bash +constellation config generate stackit +``` + + + + +This creates the file `constellation-conf.yaml` in the current directory. + +## Choosing a VM type + +Constellation supports the following VM types: + + + +By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. +Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. +If you are using the default attestation variant `awsSEVSNP`, you can use the instance types described in [AWS's AMD SEV-SNP docs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/snp-requirements.html). +Please mind the region restrictions mentioned in the [Getting started](../getting-started/first-steps.md#create-a-cluster) section. + +If you are using the attestation variant `awsNitroTPM`, you can choose any of the [nitroTPM-enabled instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-prerequisites.html). + +The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. + + + + +By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. + +You can also run `constellation config instance-types` to get the list of all supported options. + + + + +By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. + + + + +By default, Constellation uses `m1a.4cd` VMs (4 vCPUs, 30 GB RAM) to create your cluster. +Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. + +The following instance types are known to be supported: + +| name | vCPUs | GB RAM | +|----------|-------|--------| +| m1a.4cd | 4 | 30 | +| m1a.8cd | 8 | 60 | +| m1a.16cd | 16 | 120 | +| m1a.30cd | 30 | 230 | + +You can choose any of the SEV-enabled instance types. You can find a list of all supported instance types in the [STACKIT documentation](https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html). + +The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. + + + + +Fill the desired VM type into the `instanceType` fields in the `constellation-conf.yml` file. + +## Creating additional node groups + +By default, Constellation creates the node groups `control_plane_default` and `worker_default` for control-plane nodes and workers, respectively. +If you require additional control-plane or worker groups with different instance types, zone placements, or disk sizes, you can add additional node groups to the `constellation-conf.yml` file. +Each node group can be scaled individually. + +Consider the following example for AWS: + +```yaml +nodeGroups: + control_plane_default: + role: control-plane + instanceType: c6a.xlarge + stateDiskSizeGB: 30 + stateDiskType: gp3 + zone: eu-west-1c + initialCount: 3 + worker_default: + role: worker + instanceType: c6a.xlarge + stateDiskSizeGB: 30 + stateDiskType: gp3 + zone: eu-west-1c + initialCount: 2 + high_cpu: + role: worker + instanceType: c6a.24xlarge + stateDiskSizeGB: 128 + stateDiskType: gp3 + zone: eu-west-1c + initialCount: 1 +``` + +This configuration creates an additional node group `high_cpu` with a larger instance type and disk. + +You can use the field `zone` to specify what availability zone nodes of the group are placed in. +On Azure, this field is empty by default and nodes are automatically spread across availability zones. +STACKIT currently offers SEV-enabled CPUs in the `eu01-1`, `eu01-2`, and `eu01-3` zones. +Consult the documentation of your cloud provider for more information: + +* [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) +* [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) +* [GCP](https://cloud.google.com/compute/docs/regions-zones) +* [STACKIT](https://docs.stackit.cloud/stackit/en/regions-and-availability-zones-75137212.html) + +## Choosing a Kubernetes version + +To learn which Kubernetes versions can be installed with your current CLI, you can run `constellation config kubernetes-versions`. +See also Constellation's [Kubernetes support policy](../architecture/versions.md#kubernetes-support-policy). + +## Creating an IAM configuration + +You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. +If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. + + + + +You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). + +```bash +constellation iam create aws --zone=us-east-2a --prefix=constellTest +``` + +This command creates IAM configuration for the AWS zone `us-east-2a` using the prefix `constellTest` for all named resources being created. + +Constellation OS images are currently replicated to the following regions: + +* `eu-central-1` +* `eu-west-1` +* `eu-west-3` +* `us-east-2` +* `ap-south-1` + +If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+AWS+image+region:+xx-xxxx-x). + +You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). + +Paste the output into the corresponding fields of the `constellation-conf.yaml` file. + + + + +You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). + +```bash +constellation iam create azure --subscriptionID 00000000-0000-0000-0000-000000000000 --region=westus --resourceGroup=constellTest --servicePrincipal=spTest +``` + +This command creates IAM configuration on the Azure region `westus` creating a new resource group `constellTest` and a new service principal `spTest`. + +CVMs are available in several Azure regions. Constellation OS images are currently replicated to the following: + +* `germanywestcentral` +* `westus` +* `eastus` +* `northeurope` +* `westeurope` +* `southeastasia` + +If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+Azure+image+region:+xx-xxxx-x). + +You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). + +Paste the output into the corresponding fields of the `constellation-conf.yaml` file. + + + + +You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). + +```bash +constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test +``` + +This command creates IAM configuration in the GCP project `yourproject-12345` on the GCP zone `europe-west2-a` creating a new service account `constell-test`. + +Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `N2D`. + +Paste the output into the corresponding fields of the `constellation-conf.yaml` file. + + + + +STACKIT requires manual creation and configuration of service accounts. Look at the [first steps](../getting-started/first-steps.md) for more information. + + + + +
+Alternatively, you can manually create the IAM configuration on your CSP. + +The following describes the configuration fields and how you obtain the required information or create the required resources. + + + + +* **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. + + Constellation OS images are currently replicated to the following regions: + * `eu-central-1` + * `eu-west-1` + * `eu-west-3` + * `us-east-2` + * `ap-south-1` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+AWS+image+region:+xx-xxxx-x). + + You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). + +* **zone**: The name of your chosen AWS data center availability zone, e.g., `us-east-2a`. + + Learn more about [availability zones in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-availability-zones). + +* **iamProfileControlPlane**: The name of an IAM instance profile attached to all control-plane nodes. + + You can create the resource with [Terraform](https://www.terraform.io/). For that, use the [provided Terraform script](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam) to generate the necessary profile. The profile name will be provided as Terraform output value: `control_plane_instance_profile_name`. + + Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.control_plane_policy`. + +* **iamProfileWorkerNodes**: The name of an IAM instance profile attached to all worker nodes. + + You can create the resource with [Terraform](https://www.terraform.io/). For that, use the [provided Terraform script](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam) to generate the necessary profile. The profile name will be provided as Terraform output value: `worker_nodes_instance_profile_name`. + + Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. + + + + +* **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. + + You can view your subscription UUID via `az account show` and read the `id` field. For more information refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-subscription). + +* **tenant**: The UUID of your Azure tenant, e.g., `3400e5a2-8fe2-492a-886c-38cb66170f25`. + + You can view your tenant UUID via `az account show` and read the `tenant` field. For more information refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-ad-tenant). + +* **location**: The Azure datacenter location you want to deploy your cluster in, e.g., `westus`. + + CVMs are available in several Azure regions. Constellation OS images are currently replicated to the following: + + * `germanywestcentral` + * `westus` + * `eastus` + * `northeurope` + * `westeurope` + * `southeastasia` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+Azure+image+region:+xx-xxxx-x). + + You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). + +* **resourceGroup**: [Create a new resource group in Azure](https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal) for your Constellation cluster. Set this configuration field to the name of the created resource group. + +* **userAssignedIdentity**: [Create a new managed identity in Azure](https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). You should create the identity in a different resource group as all resources within the cluster resource group will be deleted on cluster termination. + + Add three role assignments to the identity: `Owner`, `Virtual Machine Contributor`, and `Application Insights Component Contributor`. The `scope` of all three should refer to the previously created cluster resource group. + + Set the configuration value to the full ID of the created identity, e.g., `/subscriptions/8b8bd01f-efd9-4113-9bd1-c82137c32da7/resourcegroups/constellation-identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/constellation-identity`. You can get it by opening the `JSON View` from the `Overview` section of the identity. + + The user-assigned identity is used by instances of the cluster to access other cloud resources. + For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). + + + + +* **project**: The ID of your GCP project, e.g., `constellation-129857`. + + You can find it on the [welcome screen of your GCP project](https://console.cloud.google.com/welcome). For more information refer to [Google's documentation](https://support.google.com/googleapi/answer/7014113). + +* **region**: The GCP region you want to deploy your cluster in, e.g., `us-west1`. + + You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available). + +* **zone**: The GCP zone you want to deploy your cluster in, e.g., `us-west1-a`. + + You can find a [list of all zones in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available). + +* **serviceAccountKeyPath**: To configure this, you need to create a GCP [service account](https://cloud.google.com/iam/docs/service-accounts) with the following permissions: + + * `Compute Instance Admin (v1) (roles/compute.instanceAdmin.v1)` + * `Compute Network Admin (roles/compute.networkAdmin)` + * `Compute Security Admin (roles/compute.securityAdmin)` + * `Compute Storage Admin (roles/compute.storageAdmin)` + * `Service Account User (roles/iam.serviceAccountUser)` + + Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. + + + + +STACKIT requires manual creation and configuration of service accounts. Look at the [first steps](../getting-started/first-steps.md) for more information. + + + +
+ +Now that you've configured your CSP, you can [create your cluster](./create.md). + +## Deleting an IAM configuration + +You can keep a created IAM configuration and reuse it for new clusters. Alternatively, you can also delete it if you don't want to use it anymore. + +Delete the IAM configuration by executing the following command in the same directory where you executed `constellation iam create` (the directory that contains [`constellation-iam-terraform`](../reference/terraform.md) as a subdirectory): + +```bash +constellation iam destroy +``` + +:::caution +For Azure, deleting the IAM configuration by executing `constellation iam destroy` will delete the whole resource group created by `constellation iam create`. +This also includes any additional resources in the resource group that weren't created by Constellation. +::: diff --git a/docs/versioned_docs/version-2.18/workflows/create.md b/docs/versioned_docs/version-2.18/workflows/create.md new file mode 100644 index 000000000..6074ebb16 --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/create.md @@ -0,0 +1,93 @@ +# Create your cluster + +:::info +This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. +::: + + + +--- + +Creating your cluster happens through multiple phases. +The most significant ones are: + +1. Creating the necessary resources in your cloud environment +2. Bootstrapping the Constellation cluster and setting up a connection +3. Installing the necessary Kubernetes components + +`constellation apply` handles all this in a single command. +You can use the `--skip-phases` flag to skip specific phases of the process. +For example, if you created the infrastructure manually, you can skip the cloud resource creation phase. + +See the [architecture](../architecture/orchestration.md) section for details on the inner workings of this process. + +:::tip +If you don't have a cloud subscription, you can also set up a [local Constellation cluster using virtualization](../getting-started/first-steps-local.md) for testing. +::: + +Before you create the cluster, make sure to have a [valid configuration file](./config.md). + + + + +```bash +constellation apply +``` + +`apply` stores the state of your cluster's cloud resources in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. + + + + +Self-managed infrastructure allows for more flexibility in the setup, by separating the infrastructure setup from the Constellation cluster management. +This provides flexibility in DevOps and can meet potential regulatory requirements. +It's recommended to use Terraform for infrastructure management, but you can use any tool of your choice. + +:::info + + When using Terraform, you can use the [Constellation Terraform provider](./terraform-provider.md) to manage the entire Constellation cluster lifecycle. + +::: + +You can refer to the Terraform files for the selected CSP from the [Constellation GitHub repository](https://github.com/edgelesssys/constellation/tree/main/terraform/infrastructure) for a minimum Constellation cluster configuration. From this base, you can now add, edit, or substitute resources per your own requirements with the infrastructure +management tooling of your choice. You need to keep the essential functionality of the base configuration in order for your cluster to function correctly. + + + +:::info + + On Azure, a manual update to the MAA provider's policy is necessary. + You can apply the update with the following command after creating the infrastructure, with `` being the URL of the MAA provider (i.e., `$(terraform output attestation_url | jq -r)`, when using the minimal Terraform configuration). + + ```bash + constellation maa-patch + ``` + +::: + + + +Make sure all necessary resources are created, e.g., through checking your CSP's portal and retrieve the necessary values, aligned with the outputs (specified in `outputs.tf`) of the base configuration. + +Fill these outputs into the corresponding fields of the `Infrastructure` block inside the `constellation-state.yaml` file. For example, fill the IP or DNS name your cluster can be reached at into the `.Infrastructure.ClusterEndpoint` field. + +With the required cloud resources set up, continue with initializing your cluster. + +```bash +constellation apply --skip-phases=infrastructure +``` + + + + +Finally, configure `kubectl` for your cluster: + +```bash +export KUBECONFIG="$PWD/constellation-admin.conf" +``` + +🏁 That's it. You've successfully created a Constellation cluster. + +### Troubleshooting + +In case `apply` fails, the CLI collects logs from the bootstrapping instance and stores them inside `constellation-cluster.log`. diff --git a/docs/versioned_docs/version-2.18/workflows/lb.md b/docs/versioned_docs/version-2.18/workflows/lb.md new file mode 100644 index 000000000..868e61076 --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/lb.md @@ -0,0 +1,28 @@ +# Expose a service + +Constellation integrates the native load balancers of each CSP. Therefore, to expose a service simply [create a service of type `LoadBalancer`](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer). + +## Internet-facing LB service on AWS + +To expose your application service externally you might want to use a Kubernetes Service of type `LoadBalancer`. On AWS, load-balancing is achieved through the [AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller) as in the managed EKS. + +Since recent versions, the controller deploy an internal LB by default requiring to set an annotation `service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing` to have an internet-facing LB. For more details, see the [official docs](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/guide/service/nlb/). + +For general information on LB with AWS see [Network load balancing on Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/network-load-balancing.html). + +:::caution +Before terminating the cluster, all LB backed services should be deleted, so that the controller can cleanup the related resources. +::: + +## Ingress on AWS + +The AWS Load Balancer Controller also provisions `Ingress` resources of class `alb`. +AWS Application Load Balancers (ALBs) can be configured with a [`target-type`](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/guide/ingress/annotations/#target-type). +The target type `ip` requires using the EKS container network solution, which makes it incompatible with Constellation. +If a service can be exposed on a `NodePort`, the target type `instance` can be used. + +See [Application load balancing on Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html) for more information. + +:::caution +Ingress handlers backed by AWS ALBs reside outside the Constellation cluster, so they shouldn't be handling sensitive traffic! +::: diff --git a/docs/versioned_docs/version-2.18/workflows/recovery.md b/docs/versioned_docs/version-2.18/workflows/recovery.md new file mode 100644 index 000000000..592ae247b --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/recovery.md @@ -0,0 +1,179 @@ +# Recover your cluster + +Recovery of a Constellation cluster means getting it back into a healthy state after too many concurrent node failures in the control plane. +Reasons for an unhealthy cluster can vary from a power outage, or planned reboot, to migration of nodes and regions. +Recovery events are rare, because Constellation is built for high availability and automatically and securely replaces failed nodes. When a node is replaced, Constellation's control plane first verifies the new node before it sends the node the cryptographic keys required to decrypt its [state disk](../architecture/images.md#state-disk). + +Constellation provides a recovery mechanism for cases where the control plane has failed and is unable to replace nodes. +The `constellation recover` command securely connects to all nodes in need of recovery using [attested TLS](../architecture/attestation.md#attested-tls-atls) and provides them with the keys to decrypt their state disks and continue booting. + +## Identify unhealthy clusters + +The first step to recovery is identifying when a cluster becomes unhealthy. +Usually, this can be first observed when the Kubernetes API server becomes unresponsive. + +You can check the health status of the nodes via the cloud service provider (CSP). +Constellation provides logging information on the boot process and status via serial console output. +In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. + + + + +First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. + +Second, check the boot logs of these *Instances*. In the ASG's *Instance management* view, select each desired instance. In the upper right corner, select **Action > Monitor and troubleshoot > Get system log**. + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"gcp"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["192.168.178.4:30090","192.168.178.2:30090"]} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.4:30090"} +{"level":"WARN","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.4:30090: connect: connection refused\"","endpoint":"192.168.178.4:30090"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.2:30090"} +{"level":"WARN","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.2:30090: i/o timeout\"","endpoint":"192.168.178.2:30090"} +{"level":"ERROR","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +In the Azure portal, find the cluster's resource group. +Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. +On the left, go to **Settings** > **Instances** and check that enough members are in a *Running* state. + +Second, check the boot logs of these *Instances*. +In the scale set's *Instances* view, open the details page of the desired instance. +On the left, go to **Support + troubleshooting** > **Serial console**. + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T09:56:41Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"azure"} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["10.9.0.5:30090","10.9.0.6:30090"]} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"10.9.0.5:30090"} +{"level":"WARN","ts":"2022-09-08T09:57:03Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 10.9.0.5:30090: i/o timeout\"","endpoint":"10.9.0.5:30090"} +{"level":"INFO","ts":"2022-09-08T09:57:03Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"10.9.0.6:30090"} +{"level":"WARN","ts":"2022-09-08T09:57:23Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 10.9.0.6:30090: i/o timeout\"","endpoint":"10.9.0.6:30090"} +{"level":"ERROR","ts":"2022-09-08T09:57:23Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +First, check that the control plane *Instance Group* has enough members in a *Ready* state. +In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. + +Second, check the status of the *VM Instances*. +Go to **VM Instances** and open the details of the desired instance. +Check the serial console output of that instance by opening the **Logs** > **Serial port 1 (console)** page: + +![GCP portal serial console link](../_media/recovery-gcp-serial-console-link.png) + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"gcp"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["192.168.178.4:30090","192.168.178.2:30090"]} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.4:30090"} +{"level":"WARN","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.4:30090: connect: connection refused\"","endpoint":"192.168.178.4:30090"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.2:30090"} +{"level":"WARN","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.2:30090: i/o timeout\"","endpoint":"192.168.178.2:30090"} +{"level":"ERROR","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +First, open the STACKIT portal to view all servers in your project. Select individual control plane nodes `--control-plane--` and check that enough members are in a *Running* state. + +Second, check the boot logs of these servers. Click on a server name and select **Overview**. Find the **Machine Setup** section and click on **Web console** > **Open console**. + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"gcp"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["192.168.178.4:30090","192.168.178.2:30090"]} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.4:30090"} +{"level":"WARN","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.4:30090: connect: connection refused\"","endpoint":"192.168.178.4:30090"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.2:30090"} +{"level":"WARN","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.2:30090: i/o timeout\"","endpoint":"192.168.178.2:30090"} +{"level":"ERROR","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +## Recover a cluster + +Recovering a cluster requires the following parameters: + +* The `constellation-state.yaml` file in your working directory or the cluster's endpoint +* The master secret of the cluster + +A cluster can be recovered like this: + +```bash +$ constellation recover +Pushed recovery key. +Pushed recovery key. +Pushed recovery key. +Recovered 3 control-plane nodes. +``` + +In the serial console output of the node you'll see a similar output to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:26:59Z","logger":"recoveryServer","caller":"recoveryserver/server.go:93","msg":"Received recover call"} +{"level":"INFO","ts":"2022-09-08T10:26:59Z","logger":"recoveryServer","caller":"recoveryserver/server.go:125","msg":"Received state disk key and measurement secret, shutting down server"} +{"level":"INFO","ts":"2022-09-08T10:26:59Z","logger":"recoveryServer.gRPC","caller":"zap/server_interceptors.go:61","msg":"finished streaming call with code OK","grpc.start_time":"2022-09-08T10:26:59Z","system":"grpc","span.kind":"server","grpc.service":"recoverproto.API","grpc.method":"Recover","peer.address":"192.0.2.3:41752","grpc.code":"OK","grpc.time_ms":15.701} +{"level":"INFO","ts":"2022-09-08T10:27:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:87","msg":"RejoinClient stopped"} +``` diff --git a/docs/versioned_docs/version-2.18/workflows/s3proxy.md b/docs/versioned_docs/version-2.18/workflows/s3proxy.md new file mode 100644 index 000000000..121e8a461 --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/s3proxy.md @@ -0,0 +1,58 @@ +# Install s3proxy + +Constellation includes a transparent client-side encryption proxy for [AWS S3](https://aws.amazon.com/de/s3/) and compatible stores. +s3proxy encrypts objects before sending them to S3 and automatically decrypts them on retrieval, without requiring changes to your application. +With s3proxy, you can use S3 for storage in a confidential way without having to trust the storage provider. + +## Limitations + +Currently, s3proxy has the following limitations: +- Only `PutObject` and `GetObject` requests are encrypted/decrypted by s3proxy. +By default, s3proxy will block requests that may expose unencrypted data to S3 (e.g. UploadPart). +The `allow-multipart` flag disables request blocking for evaluation purposes. +- Using the [Range](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html#API_GetObject_RequestSyntax) header on `GetObject` is currently not supported and will result in an error. + +These limitations will be removed with future iterations of s3proxy. +If you want to use s3proxy but these limitations stop you from doing so, consider [opening an issue](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&projects=&template=feature_request.yml). + +## Deployment + +You can add the s3proxy to your Constellation cluster as follows: +1. Add the Edgeless Systems chart repository: + ```bash + helm repo add edgeless https://helm.edgeless.systems/stable + helm repo update + ``` +2. Set ACCESS_KEY and ACCESS_SECRET to valid credentials you want s3proxy to use to interact with S3. +3. Deploy s3proxy: + ```bash + helm install s3proxy edgeless/s3proxy --set awsAccessKeyID="$ACCESS_KEY" --set awsSecretAccessKey="$ACCESS_SECRET" + ``` + +If you want to run a demo application, check out the [Filestash with s3proxy](../getting-started/examples/filestash-s3proxy.md) example. + + +## Technical details + +### Encryption + +s3proxy relies on Google's [Tink Cryptographic Library](https://developers.google.com/tink) to implement cryptographic operations securely. +The used cryptographic primitives are [NIST SP 800 38f](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf) for key wrapping and [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)-[GCM](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Galois/counter_(GCM)) with 256 bit keys for data encryption. + +s3proxy uses [envelope encryption](https://cloud.google.com/kms/docs/envelope-encryption) to encrypt objects. +This means s3proxy uses a key encryption key (KEK) issued by the [KeyService](../architecture/microservices.md#keyservice) to encrypt data encryption keys (DEKs). +Each S3 object is encrypted with its own DEK. +The encrypted DEK is then saved as metadata of the encrypted object. +This enables key rotation of the KEK without re-encrypting the data in S3. +The approach also allows access to objects from different locations, as long as each location has access to the KEK. + +### Traffic interception + +To use s3proxy, you have to redirect your outbound S3 traffic to s3proxy. +This can either be done by modifying your client application or by changing the deployment of your application. + +The necessary deployment modifications are to add DNS redirection and a trusted TLS certificate to the client's trust store. +DNS redirection can be defined for each pod, allowing you to use s3proxy for one application without changing other applications in the same cluster. +Adding a trusted TLS certificate is necessary as clients communicate with s3proxy via HTTPS. +To have your client application trust s3proxy's TLS certificate, the certificate has to be added to the client's certificate trust store. +The [Filestash with s3proxy](../getting-started/examples/filestash-s3proxy.md) example shows how to do this. diff --git a/docs/versioned_docs/version-2.18/workflows/sbom.md b/docs/versioned_docs/version-2.18/workflows/sbom.md new file mode 100644 index 000000000..6c1702dee --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/sbom.md @@ -0,0 +1,93 @@ +# Consume software bill of materials (SBOMs) + + + +--- + +Constellation builds produce a [software bill of materials (SBOM)](https://www.ntia.gov/SBOM) for each generated [artifact](../architecture/microservices.md). +You can use SBOMs to make informed decisions about dependencies and vulnerabilities in a given application. Enterprises rely on SBOMs to maintain an inventory of used applications, which allows them to take data-driven approaches to managing risks related to vulnerabilities. + +SBOMs for Constellation are generated using [Syft](https://github.com/anchore/syft), signed using [Cosign](https://github.com/sigstore/cosign), and stored with the produced artifact. + +:::note +The public key for Edgeless Systems' long-term code-signing key is: + +``` +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT +JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== +-----END PUBLIC KEY----- +``` + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +Make sure the key is available in a file named `cosign.pub` to execute the following examples. +::: + +## Verify and download SBOMs + +The following sections detail how to work with each type of artifact to verify and extract the SBOM. + +### Constellation CLI + +The SBOM for Constellation CLI is made available on the [GitHub release page](https://github.com/edgelesssys/constellation/releases). The SBOM (`constellation.spdx.sbom`) and corresponding signature (`constellation.spdx.sbom.sig`) are valid for each Constellation CLI for a given version, regardless of architecture and operating system. + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/download/v2.2.0/constellation.spdx.sbom +curl -LO https://github.com/edgelesssys/constellation/releases/download/v2.2.0/constellation.spdx.sbom.sig +cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig constellation.spdx.sbom +``` + +### Container Images + +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. + +As a consumer, use cosign to download and verify the SBOM: + +```bash +# Verify and download the attestation statement +cosign verify-attestation ghcr.io/edgelesssys/constellation/verification-service@v2.2.0 --type 'https://cyclonedx.org/bom' --key cosign.pub --output-file verification-service.att.json +# Extract SBOM from attestation statement +jq -r .payload verification-service.att.json | base64 -d > verification-service.cyclonedx.sbom +``` + +A successful verification should result in similar output: + +```shell-session +$ cosign verify-attestation ghcr.io/edgelesssys/constellation/verification-service@v2.2.0 --type 'https://cyclonedx.org/bom' --key cosign.pub --output-file verification-service.sbom + +Verification for ghcr.io/edgelesssys/constellation/verification-service@v2.2.0 -- +The following checks were performed on each of these signatures: + - The cosign claims were validated + - The signatures were verified against the specified public key +$ jq -r .payload verification-service.sbom | base64 -d > verification-service.cyclonedx.sbom +``` + +:::note + +This example considers only the `verification-service`. The same approach works for all containers in the [Constellation container registry](https://github.com/orgs/edgelesssys/packages?repo_name=constellation). + +::: + + + +## Vulnerability scanning + +You can use a plethora of tools to consume SBOMs. This section provides suggestions for tools that are popular and known to produce reliable results, but any tool that consumes [SPDX](https://spdx.dev/) or [CycloneDX](https://cyclonedx.org/) files should work. + +Syft is able to [convert between the two formats](https://github.com/anchore/syft#format-conversion-experimental) in case you require a specific type. + +### Grype + +[Grype](https://github.com/anchore/grype) is a CLI tool that lends itself well for integration into CI/CD systems or local developer machines. It's also able to consume the signed attestation statement directly and does the verification in one go. + +```bash +grype att:verification-service.sbom --key cosign.pub --add-cpes-if-none -q +``` + +### Dependency Track + +[Dependency Track](https://dependencytrack.org/) is one of the oldest and most mature solutions when it comes to managing software inventory and vulnerabilities. Once imported, it continuously scans SBOMs for new vulnerabilities. It supports the CycloneDX format and provides direct guidance on how to comply with [U.S. Executive Order 14028](https://docs.dependencytrack.org/usage/executive-order-14028/). diff --git a/docs/versioned_docs/version-2.18/workflows/scale.md b/docs/versioned_docs/version-2.18/workflows/scale.md new file mode 100644 index 000000000..28f19e3f1 --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/scale.md @@ -0,0 +1,122 @@ +# Scale your cluster + +Constellation provides all features of a Kubernetes cluster including scaling and autoscaling. + +## Worker node scaling + +### Autoscaling + +Constellation comes with autoscaling disabled by default. To enable autoscaling, find the scaling group of +worker nodes: + +```bash +kubectl get scalinggroups -o json | yq '.items | .[] | select(.spec.role == "Worker") | [{"name": .metadata.name, "nodeGoupName": .spec.nodeGroupName}]' +``` + +This will output a list of scaling groups with the corresponding cloud provider name (`name`) and the cloud provider agnostic name of the node group (`nodeGroupName`). + +Then, patch the `autoscaling` field of the scaling group resource with the desired `name` to `true`: + +```bash +# Replace with the name of the scaling group you want to enable autoscaling for +worker_group= +kubectl patch scalinggroups $worker_group --patch '{"spec":{"autoscaling": true}}' --type='merge' +kubectl get scalinggroup $worker_group -o jsonpath='{.spec}' | yq -P +``` + +The cluster autoscaler now automatically provisions additional worker nodes so that all pods have a place to run. +You can configure the minimum and maximum number of worker nodes in the scaling group by patching the `min` or +`max` fields of the scaling group resource: + +```bash +kubectl patch scalinggroups $worker_group --patch '{"spec":{"max": 5}}' --type='merge' +kubectl get scalinggroup $worker_group -o jsonpath='{.spec}' | yq -P +``` + +The cluster autoscaler will now never provision more than 5 worker nodes. + +If you want to see the autoscaling in action, try to add a deployment with a lot of replicas, like the +following Nginx deployment. The number of replicas needed to trigger the autoscaling depends on the size of +and count of your worker nodes. Wait for the rollout of the deployment to finish and compare the number of +worker nodes before and after the deployment: + +```bash +kubectl create deployment nginx --image=nginx --replicas 150 +kubectl -n kube-system get nodes +kubectl rollout status deployment nginx +kubectl -n kube-system get nodes +``` + +### Manual scaling + +Alternatively, you can manually scale your cluster up or down: + + + + +1. Go to Auto Scaling Groups and select the worker ASG to scale up. +2. Click **Edit** +3. Set the new (increased) **Desired capacity** and **Update**. + + + + +1. Find your Constellation resource group. +2. Select the `scale-set-workers`. +3. Go to **settings** and **scaling**. +4. Set the new **instance count** and **save**. + + + + +1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). +2. **Edit** the **worker** instance group. +3. Set the new **number of instances** and **save**. + + + + +Dynamic cluster scaling isn't yet supported for STACKIT. +Support will be introduced in one of the upcoming releases. + + + + +## Control-plane node scaling + +Control-plane nodes can **only be scaled manually and only scaled up**! + +To increase the number of control-plane nodes, follow these steps: + + + + +1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. +2. Click **Edit** +3. Set the new (increased) **Desired capacity** and **Update**. + + + + +1. Find your Constellation resource group. +2. Select the `scale-set-controlplanes`. +3. Go to **settings** and **scaling**. +4. Set the new (increased) **instance count** and **save**. + + + + +1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). +2. **Edit** the **control-plane** instance group. +3. Set the new (increased) **number of instances** and **save**. + + + + +Dynamic cluster scaling isn't yet supported for STACKIT. +Support will be introduced in one of the upcoming releases. + + + + +If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.18/workflows/storage.md b/docs/versioned_docs/version-2.18/workflows/storage.md new file mode 100644 index 000000000..a5c52be90 --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/storage.md @@ -0,0 +1,281 @@ +# Use persistent storage + +Persistent storage in Kubernetes requires cloud-specific configuration. +For abstraction of container storage, Kubernetes offers [volumes](https://kubernetes.io/docs/concepts/storage/volumes/), +allowing users to mount storage solutions directly into containers. +The [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) is the standard interface for exposing arbitrary block and file storage systems into containers in Kubernetes. +Cloud service providers (CSPs) offer their own CSI-based solutions for cloud storage. + +## Confidential storage + +Most cloud storage solutions support encryption, such as [GCE Persistent Disks (PD)](https://cloud.google.com/kubernetes-engine/docs/how-to/using-cmek). +Constellation supports the available CSI-based storage options for Kubernetes engines in AWS, Azure, GCP, and STACKIT. +However, their encryption takes place in the storage backend and is managed by the CSP. +Thus, using the default CSI drivers for these storage types means trusting the CSP with your persistent data. + +To address this, Constellation provides CSI drivers for AWS EBS, Azure Disk, GCE PD, and OpenStack Cinder, offering [encryption on the node level](../architecture/keys.md#storage-encryption). They enable transparent encryption for persistent volumes without needing to trust the cloud backend. Plaintext data never leaves the confidential VM context, offering you confidential storage. + +For more details see [encrypted persistent storage](../architecture/encrypted-storage.md). + +## CSI drivers + +Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. + + + + +**Constellation CSI driver for AWS Elastic Block Store** +Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. +Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. + + + + +**Constellation CSI driver for Azure Disk**: +Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. +See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. +Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. + + + + +**Constellation CSI driver for GCP Persistent Disk**: +Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. +Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. + + + + +**Constellation CSI driver for STACKIT / OpenStack Cinder** +Mount [Cinder](https://docs.openstack.org/cinder/latest/) block storage volumes into your Constellation cluster. +Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-cloud-provider-openstack) for more information. + + + + +Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. + +## Installation + +The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. +If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. + + + + +AWS comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [SSDs of `gp3` type](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-volume-types.html) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [SSDs of `gp3` type](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-volume-types.html) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +Azure comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [Standard SSDs](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#standard-ssds) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [Premium SSDs](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#premium-ssds) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +GCP comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [standard persistent disks](https://cloud.google.com/compute/docs/disks#pdspecs) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [performance (SSD) persistent disks](https://cloud.google.com/compute/docs/disks#pdspecs) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +STACKIT comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [disks of `storage_premium_perf1` type](https://docs.stackit.cloud/stackit/en/service-plans-blockstorage-75137974.html) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [disks of `storage_premium_perf1` type](https://docs.stackit.cloud/stackit/en/service-plans-blockstorage-75137974.html) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) + + A [persistent volume claim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) is a request for storage with certain properties. + It can refer to a storage class. + The following creates a persistent volume claim, requesting 20 GB of storage via the `encrypted-rwo` storage class: + + ```bash + cat < + +--- + +You can terminate your cluster using the CLI. For this, you need the Terraform state directory named [`constellation-terraform`](../reference/terraform.md) in the current directory. + +:::danger + +All ephemeral storage and state of your cluster will be lost. Make sure any data is safely stored in persistent storage. Constellation can recreate your cluster and the associated encryption keys, but won't backup your application data automatically. + +::: + + + +Terminate the cluster by running: + +```bash +constellation terminate +``` + +Or without confirmation (e.g., for automation purposes): + +```bash +constellation terminate --yes +``` + +This deletes all resources created by Constellation in your cloud environment. +All local files created by the `apply` command are deleted as well, except for `constellation-mastersecret.json` and the configuration file. + +:::caution + +Termination can fail if additional resources have been created that depend on the ones managed by Constellation. In this case, you need to delete these additional +resources manually. Just run the `terminate` command again afterward to continue the termination process of the cluster. + +::: + + + +Terminate the cluster by running: + +```bash +terraform destroy +``` + +Delete all files that are no longer needed: + +```bash +rm constellation-state.yaml constellation-admin.conf +``` + +Only the `constellation-mastersecret.json` and the configuration file remain. + + + diff --git a/docs/versioned_docs/version-2.18/workflows/terraform-provider.md b/docs/versioned_docs/version-2.18/workflows/terraform-provider.md new file mode 100644 index 000000000..ed8f46eda --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/terraform-provider.md @@ -0,0 +1,129 @@ +# Use the Terraform provider + +The Constellation Terraform provider allows to manage the full lifecycle of a Constellation cluster (namely creation, upgrades, and deletion) via Terraform. +The provider is available through the [Terraform registry](https://registry.terraform.io/providers/edgelesssys/constellation/latest) and is released in lock-step with Constellation releases. + +## Prerequisites + +- a Linux / Mac operating system (ARM64/AMD64) +- a Terraform installation of version `v1.4.4` or above + +## Quick setup + +This example shows how to set up a Constellation cluster with the reference IAM and infrastructure setup. This setup is also used when creating a Constellation cluster through the Constellation CLI. You can either consume the IAM / infrastructure modules through a remote source (recommended) or local files. The latter requires downloading the infrastructure and IAM modules for the corresponding CSP from `terraform-modules.zip` on the [Constellation release page](https://github.com/edgelesssys/constellation/releases/latest) and placing them in the Terraform workspace directory. + +1. Create a directory (workspace) for your Constellation cluster. + + ```bash + mkdir constellation-workspace + cd constellation-workspace + ``` + +2. Use one of the [example configurations for using the Constellation Terraform provider](https://github.com/edgelesssys/constellation/tree/main/terraform-provider-constellation/examples/full) or create a `main.tf` file and fill it with the resources you want to create. The [Constellation Terraform provider documentation](https://registry.terraform.io/providers/edgelesssys/constellation/latest) offers thorough documentation on the resources and their attributes. +3. Initialize and apply the Terraform configuration. + + + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + When creating a cluster on Azure, you need to manually patch the policy of the MAA provider before creating the Constellation cluster, as this feature isn't available in Azure's Terraform provider yet. The Constellation CLI provides a utility for patching, but you + can also do it manually. + + ```bash + terraform init + terraform apply -target module.azure_iam # adjust resource path if not using the example configuration + terraform apply -target module.azure_infrastructure # adjust resource path if not using the example configuration + constellation maa-patch $(terraform output -raw maa_url) # adjust output path / input if not using the example configuration or manually patch the resource + terraform apply -target constellation_cluster.azure_example # adjust resource path if not using the example configuration + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + Use the following policy if manually performing the patch. + + ``` + version= 1.0; + authorizationrules + { + [type=="x-ms-azurevm-default-securebootkeysvalidated", value==false] => deny(); + [type=="x-ms-azurevm-debuggersdisabled", value==false] => deny(); + // The line below was edited to use the MAA provider within Constellation. Do not edit manually. + //[type=="secureboot", value==false] => deny(); + [type=="x-ms-azurevm-signingdisabled", value==false] => deny(); + [type=="x-ms-azurevm-dbvalidated", value==false] => deny(); + [type=="x-ms-azurevm-dbxvalidated", value==false] => deny(); + => permit(); + }; + issuancerules + { + }; + ``` + + + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + +4. Connect to the cluster. + + ```bash + terraform output -raw kubeconfig > constellation-admin.conf + export KUBECONFIG=$(realpath constellation-admin.conf) + ``` + +## Bringing your own infrastructure + +Instead of using the example infrastructure used in the [quick setup](#quick-setup), you can also provide your own infrastructure. +If you need a starting point for a custom infrastructure setup, you can download the infrastructure / IAM Terraform modules for the respective CSP from the Constellation [GitHub releases](https://github.com/edgelesssys/constellation/releases). You can modify and extend the modules per your requirements, while keeping the basic functionality intact. +The module contains: + +- `{csp}`: cloud resources the cluster runs on +- `iam/{csp}`: IAM resources used within the cluster + +When upgrading your cluster, make sure to check the Constellation release notes for potential breaking changes in the reference infrastructure / IAM modules that need to be considered. + +## Cluster upgrades + +:::tip +Also see the [general documentation on cluster upgrades](./upgrade.md). +::: + +The steps for applying the upgrade are as follows: + +1. Update the version constraint of the Constellation Terraform provider in the `required_providers` block in your Terraform configuration. +2. If you explicitly set any of the version attributes of the provider's resources and data sources (e.g. `image_version` or `constellation_microservice_version`), make sure to update them too. Refer to Constellation's [version support policy](https://github.com/edgelesssys/constellation/blob/main/dev-docs/workflows/versions-support.md) for more information on how each Constellation version and its dependencies are supported. +3. Update the IAM / infrastructure configuration. + - For [remote addresses as module sources](https://developer.hashicorp.com/terraform/language/modules/sources#fetching-archives-over-http), update the version number inside the address of the `source` field of the infrastructure / IAM module to the target version. + - For [local paths as module sources](https://developer.hashicorp.com/terraform/language/modules/sources#local-paths) or when [providing your own infrastructure](#bringing-your-own-infrastructure), see the changes made in the reference modules since the upgrade's origin version and adjust your infrastructure / IAM configuration accordingly. +4. Upgrade the Terraform module and provider dependencies and apply the targeted configuration. + +```bash + terraform init -upgrade + terraform apply +``` diff --git a/docs/versioned_docs/version-2.18/workflows/troubleshooting.md b/docs/versioned_docs/version-2.18/workflows/troubleshooting.md new file mode 100644 index 000000000..195bce1cc --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/troubleshooting.md @@ -0,0 +1,151 @@ +# Troubleshooting + +This section aids you in finding problems when working with Constellation. + +## Common issues + +### Issues with creating new clusters + +When you create a new cluster, you should always use the [latest release](https://github.com/edgelesssys/constellation/releases/latest). +If something doesn't work, check out the [known issues](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22). + +### Azure: Resource Providers can't be registered + +On Azure, you may receive the following error when running `apply` or `terminate` with limited IAM permissions: + +```shell-session +Error: Error ensuring Resource Providers are registered. + +Terraform automatically attempts to register the Resource Providers it supports to +ensure it's able to provision resources. + +If you don't have permission to register Resource Providers you may wish to use the +"skip_provider_registration" flag in the Provider block to disable this functionality. + +[...] +``` + +To continue, please ensure that the [required resource providers](../getting-started/install.md#required-permissions) have been registered in your subscription by your administrator. + +Afterward, set `ARM_SKIP_PROVIDER_REGISTRATION=true` as an environment variable and either run `apply` or `terminate` again. +For example: + +```bash +ARM_SKIP_PROVIDER_REGISTRATION=true constellation apply +``` + +Or alternatively, for `terminate`: + +```bash +ARM_SKIP_PROVIDER_REGISTRATION=true constellation terminate +``` + +### Azure: Can't update attestation policy + +On Azure, you may receive the following error when running `apply` from within an Azure environment, e.g., an Azure VM: + +```shell-session +An error occurred: patching policies: updating attestation policy: unexpected status code: 403 Forbidden +``` + +The problem occurs because the Azure SDK we use internally attempts to [authenticate towards the Azure API with the managed identity of your current environment instead of the Azure CLI token](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential). + +We decided not to deviate from this behavior and comply with the ordering of credentials. + +A solution is to add the [required permissions](../getting-started/install.md#required-permissions) to the managed identity of your environment. For example, the managed identity of your Azure VM, instead of the account that you've authenticated with in the Azure CLI. + +If your setup requires a change in the ordering of credentials, please open an issue and explain your desired behavior. + + + +### Nodes fail to join with error `untrusted measurement value` + +This error indicates that a node's [attestation statement](../architecture/attestation.md) contains measurements that don't match the trusted values expected by the [JoinService](../architecture/microservices.md#joinservice). +This may for example happen if the cloud provider updates the VM's firmware such that it influences the [runtime measurements](../architecture/attestation.md#runtime-measurements) in an unforeseen way. +A failed upgrade due to an erroneous attestation config can also cause this error. +You can change the expected measurements to resolve the failure. + +:::caution + +Attestation and trusted measurements are crucial for the security of your cluster. +Be extra careful when manually changing these settings. +When in doubt, check if the encountered [issue is known](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22) or [contact support](https://github.com/edgelesssys/constellation#support). + +::: + +:::tip + +During an upgrade with modified attestation config, a backup of the current configuration is stored in the `join-config` config map in the `kube-system` namespace under the `attestationConfig_backup` key. To restore the old attestation config after a failed upgrade, replace the value of `attestationConfig` with the value from `attestationConfig_backup`: + +```bash +kubectl patch configmaps -n kube-system join-config -p "{\"data\":{\"attestationConfig\":\"$(kubectl get configmaps -n kube-system join-config -o "jsonpath={.data.attestationConfig_backup}")\"}}" +``` + +::: + +You can use the `apply` command to change measurements of a running cluster: + +1. Modify the `measurements` key in your local `constellation-conf.yaml` to the expected values. +2. Run `constellation apply`. + +Keep in mind that running `apply` also applies any version changes from your config to the cluster. + +You can run these commands to learn about the versions currently configured in the cluster: + +- Kubernetes API server version: `kubectl get nodeversion constellation-version -o json -n kube-system | jq .spec.kubernetesClusterVersion` +- image version: `kubectl get nodeversion constellation-version -o json -n kube-system | jq .spec.imageVersion` +- microservices versions: `helm list --filter 'constellation-services' -n kube-system` + +### Upgrading Kubernetes resources fails + +Constellation manages its Kubernetes resources using Helm. +When applying an upgrade, the charts that are about to be installed, and a values override file `overrides.yaml`, +are saved to disk in your current workspace under `constellation-upgrade/upgrade-/helm-charts/`. +If upgrading the charts using the Constellation CLI fails, you can review these charts and try to manually apply the upgrade. + +:::caution + +Changing and manually applying the charts may destroy cluster resources and can lead to broken Constellation deployments. +Proceed with caution and when in doubt, +check if the encountered [issue is known](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22) or [contact support](https://github.com/edgelesssys/constellation#support). + +::: + +## Diagnosing issues + +### Logs + +To get started on diagnosing issues with Constellation, it's often helpful to collect logs from nodes, pods, or other resources in the cluster. Most logs are available through Kubernetes' standard +[logging interfaces](https://kubernetes.io/docs/concepts/cluster-administration/logging/). + +To debug issues occurring at boot time of the nodes, you can use the serial console interface of the CSP while the machine boots to get a read-only view of the boot logs. + +Apart from that, Constellation also offers further [observability integrations](../architecture/observability.md). + +### Node shell access + +Debugging via a shell on a node is [directly supported by Kubernetes](https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/#node-shell-session). + +1. Figure out which node to connect to: + + ```bash + kubectl get nodes + # or to see more information, such as IPs: + kubectl get nodes -o wide + ``` + +2. Connect to the node: + + ```bash + kubectl debug node/constell-worker-xksa0-000000 -it --image=busybox + ``` + + You will be presented with a prompt. + + The nodes file system is mounted at `/host`. + +3. Once finished, clean up the debug pod: + + ```bash + kubectl delete pod node-debugger-constell-worker-xksa0-000000-bjthj + ``` diff --git a/docs/versioned_docs/version-2.18/workflows/trusted-launch.md b/docs/versioned_docs/version-2.18/workflows/trusted-launch.md new file mode 100644 index 000000000..d6d01d8eb --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/trusted-launch.md @@ -0,0 +1,54 @@ +# Use Azure trusted launch VMs + +Constellation also supports [trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch) on Microsoft Azure. Trusted launch VMs don't offer the same level of security as Confidential VMs, but are available in more regions and in larger quantities. The main difference between trusted launch VMs and normal VMs is that the former offer vTPM-based remote attestation. When used with trusted launch VMs, Constellation relies on vTPM-based remote attestation to verify nodes. + +:::caution + +Trusted launch VMs don't provide runtime encryption and don't keep the cloud service provider (CSP) out of your trusted computing base. + +::: + +Constellation supports trusted launch VMs with instance types `Standard_D*_v4` and `Standard_E*_v4`. Run `constellation config instance-types` for a list of all supported instance types. + +## VM images + +Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. + +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. + +After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. +You can use a script to do this: + +```bash +wget https://raw.githubusercontent.com/edgelesssys/constellation/main/hack/importAzure.sh +chmod +x importAzure.sh +AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_IMAGE_FILE=./constellation.img ./importAzure.sh +``` + +The script creates the following resources: + +1. A new image gallery with the default name `constellation-import` +2. A new image definition with the default name `constellation` +3. The actual image with the provided version. In this case `2.2.0` + +Once the import is completed, use the `ID` of the image version in your `constellation-conf.yaml` for the `image` field. Set `confidentialVM` to `false`. + +Fetch the image measurements: + +```bash +IMAGE_VERSION=2.2.0 +URL=https://public-edgeless-constellation.s3.us-east-2.amazonaws.com//communitygalleries/constellationcvm-b3782fa0-0df7-4f2f-963e-fc7fc42663df/images/constellation/versions/$IMAGE_VERSION/measurements.yaml +constellation config fetch-measurements -u$URL -s$URL.sig +``` + +:::info + +The [`constellation apply`](create.md) command will issue a warning because manually imported images aren't recognized as production grade images: + +```shell-session +Configured image doesn't look like a released production image. Double check image before deploying to production. +``` + +Please ignore this warning. + +::: diff --git a/docs/versioned_docs/version-2.18/workflows/upgrade.md b/docs/versioned_docs/version-2.18/workflows/upgrade.md new file mode 100644 index 000000000..7348c0dbc --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/upgrade.md @@ -0,0 +1,110 @@ +# Upgrade your cluster + +Constellation provides an easy way to upgrade all components of your cluster, without disrupting it's availability. +Specifically, you can upgrade the Kubernetes version, the nodes' image, and the Constellation microservices. +You configure the desired versions in your local Constellation configuration and trigger upgrades with the `apply` command. +To learn about available versions you use the `upgrade check` command. +Which versions are available depends on the CLI version you are using. + +## Update the CLI + +Each CLI comes with a set of supported microservice and Kubernetes versions. +Most importantly, a given CLI version can only upgrade a cluster of the previous minor version, but not older ones. +This means that you have to upgrade your CLI and cluster one minor version at a time. + +For example, if you are currently on CLI version v2.6 and the latest version is v2.8, you should + +* upgrade the CLI to v2.7, +* upgrade the cluster to v2.7, +* and only then continue upgrading the CLI (and the cluster) to v2.8 after. + +Also note that if your current Kubernetes version isn't supported by the next CLI version, use your current CLI to upgrade to a newer Kubernetes version first. + +To learn which Kubernetes versions are supported by a particular CLI, run [constellation config kubernetes-versions](../reference/cli.md#constellation-config-kubernetes-versions). + +## Migrate the configuration + +The Constellation configuration file is located in the file `constellation-conf.yaml` in your workspace. +Refer to the [migration reference](../reference/migration.md) to check if you need to update fields in your configuration file. +Use [`constellation config migrate`](../reference/cli.md#constellation-config-migrate) to automatically update an old config file to a new format. + +## Check for upgrades + +To learn which versions the current CLI can upgrade to and what's installed in your cluster, run: + +```bash +# Show possible upgrades +constellation upgrade check + +# Show possible upgrades and write them to config file +constellation upgrade check --update-config +``` + +You can either enter the reported target versions into your config manually or run the above command with the `--update-config` flag. +When using this flag, the `kubernetesVersion`, `image`, `microserviceVersion`, and `attestation` fields are overwritten with the smallest available upgrade. + +## Apply the upgrade + +Once you updated your config with the desired versions, you can trigger the upgrade with this command: + +```bash +constellation apply +``` + +Microservice upgrades will be finished within a few minutes, depending on the cluster size. +If you are interested, you can monitor pods restarting in the `kube-system` namespace with your tool of choice. + +Image and Kubernetes upgrades take longer. +For each node in your cluster, a new node has to be created and joined. +The process usually takes up to ten minutes per node. + +When applying an upgrade, the Helm charts for the upgrade as well as backup files of Constellation-managed Custom Resource Definitions, Custom Resources, and Terraform state are created. +You can use the Terraform state backup to restore previous resources in case an upgrade misconfigured or erroneously deleted a resource. +You can use the Custom Resource (Definition) backup files to restore Custom Resources and Definitions manually (e.g., via `kubectl apply`) if the automatic migration of those resources fails. +You can use the Helm charts to manually apply upgrades to the Kubernetes resources, should an upgrade fail. + +:::note + +For advanced users: the upgrade consists of several phases that can be individually skipped through the `--skip-phases` flag. +The phases are `infrastracture` for the cloud resource management through Terraform, `helm` for the chart management of the microservices, `image` for OS image upgrades, and `k8s` for Kubernetes version upgrades. + +::: + +## Check the status + +Upgrades are asynchronous operations. +After you run `apply`, it will take a while until the upgrade has completed. +To understand if an upgrade is finished, you can run: + +```bash +constellation status +``` + +This command displays the following information: + +* The installed services and their versions +* The image and Kubernetes version the cluster is expecting on each node +* How many nodes are up to date + +Here's an example output: + +```shell-session +Target versions: + Image: v2.6.0 + Kubernetes: v1.25.8 +Service versions: + Cilium: v1.12.1 + cert-manager: v1.10.0 + constellation-operators: v2.6.0 + constellation-services: v2.6.0 +Cluster status: Some node versions are out of date + Image: 23/25 + Kubernetes: 25/25 +``` + +This output indicates that the cluster is running Kubernetes version `1.25.8`, and all nodes have the appropriate binaries installed. +23 out of 25 nodes have already upgraded to the targeted image version of `2.6.0`, while two are still in progress. + +## Apply further upgrades + +After the upgrade is finished, you can run `constellation upgrade check` again to see if there are more upgrades available. If so, repeat the process. diff --git a/docs/versioned_docs/version-2.18/workflows/verify-cli.md b/docs/versioned_docs/version-2.18/workflows/verify-cli.md new file mode 100644 index 000000000..e33569d37 --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/verify-cli.md @@ -0,0 +1,129 @@ +# Verify the CLI + +:::info +This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. +::: + + + +--- + +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. + +:::note +The public key for Edgeless Systems' long-term code-signing key is: + +``` +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT +JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== +-----END PUBLIC KEY----- +``` + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +::: + +The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. + +You should always ensure that (1) your CLI executable was signed with the private key corresponding to the above public key and that (2) there is a corresponding entry in the Rekor transparency log. Both can be done as described in the following. + +:::info +You don't need to verify the Constellation node images. This is done automatically by your CLI and the rest of Constellation. +::: + +## Verify the signature + +:::info +This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. +::: + +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: + +```shell-session +$ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 + +Verified OK +``` + +The above performs an offline verification of the provided public key, signature, and executable. To also verify that a corresponding entry exists in the public Rekor transparency log, add the variable `COSIGN_EXPERIMENTAL=1`: + +```shell-session +$ COSIGN_EXPERIMENTAL=1 cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 + +tlog entry verified with uuid: afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 index: 3477047 +Verified OK +``` + +🏁 You now know that your CLI executable was officially released and signed by Edgeless Systems. + +### Optional: Manually inspect the transparency log + +To further inspect the public Rekor transparency log, [install the Rekor CLI](https://docs.sigstore.dev/logging/installation). A search for the CLI executable should give a single UUID. (Note that this UUID contains the UUID from the previous `cosign` command.) + +```shell-session +$ rekor-cli search --artifact constellation-linux-amd64 + +Found matching entries (listed by UUID): +362f8ecba72f4326afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 +``` + +With this UUID you can get the full entry from the transparency log: + +```shell-session +$ rekor-cli get --uuid=362f8ecba72f4326afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 + +LogID: c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d +Index: 3477047 +IntegratedTime: 2022-09-12T22:28:16Z +UUID: afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 +Body: { + "HashedRekordObj": { + "data": { + "hash": { + "algorithm": "sha256", + "value": "40e137b9b9b8204d672642fd1e181c6d5ccb50cfc5cc7fcbb06a8c2c78f44aff" + } + }, + "signature": { + "content": "MEUCIQCSER3mGj+j5Pr2kOXTlCIHQC3gT30I7qkLr9Awt6eUUQIgcLUKRIlY50UN8JGwVeNgkBZyYD8HMxwC/LFRWoMn180=", + "publicKey": { + "content": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFZjhGMWhwbXdFK1lDRlh6akd0YVFjckw2WFpWVApKbUVlNWlTTHZHMVN5UVNBZXc3V2RNS0Y2bzl0OGUyVEZ1Q2t6bE9oaGx3czJPSFdiaUZabkZXQ0Z3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==" + } + } + } +} +``` + +The field `publicKey` should contain Edgeless Systems' public key in Base64 encoding. + +You can get an exhaustive list of artifact signatures issued by Edgeless Systems via the following command: + +```bash +rekor-cli search --public-key https://edgeless.systems/es.pub --pki-format x509 +``` + +Edgeless Systems monitors this list to detect potential unauthorized use of its private key. + +## Verify the provenance + +Provenance attests that a software artifact was produced by a specific repository and build system invocation. For more information on provenance visit [slsa.dev](https://slsa.dev/provenance/v0.2) and learn about the [adoption of SLSA for Constellation](../reference/slsa.md). + +Just as checking its signature proves that the CLI hasn't been manipulated, checking the provenance proves that the artifact was produced by the expected build process and hasn't been tampered with. + +To verify the provenance, first install the [slsa-verifier](https://github.com/slsa-framework/slsa-verifier). Then make sure you have the provenance file (`constellation.intoto.jsonl`) and Constellation CLI downloaded. Both are available on the [GitHub release page](https://github.com/edgelesssys/constellation/releases). + +:::info +The same provenance file is valid for all Constellation CLI executables of a given version independent of the target platform. +::: + +Use the verifier to perform the check: + +```shell-session +$ slsa-verifier verify-artifact constellation-linux-amd64 \ + --provenance-path constellation.intoto.jsonl \ + --source-uri github.com/edgelesssys/constellation + +Verified signature against tlog entry index 7771317 at URL: https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77af2c04c8b4ae0d5bc5... +Verified build using builder https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v1.2.2 at commit 18e9924b416323c37b9cdfd6cc728de8a947424a +PASSED: Verified SLSA provenance +``` diff --git a/docs/versioned_docs/version-2.18/workflows/verify-cluster.md b/docs/versioned_docs/version-2.18/workflows/verify-cluster.md new file mode 100644 index 000000000..b6595ebf2 --- /dev/null +++ b/docs/versioned_docs/version-2.18/workflows/verify-cluster.md @@ -0,0 +1,97 @@ +# Verify your cluster + +Constellation's [attestation feature](../architecture/attestation.md) allows you, or a third party, to verify the integrity and confidentiality of your Constellation cluster. + +## Fetch measurements + +To verify the integrity of Constellation you need trusted measurements to verify against. For each node image released by Edgeless Systems, there are signed measurements, which you can download using the CLI: + +```bash +constellation config fetch-measurements +``` + +This command performs the following steps: + +1. Download the signed measurements for the configured image. By default, this will use Edgeless Systems' public measurement registry. +2. Verify the signature of the measurements. This will use Edgeless Systems' [public key](https://edgeless.systems/es.pub). +3. Write measurements into configuration file. + +The configuration file then contains a list of `measurements` similar to the following: + +```yaml +# ... +measurements: + 0: + expected: "0f35c214608d93c7a6e68ae7359b4a8be5a0e99eea9107ece427c4dea4e439cf" + warnOnly: false + 4: + expected: "02c7a67c01ec70ffaf23d73a12f749ab150a8ac6dc529bda2fe1096a98bf42ea" + warnOnly: false + 5: + expected: "e6949026b72e5045706cd1318889b3874480f7a3f7c5c590912391a2d15e6975" + warnOnly: true + 8: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false + 9: + expected: "f0a6e8601b00e2fdc57195686cd4ef45eb43a556ac1209b8e25d993213d68384" + warnOnly: false + 11: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false + 12: + expected: "da99eb6cf7c7fbb692067c87fd5ca0b7117dc293578e4fea41f95d3d3d6af5e2" + warnOnly: false + 13: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false + 14: + expected: "d7c4cc7ff7933022f013e03bdee875b91720b5b86cf1753cad830f95e791926f" + warnOnly: true + 15: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false +# ... +``` + +Each entry specifies the expected value of the Constellation node, and whether the measurement should be enforced (`warnOnly: false`), or only a warning should be logged (`warnOnly: true`). +By default, the subset of the [available measurements](../architecture/attestation.md#runtime-measurements) that can be locally reproduced and verified is enforced. + +During attestation, the validating side (CLI or [join service](../architecture/microservices.md#joinservice)) compares each measurement reported by the issuing side (first node or joining node) individually. +For mismatching measurements that have set `warnOnly` to `true` only a warning is emitted. +For mismatching measurements that have set `warnOnly` to `false` an error is emitted and attestation fails. +If attestation fails for a new node, it isn't permitted to join the cluster. + +## The *verify* command + +:::note +The steps below are purely optional. They're automatically executed by `constellation apply` when you initialize your cluster. The `constellation verify` command mostly has an illustrative purpose. +::: + +The `verify` command obtains and verifies an attestation statement from a running Constellation cluster. + +```bash +constellation verify [--cluster-id ...] +``` + +From the attestation statement, the command verifies the following properties: + +* The cluster is using the correct Confidential VM (CVM) type. +* Inside the CVMs, the correct node images are running. The node images are identified through the measurements obtained in the previous step. +* The unique ID of the cluster matches the one from your `constellation-state.yaml` file or passed in via `--cluster-id`. + +Once the above properties are verified, you know that you are talking to the right Constellation cluster and it's in a good and trustworthy shape. + +### Custom arguments + +The `verify` command also allows you to verify any Constellation deployment that you have network access to. For this you need the following: + +* The IP address of a running Constellation cluster's [VerificationService](../architecture/microservices.md#verificationservice). The `VerificationService` is exposed via a `NodePort` service using the external IP address of your cluster. Run `kubectl get nodes -o wide` and look for `EXTERNAL-IP`. +* The cluster's *clusterID*. See [cluster identity](../architecture/keys.md#cluster-identity) for more details. +* A `constellation-conf.yaml` file with the expected measurements of the cluster in your working directory. + +For example: + +```shell-session +constellation verify -e 192.0.2.1 --cluster-id Q29uc3RlbGxhdGlvbkRvY3VtZW50YXRpb25TZWNyZXQ= +``` diff --git a/docs/versioned_docs/version-2.19/_media/SLSA-Badge-full-level3.svg b/docs/versioned_docs/version-2.19/_media/SLSA-Badge-full-level3.svg new file mode 100644 index 000000000..7154d4a13 --- /dev/null +++ b/docs/versioned_docs/version-2.19/_media/SLSA-Badge-full-level3.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_fio_azure_bw.png b/docs/versioned_docs/version-2.19/_media/benchmark_fio_azure_bw.png new file mode 100644 index 000000000..a82ebe2d0 Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_fio_azure_bw.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_fio_azure_iops.png b/docs/versioned_docs/version-2.19/_media/benchmark_fio_azure_iops.png new file mode 100644 index 000000000..1723257a8 Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_fio_azure_iops.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_fio_gcp_bw.png b/docs/versioned_docs/version-2.19/_media/benchmark_fio_gcp_bw.png new file mode 100644 index 000000000..4f0ecc94b Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_fio_gcp_bw.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_fio_gcp_iops.png b/docs/versioned_docs/version-2.19/_media/benchmark_fio_gcp_iops.png new file mode 100644 index 000000000..571086da2 Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_fio_gcp_iops.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_net_p2p_azure.png b/docs/versioned_docs/version-2.19/_media/benchmark_net_p2p_azure.png new file mode 100644 index 000000000..9130349c7 Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_net_p2p_azure.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_net_p2p_gcp.png b/docs/versioned_docs/version-2.19/_media/benchmark_net_p2p_gcp.png new file mode 100644 index 000000000..a41557e96 Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_net_p2p_gcp.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_net_p2svc_azure.png b/docs/versioned_docs/version-2.19/_media/benchmark_net_p2svc_azure.png new file mode 100644 index 000000000..d83e17f5a Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_net_p2svc_azure.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_net_p2svc_gcp.png b/docs/versioned_docs/version-2.19/_media/benchmark_net_p2svc_gcp.png new file mode 100644 index 000000000..55916a1de Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_net_p2svc_gcp.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/max_latency.png b/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/max_latency.png new file mode 100644 index 000000000..696250181 Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/max_latency.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/mean_latency.png b/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/mean_latency.png new file mode 100644 index 000000000..3b43298ac Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/mean_latency.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/min_latency.png b/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/min_latency.png new file mode 100644 index 000000000..1046df67e Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/min_latency.png differ diff --git a/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/p99_latency.png b/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/p99_latency.png new file mode 100644 index 000000000..0190118b2 Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/benchmark_vault/5replicas/p99_latency.png differ diff --git a/docs/versioned_docs/version-2.19/_media/concept-constellation.svg b/docs/versioned_docs/version-2.19/_media/concept-constellation.svg new file mode 100644 index 000000000..30d32bf6d --- /dev/null +++ b/docs/versioned_docs/version-2.19/_media/concept-constellation.svg @@ -0,0 +1,460 @@ + + diff --git a/docs/versioned_docs/version-2.19/_media/concept-managed.svg b/docs/versioned_docs/version-2.19/_media/concept-managed.svg new file mode 100644 index 000000000..5645a608f --- /dev/null +++ b/docs/versioned_docs/version-2.19/_media/concept-managed.svg @@ -0,0 +1,591 @@ + + diff --git a/docs/versioned_docs/version-2.19/_media/constellation_oneline.svg b/docs/versioned_docs/version-2.19/_media/constellation_oneline.svg new file mode 100644 index 000000000..4e354958a --- /dev/null +++ b/docs/versioned_docs/version-2.19/_media/constellation_oneline.svg @@ -0,0 +1,52 @@ + + + + + + + + diff --git a/docs/versioned_docs/version-2.19/_media/example-emojivoto.jpg b/docs/versioned_docs/version-2.19/_media/example-emojivoto.jpg new file mode 100644 index 000000000..4be0d5b26 Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/example-emojivoto.jpg differ diff --git a/docs/versioned_docs/version-2.19/_media/example-online-boutique.jpg b/docs/versioned_docs/version-2.19/_media/example-online-boutique.jpg new file mode 100644 index 000000000..026f0d865 Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/example-online-boutique.jpg differ diff --git a/docs/versioned_docs/version-2.19/_media/recovery-gcp-serial-console-link.png b/docs/versioned_docs/version-2.19/_media/recovery-gcp-serial-console-link.png new file mode 100644 index 000000000..eb67f0e99 Binary files /dev/null and b/docs/versioned_docs/version-2.19/_media/recovery-gcp-serial-console-link.png differ diff --git a/docs/versioned_docs/version-2.19/_media/tcb.svg b/docs/versioned_docs/version-2.19/_media/tcb.svg new file mode 100644 index 000000000..e5bcb5b95 --- /dev/null +++ b/docs/versioned_docs/version-2.19/_media/tcb.svg @@ -0,0 +1,535 @@ + + diff --git a/docs/versioned_docs/version-2.19/architecture/attestation.md b/docs/versioned_docs/version-2.19/architecture/attestation.md new file mode 100644 index 000000000..9bd157460 --- /dev/null +++ b/docs/versioned_docs/version-2.19/architecture/attestation.md @@ -0,0 +1,409 @@ +# Attestation + +This page explains Constellation's attestation process and highlights the cornerstones of its trust model. + +## Terms + +The following lists terms and concepts that help to understand the attestation concept of Constellation. + +### Trusted Platform Module (TPM) + +A TPM chip is a dedicated tamper-resistant crypto-processor. +It can securely store artifacts such as passwords, certificates, encryption keys, or *runtime measurements* (more on this below). +When a TPM is implemented in software, it's typically called a *virtual* TPM (vTPM). + +### Runtime measurement + +A runtime measurement is a cryptographic hash of the memory pages of a so called *runtime component*. Runtime components of interest typically include a system's bootloader or OS kernel. + +### Platform Configuration Register (PCR) + +A Platform Configuration Register (PCR) is a memory location in the TPM that has some unique properties. +To store a new value in a PCR, the existing value is extended with a new value as follows: + +``` +PCR[N] = HASHalg( PCR[N] || ArgumentOfExtend ) +``` + +The PCRs are typically used to store runtime measurements. +The new value of a PCR is always an extension of the existing value. +Thus, storing the measurements of multiple components into the same PCR irreversibly links them together. + +### Measured boot + +Measured boot builds on the concept of chained runtime measurements. +Each component in the boot chain loads and measures the next component into the PCR before executing it. +By comparing the resulting PCR values against trusted reference values, the integrity of the entire boot chain and thereby the running system can be ensured. + +### Remote attestation (RA) + +Remote attestation is the process of verifying certain properties of an application or platform, such as integrity and confidentiality, from a remote location. +In the case of a measured boot, the goal is to obtain a signed attestation statement on the PCR values of the boot measurements. +The statement can then be verified and compared to a set of trusted reference values. +This way, the integrity of the platform can be ensured before sharing secrets with it. + +### Confidential virtual machine (CVM) + +Confidential computing (CC) is the protection of data in-use with hardware-based trusted execution environments (TEEs). +With CVMs, TEEs encapsulate entire virtual machines and isolate them against the hypervisor, other VMs, and direct memory access. +After loading the initial VM image into encrypted memory, the hypervisor calls for a secure processor to measure these initial memory pages. +The secure processor locks these pages and generates an attestation report on the initial page measurements. +CVM memory pages are encrypted with a key that resides inside the secure processor, which makes sure only the guest VM can access them. +The attestation report is signed by the secure processor and can be verified using remote attestation via the certificate authority of the hardware vendor. +Such an attestation statement guarantees the confidentiality and integrity of a CVM. + +### Attested TLS (aTLS) + +In a CC environment, attested TLS (aTLS) can be used to establish secure connections between two parties using the remote attestation features of the CC components. + +aTLS modifies the TLS handshake by embedding an attestation statement into the TLS certificate. +Instead of relying on a certificate authority, aTLS uses this attestation statement to establish trust in the certificate. + +The protocol can be used by clients to verify a server certificate, by a server to verify a client certificate, or for mutual verification (mutual aTLS). + +## Overview + +The challenge for Constellation is to lift a CVM's attestation statement to the Kubernetes software layer and make it end-to-end verifiable. +From there, Constellation needs to expand the attestation from a single CVM to the entire cluster. + +The [*JoinService*](microservices.md#joinservice) and [*VerificationService*](microservices.md#verificationservice) are where all runs together. +Internally, the *JoinService* uses remote attestation to securely join CVM nodes to the cluster. +Externally, the *VerificationService* provides an attestation statement for the cluster's CVMs and configuration. + +The following explains the details of both steps. + +## Node attestation + +The idea is that Constellation nodes should have verifiable integrity from the CVM hardware measurement up to the Kubernetes software layer. +The solution is a verifiable boot chain and an integrity-protected runtime environment. + +Constellation uses measured boot within CVMs, measuring each component in the boot process before executing it. +Outside of CC, this is usually implemented via TPMs. +CVM technologies differ in how they implement runtime measurements, but the general concepts are similar to those of a TPM. +For simplicity, TPM terminology like *PCR* is used in the following. + +When a Constellation node image boots inside a CVM, measured boot is used for all stages and components of the boot chain. +This process goes up to the root filesystem. +The root filesystem is mounted read-only with integrity protection. +For the details on the image and boot stages see the [image architecture](../architecture/images.md) documentation. +Any changes to the image will inevitably also change the corresponding PCR values. +To create a node attestation statement, the Constellation image obtains a CVM attestation statement from the hardware. +This includes the runtime measurements and thereby binds the measured boot results to the CVM hardware measurement. + +In addition to the image measurements, Constellation extends a PCR during the [initialization phase](../workflows/create.md) that irrevocably marks the node as initialized. +The measurement is created using the [*clusterID*](../architecture/keys.md#cluster-identity), tying all future attestation statements to this ID. +Thereby, an attestation statement is unique for every cluster and a node can be identified unambiguously as being initialized. + +To verify an attestation, the hardware's signature and a statement are verified first to establish trust in the contained runtime measurements. +If successful, the measurements are verified against the trusted values of the particular Constellation release version. +Finally, the measurement of the *clusterID* can be compared by calculating it with the [master secret](keys.md#master-secret). + +### Runtime measurements + +Constellation uses runtime measurements to implement the measured boot approach. +As stated above, the underlying hardware technology and guest firmware differ in their implementations of runtime measurements. +The following gives a detailed description of the available measurements in the different cloud environments. + +The runtime measurements consist of two types of values: + +* **Measurements produced by the cloud infrastructure and firmware of the CVM**: +These are measurements of closed-source firmware and other values controlled by the cloud provider. +While not being reproducible for the user, some of them can be compared against previously observed values. +Others may change frequently and aren't suitable for verification. +The [signed image measurements](#chain-of-trust) include measurements that are known, previously observed values. + +* **Measurements produced by the Constellation bootloader and boot chain**: +The Constellation Bootloader takes over from the CVM firmware and [measures the rest of the boot chain](images.md). +The Constellation [Bootstrapper](microservices.md#bootstrapper) is the first user mode component that runs in a Constellation image. +It extends PCR registers with the [IDs](keys.md#cluster-identity) of the cluster marking a node as initialized. + +Constellation allows to specify in the config which measurements should be enforced during the attestation process. +Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. +By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. + + + + +Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. + +The vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +The VMs are attested by obtaining signed PCR values over the VM's boot configuration from the TPM and comparing them to a known, good state (measured boot). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | Firmware | AWS | No | +| 1 | Firmware | AWS | No | +| 2 | Firmware | AWS | No | +| 3 | Firmware | AWS | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | AWS, Constellation Bootloader | Yes | +| 5 | Firmware | AWS | No | +| 6 | Firmware | AWS | No | +| 7 | Secure Boot Policy | AWS, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. +This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +It provides a [measured boot](https://docs.microsoft.com/en-us/azure/security/fundamentals/measured-boot-host-attestation#measured-boot) verification that's based on the trusted launch feature of [Trusted Launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | Firmware | Azure | No | +| 1 | Firmware | Azure | No | +| 2 | Firmware | Azure | No | +| 3 | Firmware | Azure | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | Azure, Constellation Bootloader | Yes | +| 5 | Reserved | Azure | No | +| 6 | VM Unique ID | Azure | No | +| 7 | Secure Boot State | Azure, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. +Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. + +The vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +It provides a [launch attestation report](https://cloud.google.com/compute/confidential-vm/docs/monitoring#about_launch_attestation_report_events) that's based on the measured boot feature of [Shielded VMs](https://cloud.google.com/compute/shielded-vm/docs/shielded-vm#measured-boot). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | CVM version and technology | GCP | No | +| 1 | Firmware | GCP | No | +| 2 | Firmware | GCP | No | +| 3 | Firmware | GCP | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | GCP, Constellation Bootloader | Yes | +| 5 | Disk GUID partition table | GCP | No | +| 6 | Disk GUID partition table | GCP | No | +| 7 | GCP Secure Boot Policy | GCP, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +Constellation uses a hypervisor-based vTPM for runtime measurements. + +The vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. +The VMs are attested by obtaining signed PCR values over the VM's boot configuration from the TPM and comparing them to a known, good state (measured boot). + +The following table lists all PCR values of the vTPM and the measured components. +It also lists what components of the boot chain did the measurements and if the value is reproducible and verifiable. +The latter means that the value can be generated offline and compared to the one in the vTPM. + +| PCR | Components | Measured by | Reproducible and verifiable | +| ----------- | ---------------------------------------------------------------- | -------------------------------------- | --------------------------- | +| 0 | Firmware | STACKIT | No | +| 1 | Firmware | STACKIT | No | +| 2 | Firmware | STACKIT | No | +| 3 | Firmware | STACKIT | No | +| 4 | Constellation Bootloader, Kernel, initramfs, Kernel command line | STACKIT, Constellation Bootloader | Yes | +| 5 | Firmware | STACKIT | No | +| 6 | Firmware | STACKIT | No | +| 7 | Secure Boot Policy | STACKIT, Constellation Bootloader | No | +| 8 | - | - | - | +| 9 | initramfs, Kernel command line | Linux Kernel | Yes | +| 10 | User space | Linux IMA | No[^1] | +| 11 | Unified Kernel Image components | Constellation Bootloader | Yes | +| 12 | Reserved | (User space, Constellation Bootloader) | Yes | +| 13 | Reserved | (Constellation Bootloader) | Yes | +| 14 | Secure Boot State | Constellation Bootloader | No | +| 15 | ClusterID | Constellation Bootstrapper | Yes | +| 16–23 | Unused | - | - | + + + + +### CVM verification + +To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. +For verification of the CVM technology, Constellation may expose additional options in its config file. + + + + +On AWS, AMD SEV-SNP is used to provide runtime encryption to the VMs. +An SEV-SNP attestation report is used to establish trust in the VM. +You may customize certain parameters for verification of the attestation statement using the Constellation config file. + +* TCB versions + + You can set the minimum version numbers of components in the SEV-SNP TCB. + Use the latest versions to enforce that only machines with the most recent firmware updates are allowed to join the cluster. + Alternatively, you can set a lower minimum version to allow slightly out-of-date machines to still be able to join the cluster. + +* AMD Root Key Certificate + + This certificate is the root of trust for verifying the SEV-SNP certificate chain. + +* AMD Signing Key Certificate + + This is the intermediate certificate for verifying the SEV-SNP report's signature. + If it's not specified, the CLI fetches it from the AMD key distribution server. + + + + +On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. +An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. +You may customize certain parameters for verification of the attestation statement using the Constellation config file. + +* TCB versions + + You can set the minimum version numbers of components in the SEV-SNP TCB. + Use the latest versions to enforce that only machines with the most recent firmware updates are allowed to join the cluster. + Alternatively, you can set a lower minimum version to allow slightly out-of-date machines to still be able to join the cluster. + +* AMD Root Key Certificate + + This certificate is the root of trust for verifying the SEV-SNP certificate chain. + +* Firmware Signer + + This config option allows you to specify how the firmware signer should be verified. + More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. + You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. + + + + +On GCP, AMD SEV-SNP is used to provide runtime encryption to the VMs. +An SEV-SNP attestation report is used to establish trust in the VM. +You may customize certain parameters for verification of the attestation statement using the Constellation config file. + +* TCB versions + + You can set the minimum version numbers of components in the SEV-SNP TCB. + Use the latest versions to enforce that only machines with the most recent firmware updates are allowed to join the cluster. + Alternatively, you can set a lower minimum version to allow slightly out-of-date machines to still be able to join the cluster. + +* AMD Root Key Certificate + + This certificate is the root of trust for verifying the SEV-SNP certificate chain. + +* AMD Signing Key Certificate + + This is the intermediate certificate for verifying the SEV-SNP report's signature. + If it's not specified, the CLI fetches it from the AMD key distribution server. + + + + +On STACKIT, AMD SEV-ES is used to provide runtime encryption to the VMs. +The hypervisor-based vTPM is used to establish trust in the VM via [runtime measurements](#runtime-measurements). +There is no additional configuration available for STACKIT. + + + + +## Cluster attestation + +Cluster-facing, Constellation's [*JoinService*](microservices.md#joinservice) verifies each node joining the cluster given the configured ground truth runtime measurements. +User-facing, the [*VerificationService*](microservices.md#verificationservice) provides an interface to verify a node using remote attestation. +By verifying the first node during the [initialization](microservices.md#bootstrapper) and configuring the ground truth measurements that are subsequently enforced by the *JoinService*, the whole cluster is verified in a transitive way. + +### Cluster-facing attestation + +The *JoinService* is provided with the runtime measurements of the whitelisted Constellation image version as the ground truth. +During the initialization and the cluster bootstrapping, each node connects to the *JoinService* using [aTLS](#attested-tls-atls). +During the handshake, the node transmits an attestation statement including its runtime measurements. +The *JoinService* verifies that statement and compares the measurements against the ground truth. +For details of the initialization process check the [microservice descriptions](microservices.md). + +After the initialization, every node updates its runtime measurements with the *clusterID* value, marking it irreversibly as initialized. +When an initialized node tries to join another cluster, its measurements inevitably mismatch the measurements of an uninitialized node and it will be declined. + +### User-facing attestation + +The [*VerificationService*](microservices.md#verificationservice) provides an endpoint for obtaining its hardware-based remote attestation statement, which includes the runtime measurements. +A user can [verify](../workflows/verify-cluster.md) this statement and compare the measurements against the configured ground truth and, thus, verify the identity and integrity of all Constellation components and the cluster configuration. Subsequently, the user knows that the entire cluster is in the expected state and is trustworthy. + +## Putting it all together + +This section puts the aforementioned concepts together and illustrate how trust into a Constellation cluster is established and maintained. + +### CLI and node images + +It all starts with the CLI executable. The CLI is signed by Edgeless Systems. To ensure non-repudiability for CLI releases, Edgeless Systems publishes corresponding signatures to the public ledger of the [sigstore project](https://www.sigstore.dev/). There's a [step-by-step guide](../workflows/verify-cli.md) on how to verify CLI signatures based on sigstore. + +The CLI contains the latest runtime measurements of the Constellation node image for all supported cloud platforms. In case a different version of the node image is to be used, the corresponding runtime measurements can be fetched using the CLI's [fetch-measurements command](../reference/cli.md#constellation-config-fetch-measurements). This command downloads the runtime measurements and the corresponding signature from cdn.confidential.cloud. See for example the following files corresponding to node image v2.16.3: + +* [Measurements](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json) +* [Signature](https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/v2.16.3/image/measurements.json.sig) + +The CLI contains the long-term public key of Edgeless Systems to verify the signature of downloaded runtime measurements. + +### Cluster creation + +When a cluster is [created](../workflows/create.md), the CLI automatically verifies the runtime measurements of the *first node* using remote attestation. Based on this, the CLI and the first node set up a temporary TLS connection. This [aTLS](#attested-tls-atls) connection is used for two things: + +1. The CLI sends the [master secret](../architecture/keys.md#master-secret) of the to-be-created cluster to the CLI. The master secret is generated by the first node. +2. The first node sends a [kubeconfig file](https://www.redhat.com/sysadmin/kubeconfig) with Kubernetes credentials to the CLI. + +After this, the aTLS connection is closed and the first node bootstraps the Kubernetes cluster. All subsequent interactions between the CLI and the cluster go via the [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) server running inside the cluster. The CLI (and other tools like kubectl) use the credentials referenced by the kubeconfig file to authenticate themselves towards the Kubernetes API server and to establish a mTLS connection. + +The CLI connects to the Kubernetes API to write the runtime measurements for the applicable node image to etcd. The JoinService uses these runtime measurements to verify all nodes that join the cluster subsequently. + +### Chain of trust + +In summary, there's a chain of trust based on cryptographic signatures that goes from the user to the cluster via the CLI. This is illustrated in the following diagram. + +```mermaid +flowchart LR + A[User]-- "verifies" -->B[CLI] + B[CLI]-- "verifies" -->C([Runtime measurements]) + D[Edgeless Systems]-- "signs" -->B[CLI] + D[Edgeless Systems]-- "signs" -->C([Runtime measurements]) + B[CLI]-- "verifies (remote attestation)" -->E[First node] + E[First node]-- "verifies (remote attestation)" -->F[Other nodes] + C([Runtime measurements]) -.-> E[First node] + C([Runtime measurements]) -.-> F[Other nodes] +``` + +### Upgrades + +Whenever a cluster is [upgraded](../workflows/upgrade.md) to a new version of the node image, the CLI sends the corresponding runtime measurements via the Kubernetes API server. The new runtime measurements are stored in etcd within the cluster and replace any previous runtime measurements. The new runtime measurements are then used automatically by the JoinService for the verification of new nodes. + +## References + +[^1]: Linux IMA produces runtime measurements of user-space binaries. +However, these measurements aren't deterministic and thus, PCR\[10] can't be compared to a constant value. +Instead, a policy engine must be used to verify the TPM event log against a policy. diff --git a/docs/versioned_docs/version-2.19/architecture/encrypted-storage.md b/docs/versioned_docs/version-2.19/architecture/encrypted-storage.md new file mode 100644 index 000000000..f047fa4a9 --- /dev/null +++ b/docs/versioned_docs/version-2.19/architecture/encrypted-storage.md @@ -0,0 +1,62 @@ +# Encrypted persistent storage + +Confidential VMs provide runtime memory encryption to protect data in use. +In the context of Kubernetes, this is sufficient for the confidentiality and integrity of stateless services. +Consider a front-end web server, for example, that keeps all connection information cached in main memory. +No sensitive data is ever written to an insecure medium. +However, many real-world applications need some form of state or data-lake service that's connected to a persistent storage device and requires encryption at rest. +As described in [Use persistent storage](../workflows/storage.md), cloud service providers (CSPs) use the container storage interface (CSI) to make their storage solutions available to Kubernetes workloads. +These CSI storage solutions often support some sort of encryption. +For example, Google Cloud [encrypts data at rest by default](https://cloud.google.com/security/encryption/default-encryption), without any action required by the customer. + +## Cloud provider-managed encryption + +CSP-managed storage solutions encrypt the data in the cloud backend before writing it physically to disk. +In the context of confidential computing and Constellation, the CSP and its managed services aren't trusted. +Hence, cloud provider-managed encryption protects your data from offline hardware access to physical storage devices. +It doesn't protect it from anyone with infrastructure-level access to the storage backend or a malicious insider in the cloud platform. +Even with "bring your own key" or similar concepts, the CSP performs the encryption process with access to the keys and plaintext data. + +In the security model of Constellation, securing persistent storage and thereby data at rest requires that all cryptographic operations are performed inside a trusted execution environment. +Consequently, using CSP-managed encryption of persistent storage usually isn't an option. + +## Constellation-managed encryption + +Constellation provides CSI drivers for storage solutions in all major clouds with built-in encryption support. +Block storage provisioned by the CSP is [mapped](https://guix.gnu.org/manual/en/html_node/Mapped-Devices.html) using the [dm-crypt](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-crypt.html), and optionally the [dm-integrity](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-integrity.html), kernel modules, before it's formatted and accessed by the Kubernetes workloads. +All cryptographic operations happen inside the trusted environment of the confidential Constellation node. + +Note that for integrity-protected disks, [volume expansion](https://kubernetes.io/blog/2018/07/12/resizing-persistent-volumes-using-kubernetes/) isn't supported. + +By default the driver uses data encryption keys (DEKs) issued by the Constellation [*KeyService*](microservices.md#keyservice). +The DEKs are in turn derived from the Constellation's key encryption key (KEK), which is directly derived from the [master secret](keys.md#master-secret). +This is the recommended mode of operation, and also requires the least amount of setup by the cluster administrator. + +Alternatively, the driver can be configured to use a key management system to store and access KEKs and DEKs. + +Refer to [keys and cryptography](keys.md) for more details on key management in Constellation. + +Once deployed and configured, the CSI driver ensures transparent encryption and integrity of all persistent volumes provisioned via its storage class. +Data at rest is secured without any additional actions required by the developer. + +## Cryptographic algorithms + +This section gives an overview of the libraries, cryptographic algorithms, and their configurations, used in Constellation's CSI drivers. + +### dm-crypt + +To interact with the dm-crypt kernel module, Constellation uses [libcryptsetup](https://gitlab.com/cryptsetup/cryptsetup/). +New devices are formatted as [LUKS2](https://gitlab.com/cryptsetup/LUKS2-docs/-/tree/master) partitions with a sector size of 4096 bytes. +The used key derivation function is [Argon2id](https://datatracker.ietf.org/doc/html/rfc9106) with the [recommended parameters for memory-constrained environments](https://datatracker.ietf.org/doc/html/rfc9106#section-7.4) of 3 iterations and 64 MiB of memory, utilizing 4 parallel threads. +For encryption Constellation uses AES in XTS-Plain64. The key size is 512 bit. + +### dm-integrity + +To interact with the dm-integrity kernel module, Constellation uses [libcryptsetup](https://gitlab.com/cryptsetup/cryptsetup/). +When enabled, the used data integrity algorithm is [HMAC](https://datatracker.ietf.org/doc/html/rfc2104) with SHA256 as the hash function. +The tag size is 32 Bytes. + +## Encrypted S3 object storage + +Constellation comes with a service that you can use to transparently retrofit client-side encryption to existing applications that use S3 (AWS or compatible) for storage. +To learn more, check out the [s3proxy documentation](../workflows/s3proxy.md). diff --git a/docs/versioned_docs/version-2.19/architecture/images.md b/docs/versioned_docs/version-2.19/architecture/images.md new file mode 100644 index 000000000..8a9c51d36 --- /dev/null +++ b/docs/versioned_docs/version-2.19/architecture/images.md @@ -0,0 +1,49 @@ +# Constellation images + +Constellation uses a minimal version of Fedora as the operating system running inside confidential VMs. This Linux distribution is optimized for containers and designed to be stateless. +The Constellation images provide measured boot and an immutable filesystem. + +## Measured boot + +```mermaid +flowchart LR + Firmware --> Bootloader + Bootloader --> uki + subgraph uki[Unified Kernel Image] + Kernel[Kernel] + initramfs[Initramfs] + cmdline[Kernel Command Line] + end + uki --> rootfs[Root Filesystem] +``` + +Measured boot uses a Trusted Platform Module (TPM) to measure every part of the boot process. This allows for verification of the integrity of a running system at any point in time. To ensure correct measurements of every stage, each stage is responsible to measure the next stage before transitioning. + +### Firmware + +With confidential VMs, the firmware is the root of trust and is measured automatically at boot. After initialization, the firmware will load and measure the bootloader before executing it. + +### Bootloader + +The bootloader is the first modifiable part of the boot chain. The bootloader is tasked with loading the kernel, initramfs and setting the kernel command line. The Constellation bootloader measures these components before starting the kernel. + +### initramfs + +The initramfs is a small filesystem loaded to prepare the actual root filesystem. The Constellation initramfs maps the block device containing the root filesystem with [dm-verity](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html). The initramfs then mounts the root filesystem from the mapped block device. + +dm-verity provides integrity checking using a cryptographic hash tree. When a block is read, its integrity is checked by verifying the tree against a trusted root hash. The initramfs reads this root hash from the previously measured kernel command line. Thus, if any block of the root filesystem's device is modified on disk, trying to read the modified block will result in a kernel panic at runtime. + +After mounting the root filesystem, the initramfs will switch over and start the `init` process of the integrity-protected root filesystem. + +## State disk + +In addition to the read-only root filesystem, each Constellation node has a disk for storing state data. +This disk is mounted readable and writable by the initramfs and contains data that should persist across reboots. +Such data can contain sensitive information and, therefore, must be stored securely. +To that end, the state disk is protected by authenticated encryption. +See the section on [keys and encryption](keys.md#storage-encryption) for more information on the cryptographic primitives in use. + +## Kubernetes components + +During initialization, the [*Bootstrapper*](microservices.md#bootstrapper) downloads and verifies the [Kubernetes components](https://kubernetes.io/docs/concepts/overview/components/) as configured by the user. +They're stored on the state partition and can be updated once new releases need to be installed. diff --git a/docs/versioned_docs/version-2.19/architecture/keys.md b/docs/versioned_docs/version-2.19/architecture/keys.md new file mode 100644 index 000000000..553d9d4e2 --- /dev/null +++ b/docs/versioned_docs/version-2.19/architecture/keys.md @@ -0,0 +1,131 @@ +# Key management and cryptographic primitives + +Constellation protects and isolates your cluster and workloads. +To that end, cryptography is the foundation that ensures the confidentiality and integrity of all components. +Evaluating the security and compliance of Constellation requires a precise understanding of the cryptographic primitives and keys used. +The following gives an overview of the architecture and explains the technical details. + +## Confidential VMs + +Confidential VM (CVM) technology comes with hardware and software components for memory encryption, isolation, and remote attestation. +For details on the implementations and cryptographic soundness, refer to the hardware vendors' documentation and advisories. + +## Master secret + +The master secret is the cryptographic material used for deriving the [*clusterID*](#cluster-identity) and the *key encryption key (KEK)* for [storage encryption](#storage-encryption). +It's generated during the bootstrapping of a Constellation cluster. +It can either be managed by [Constellation](#constellation-managed-key-management) or an [external key management system](#user-managed-key-management). +In case of [recovery](#recovery-and-migration), the master secret allows to decrypt the state and recover a Constellation cluster. + +## Cluster identity + +The identity of a Constellation cluster is represented by cryptographic [measurements](attestation.md#runtime-measurements): + +The **base measurements** represent the identity of a valid, uninitialized Constellation node. +They depend on the node image, but are otherwise the same for every Constellation cluster. +On node boot, they're determined using the CVM's attestation mechanism and [measured boot up to the read-only root filesystem](images.md). + +The **clusterID** represents the identity of a single initialized Constellation cluster. +It's derived from the master secret and a cryptographically random salt and unique for every Constellation cluster. +The [Bootstrapper](microservices.md#bootstrapper) measures the *clusterID* into its own PCR before executing any code not measured as part of the *base measurements*. +See [Node attestation](attestation.md#node-attestation) for details. + +The remote attestation statement of a Constellation cluster combines the *base measurements* and the *clusterID* for a verifiable, unspoofable, unique identity. + +## Network encryption + +Constellation encrypts all cluster network communication using the [container network interface (CNI)](https://github.com/containernetworking/cni). +See [network encryption](networking.md) for more details. + +The Cilium agent running on each node establishes a secure [WireGuard](https://www.wireguard.com/) tunnel between it and all other known nodes in the cluster. +Each node creates its own [Curve25519](http://cr.yp.to/ecdh.html) encryption key pair and distributes its public key via Kubernetes. +A node uses another node's public key to decrypt and encrypt traffic from and to Cilium-managed endpoints running on that node. +Connections are always encrypted peer-to-peer using [ChaCha20](http://cr.yp.to/chacha.html) with [Poly1305](http://cr.yp.to/mac.html). +WireGuard implements [forward secrecy with key rotation every 2 minutes](https://lists.zx2c4.com/pipermail/wireguard/2017-December/002141.html). +Cilium supports [key rotation](https://docs.cilium.io/en/stable/security/network/encryption-ipsec/#key-rotation) for the long-term node keys via Kubernetes secrets. + +## Storage encryption + +Constellation supports transparent encryption of persistent storage. +The Linux kernel's device mapper-based encryption features are used to encrypt the data on the block storage level. +Currently, the following primitives are used for block storage encryption: + +* [dm-crypt](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-crypt.html) +* [dm-integrity](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-integrity.html) + +Adding primitives for integrity protection in the CVM attacker model are under active development and will be available in a future version of Constellation. +See [encrypted storage](encrypted-storage.md) for more details. + +As a cluster administrator, when creating a cluster, you can use the Constellation [installation program](orchestration.md) to select one of the following methods for key management: + +* Constellation-managed key management +* User-managed key management + +### Constellation-managed key management + +#### Key material and key derivation + +During the creation of a Constellation cluster, the cluster's master secret is used to derive a KEK. +This means creating two clusters with the same master secret will yield the same KEK. +Any data encryption key (DEK) is derived from the KEK via HKDF. +Note that the master secret is recommended to be unique for every cluster and shouldn't be reused (except in case of [recovering](../workflows/recovery.md) a cluster). + +#### State and storage + +The KEK is derived from the master secret during the initialization. +Subsequently, all other key material is derived from the KEK. +Given the same KEK, any DEK can be derived deterministically from a given identifier. +Hence, there is no need to store DEKs. They can be derived on demand. +After the KEK was derived, it's stored in memory only and never leaves the CVM context. + +#### Availability + +Constellation-managed key management has the same availability as the underlying Kubernetes cluster. +Therefore, the KEK is stored in the [distributed Kubernetes etcd storage](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/) to allow for unexpected but non-fatal (control-plane) node failure. +The etcd storage is backed by the encrypted and integrity protected [state disk](images.md#state-disk) of the nodes. + +#### Recovery + +Constellation clusters can be recovered in the event of a disaster, even when all node machines have been stopped and need to be rebooted. +For details on the process see the [recovery workflow](../workflows/recovery.md). + +### User-managed key management + +User-managed key management is under active development and will be available soon. +In scenarios where constellation-managed key management isn't an option, this mode allows you to keep full control of your keys. +For example, compliance requirements may force you to keep your KEKs in an on-prem key management system (KMS). + +During the creation of a Constellation cluster, you specify a KEK present in a remote KMS. +This follows the common scheme of "bring your own key" (BYOK). +Constellation will support several KMSs for managing the storage and access of your KEK. +Initially, it will support the following KMSs: + +* [AWS KMS](https://aws.amazon.com/kms/) +* [GCP KMS](https://cloud.google.com/security-key-management) +* [Azure Key Vault](https://azure.microsoft.com/en-us/services/key-vault/#product-overview) +* [KMIP-compatible KMS](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=kmip) + +Storing the keys in Cloud KMS of AWS, Azure, or GCP binds the key usage to the particular cloud identity access management (IAM). +In the future, Constellation will support remote attestation-based access policies for Cloud KMS once available. +Note that using a Cloud KMS limits the isolation and protection to the guarantees of the particular offering. + +KMIP support allows you to use your KMIP-compatible on-prem KMS and keep full control over your keys. +This follows the common scheme of "hold your own key" (HYOK). + +The KEK is used to encrypt per-data "data encryption keys" (DEKs). +DEKs are generated to encrypt your data before storing it on persistent storage. +After being encrypted by the KEK, the DEKs are stored on dedicated cloud storage for persistence. +Currently, Constellation supports the following cloud storage options: + +* [AWS S3](https://aws.amazon.com/s3/) +* [GCP Cloud Storage](https://cloud.google.com/storage) +* [Azure Blob Storage](https://azure.microsoft.com/en-us/services/storage/blobs/#overview) + +The DEKs are only present in plaintext form in the encrypted main memory of the CVMs. +Similarly, the cryptographic operations for encrypting data before writing it to persistent storage are performed in the context of the CVMs. + +#### Recovery and migration + +In the case of a disaster, the KEK can be used to decrypt the DEKs locally and subsequently use them to decrypt and retrieve the data. +In case of migration, configuring the same KEK will provide seamless migration of data. +Thus, only the DEK storage needs to be transferred to the new cluster alongside the encrypted data for seamless migration. diff --git a/docs/versioned_docs/version-2.19/architecture/microservices.md b/docs/versioned_docs/version-2.19/architecture/microservices.md new file mode 100644 index 000000000..90bae783b --- /dev/null +++ b/docs/versioned_docs/version-2.19/architecture/microservices.md @@ -0,0 +1,73 @@ +# Microservices + +Constellation takes care of bootstrapping and initializing a Confidential Kubernetes cluster. +During the lifetime of the cluster, it handles day 2 operations such as key management, remote attestation, and updates. +These features are provided by several microservices: + +* The [Bootstrapper](microservices.md#bootstrapper) initializes a Constellation node and bootstraps the cluster +* The [JoinService](microservices.md#joinservice) joins new nodes to an existing cluster +* The [VerificationService](microservices.md#verificationservice) provides remote attestation functionality +* The [KeyService](microservices.md#keyservice) manages Constellation-internal keys + +The relations between microservices are shown in the following diagram: + +```mermaid +flowchart LR + subgraph admin [Admin's machine] + A[Constellation CLI] + end + subgraph img [Constellation OS image] + B[Constellation OS] + C[Bootstrapper] + end + subgraph Kubernetes + D[JoinService] + E[KeyService] + F[VerificationService] + end + A -- deploys --> + B -- starts --> C + C -- deploys --> D + C -- deploys --> E + C -- deploys --> F +``` + +## Bootstrapper + +The *Bootstrapper* is the first microservice launched after booting a Constellation node image. +It sets up that machine as a Kubernetes node and integrates that node into the Kubernetes cluster. +To this end, the *Bootstrapper* first downloads and verifies the [Kubernetes components](https://kubernetes.io/docs/concepts/overview/components/) at the configured versions. +The *Bootstrapper* tries to find an existing cluster and if successful, communicates with the [JoinService](microservices.md#joinservice) to join the node. +Otherwise, it waits for an initialization request to create a new Kubernetes cluster. + +## JoinService + +The *JoinService* runs as [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) on each control-plane node. +New nodes (at cluster start, or later through autoscaling) send a request to the service over [attested TLS (aTLS)](attestation.md#attested-tls-atls). +The *JoinService* verifies the new node's certificate and attestation statement. +If attestation is successful, the new node is supplied with an encryption key from the [*KeyService*](microservices.md#keyservice) for its state disk, and a Kubernetes bootstrap token. + + +```mermaid +sequenceDiagram + participant New node + participant JoinService + New node->>JoinService: aTLS handshake (server side verification) + JoinService-->>New node: # + New node->>+JoinService: IssueJoinTicket(DiskUUID, NodeName, IsControlPlane) + JoinService->>+KeyService: GetDataKey(DiskUUID) + KeyService-->>-JoinService: DiskEncryptionKey + JoinService-->>-New node: DiskEncryptionKey, KubernetesJoinToken, ... +``` + +## VerificationService + +The *VerificationService* runs as DaemonSet on each node. +It provides user-facing functionality for remote attestation during the cluster's lifetime via an endpoint for [verifying the cluster](attestation.md#cluster-attestation). +Read more about the hardware-based [attestation feature](attestation.md) of Constellation and how to [verify](../workflows/verify-cluster.md) a cluster on the client side. + +## KeyService + +The *KeyService* runs as DaemonSet on each control-plane node. +It implements the key management for the [storage encryption keys](keys.md#storage-encryption) in Constellation. These keys are used for the [state disk](images.md#state-disk) of each node and the [transparently encrypted storage](encrypted-storage.md) for Kubernetes. +Depending on wether the [constellation-managed](keys.md#constellation-managed-key-management) or [user-managed](keys.md#user-managed-key-management) mode is used, the *KeyService* holds the key encryption key (KEK) directly or calls an external key management service (KMS) for key derivation respectively. diff --git a/docs/versioned_docs/version-2.19/architecture/networking.md b/docs/versioned_docs/version-2.19/architecture/networking.md new file mode 100644 index 000000000..e9cbdf029 --- /dev/null +++ b/docs/versioned_docs/version-2.19/architecture/networking.md @@ -0,0 +1,22 @@ +# Network encryption + +Constellation encrypts all pod communication using the [container network interface (CNI)](https://github.com/containernetworking/cni). +To that end, Constellation deploys, configures, and operates the [Cilium](https://cilium.io/) CNI plugin. +Cilium provides [transparent encryption](https://docs.cilium.io/en/stable/security/network/encryption) for all cluster traffic using either IPSec or [WireGuard](https://www.wireguard.com/). +Currently, Constellation only supports WireGuard as the encryption engine. +You can read more about the cryptographic soundness of WireGuard [in their white paper](https://www.wireguard.com/papers/wireguard.pdf). + +Cilium is actively working on implementing a feature called [`host-to-host`](https://github.com/cilium/cilium/pull/19401) encryption mode for WireGuard. +With `host-to-host`, all traffic between nodes will be tunneled via WireGuard (host-to-host, host-to-pod, pod-to-host, pod-to-pod). +Until the `host-to-host` feature is released, Constellation enables `pod-to-pod` encryption. +This mode encrypts all traffic between Kubernetes pods using WireGuard tunnels. + +When using Cilium in the default setup but with encryption enabled, there is a [known issue](https://docs.cilium.io/en/v1.12/gettingstarted/encryption/#egress-traffic-to-not-yet-discovered-remote-endpoints-may-be-unencrypted) +that can cause pod-to-pod traffic to be unencrypted. +To mitigate this issue, Constellation adds a *strict* mode to Cilium's `pod-to-pod` encryption. +This mode changes the default behavior of traffic that's destined for an unknown endpoint to not be send out in plaintext, but instead being dropped. +The strict mode distinguishes between traffic that's send to a pod from traffic that's destined for a cluster-external endpoint by considering the pod's CIDR range. + +Traffic originating from hosts isn't encrypted yet. +This mainly includes health checks from Kubernetes API server. +Also, traffic proxied over the API server via e.g. `kubectl port-forward` isn't encrypted. diff --git a/docs/versioned_docs/version-2.19/architecture/observability.md b/docs/versioned_docs/version-2.19/architecture/observability.md new file mode 100644 index 000000000..0f4daffd4 --- /dev/null +++ b/docs/versioned_docs/version-2.19/architecture/observability.md @@ -0,0 +1,74 @@ +# Observability + +In Kubernetes, observability is the ability to gain insight into the behavior and performance of applications. +It helps identify and resolve issues more effectively, ensuring stability and performance of Kubernetes workloads, reducing downtime and outages, and improving efficiency. +The "three pillars of observability" are logs, metrics, and traces. + +In the context of Confidential Computing, observability is a delicate subject and needs to be applied such that it doesn't leak any sensitive information. +The following gives an overview of where and how you can apply standard observability tools in Constellation. + +## Cloud resource monitoring + +While inaccessible, Constellation's nodes are still visible as black box VMs to the hypervisor. +Resource consumption, such as memory and CPU utilization, can be monitored from the outside and observed via the cloud platforms directly. +Similarly, other resources, such as storage and network and their respective metrics, are visible via the cloud platform. + +## Metrics + +Metrics are numeric representations of data measured over intervals of time. They're essential for understanding system health and gaining insights using telemetry signals. + +By default, Constellation exposes the [metrics for Kubernetes system components](https://kubernetes.io/docs/concepts/cluster-administration/system-metrics/) inside the cluster. +Similarly, the [etcd metrics](https://etcd.io/docs/v3.5/metrics/) endpoints are exposed inside the cluster. +These [metrics endpoints can be disabled](https://kubernetes.io/docs/concepts/cluster-administration/system-metrics/#disabling-metrics). + +You can collect these cluster-internal metrics via tools such as [Prometheus](https://prometheus.io/) or the [Elastic Stack](https://www.elastic.co/de/elastic-stack/). + +Constellation's CNI Cilium also supports [metrics via Prometheus endpoints](https://docs.cilium.io/en/latest/observability/metrics/). +However, in Constellation, they're disabled by default and must be enabled first. + +## Logs + +Logs represent discrete events that usually describe what's happening with your service. +The payload is an actual message emitted from your system along with a metadata section containing a timestamp, labels, and tracking identifiers. + +### System logs + +Detailed system-level logs are accessible via `/var/log` and [journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) on the nodes directly. +They can be collected from there, for example, via [Filebeat and Logstash](https://www.elastic.co/guide/en/beats/filebeat/current/logstash-output.html), which are tools of the [Elastic Stack](https://www.elastic.co/de/elastic-stack/). + +In case of an error during the initialization, the CLI automatically collects the [Bootstrapper](./microservices.md#bootstrapper) logs and returns these as a file for [troubleshooting](../workflows/troubleshooting.md). Here is an example of such an event: + +```shell-session +Cluster initialization failed. This error is not recoverable. +Terminate your cluster and try again. +Fetched bootstrapper logs are stored in "constellation-cluster.log" +``` + +### Kubernetes logs + +Constellation supports the [Kubernetes logging architecture](https://kubernetes.io/docs/concepts/cluster-administration/logging/). +By default, logs are written to the nodes' encrypted state disks. +These include the Pod and container logs and the [system component logs](https://kubernetes.io/docs/concepts/cluster-administration/logging/#system-component-logs). + +[Constellation services](microservices.md) run as Pods inside the `kube-system` namespace and use the standard container logging mechanism. +The same applies for the [Cilium Pods](https://docs.cilium.io/en/latest/operations/troubleshooting/#logs). + +You can collect logs from within the cluster via tools such as [Fluentd](https://github.com/fluent/fluentd), [Loki](https://github.com/grafana/loki), or the [Elastic Stack](https://www.elastic.co/de/elastic-stack/). + +## Traces + +Modern systems are implemented as interconnected complex and distributed microservices. Understanding request flows and system communications is challenging, mainly because all systems in a chain need to be modified to propagate tracing information. Distributed tracing is a new approach to increasing observability and understanding performance bottlenecks. A trace represents consecutive events that reflect an end-to-end request path in a distributed system. + +Constellation supports [traces for Kubernetes system components](https://kubernetes.io/docs/concepts/cluster-administration/system-traces/). +By default, they're disabled and need to be enabled first. + +Similarly, Cilium can be enabled to [export traces](https://cilium.io/use-cases/metrics-export/). + +You can collect these traces via tools such as [Jaeger](https://www.jaegertracing.io/) or [Zipkin](https://zipkin.io/). + +## Integrations + +Platforms and SaaS solutions such as Datadog, logz.io, Dynatrace, or New Relic facilitate the observability challenge for Kubernetes and provide all-in-one SaaS solutions. +They install agents into the cluster that collect metrics, logs, and tracing information and upload them into the data lake of the platform. +Technically, the agent-based approach is compatible with Constellation, and attaching these platforms is straightforward. +However, you need to evaluate if the exported data might violate Constellation's compliance and privacy guarantees by uploading them to a third-party platform. diff --git a/docs/versioned_docs/version-2.19/architecture/orchestration.md b/docs/versioned_docs/version-2.19/architecture/orchestration.md new file mode 100644 index 000000000..3c8d529e7 --- /dev/null +++ b/docs/versioned_docs/version-2.19/architecture/orchestration.md @@ -0,0 +1,83 @@ +# Orchestrating Constellation clusters + +You can use the CLI to create a cluster on the supported cloud platforms. +The CLI provisions the resources in your cloud environment and initiates the initialization of your cluster. +It uses a set of parameters and an optional configuration file to manage your cluster installation. +The CLI is also used for updating your cluster. + +## Workspaces + +Each Constellation cluster has an associated *workspace*. +The workspace is where data such as the Constellation state and config files are stored. +Each workspace is associated with a single cluster and configuration. +The CLI stores state in the local filesystem making the current directory the active workspace. +Multiple clusters require multiple workspaces, hence, multiple directories. +Note that every operation on a cluster always has to be performed from the directory associated with its workspace. + +You may copy files from the workspace to other locations, +but you shouldn't move or delete them while the cluster is still being used. +The Constellation CLI takes care of managing the workspace. +Only when a cluster was terminated, and you are sure the files aren't needed anymore, should you remove a workspace. + +## Cluster creation process + +To allow for fine-grained configuration of your cluster and cloud environment, Constellation supports an extensive configuration file with strong defaults. [Generating the configuration file](../workflows/config.md) is typically the first thing you do in the workspace. + +Altogether, the following files are generated during the creation of a Constellation cluster and stored in the current workspace: + +* a configuration file +* a state file +* a Base64-encoded master secret +* [Terraform artifacts](../reference/terraform.md), stored in subdirectories +* a Kubernetes `kubeconfig` file. + +After the initialization of your cluster, the CLI will provide you with a Kubernetes `kubeconfig` file. +This file grants you access to your Kubernetes cluster and configures the [kubectl](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) tool. +In addition, the cluster's [identifier](orchestration.md#post-installation-configuration) is returned and stored in the state file. + +### Creation process details + +1. The CLI `apply` command first creates the confidential VM (CVM) resources in your cloud environment and configures the network +2. Each CVM boots the Constellation node image and measures every component in the boot chain +3. The first microservice launched in each node is the [*Bootstrapper*](microservices.md#bootstrapper) +4. The *Bootstrapper* waits until it either receives an initialization request or discovers an initialized cluster +5. The CLI then connects to the *Bootstrapper* of a selected node, sends the configuration, and initiates the initialization of the cluster +6. The *Bootstrapper* of **that** node [initializes the Kubernetes cluster](microservices.md#bootstrapper) and deploys the other Constellation [microservices](microservices.md) including the [*JoinService*](microservices.md#joinservice) +7. Subsequently, the *Bootstrappers* of the other nodes discover the initialized cluster and send join requests to the *JoinService* +8. As part of the join request each node includes an attestation statement of its boot measurements as authentication +9. The *JoinService* verifies the attestation statements and joins the nodes to the Kubernetes cluster +10. This process is repeated for every node joining the cluster later (e.g., through autoscaling) + +## Post-installation configuration + +Post-installation the CLI provides a configuration for [accessing the cluster using the Kubernetes API](https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/). +The `kubeconfig` file provides the credentials and configuration for connecting and authenticating to the API server. +Once configured, orchestrate the Kubernetes cluster via `kubectl`. + +After the initialization, the CLI will present you with a couple of tokens: + +* The [*master secret*](keys.md#master-secret) (stored in the `constellation-mastersecret.json` file by default) +* The [*clusterID*](keys.md#cluster-identity) of your cluster in Base64 encoding + +You can read more about these values and their meaning in the guide on [cluster identity](keys.md#cluster-identity). + +The *master secret* must be kept secret and can be used to [recover your cluster](../workflows/recovery.md). +Instead of managing this secret manually, you can [use your key management solution of choice](keys.md#user-managed-key-management) with Constellation. + +The *clusterID* uniquely identifies a cluster and can be used to [verify your cluster](../workflows/verify-cluster.md). + +## Upgrades + +Constellation images and microservices may need to be upgraded to new versions during the lifetime of a cluster. +Constellation implements a rolling update mechanism ensuring no downtime of the control or data plane. +You can upgrade a Constellation cluster with a single operation by using the CLI. +For step-by-step instructions on how to do this, refer to [Upgrade your cluster](../workflows/upgrade.md). + +### Attestation of upgrades + +With every new image, corresponding measurements are released. +During an update procedure, the CLI provides new measurements to the [JoinService](microservices.md#joinservice) securely. +New measurements for an updated image are automatically pulled and verified by the CLI following the [supply chain security concept](attestation.md#chain-of-trust) of Constellation. +The [attestation section](attestation.md#cluster-facing-attestation) describes in detail how these measurements are then used by the JoinService for the attestation of nodes. + + diff --git a/docs/versioned_docs/version-2.19/architecture/overview.md b/docs/versioned_docs/version-2.19/architecture/overview.md new file mode 100644 index 000000000..386f93b2f --- /dev/null +++ b/docs/versioned_docs/version-2.19/architecture/overview.md @@ -0,0 +1,30 @@ +# Overview + +Constellation is a cloud-based confidential orchestration platform. +The foundation of Constellation is Kubernetes and therefore shares the same technology stack and architecture principles. +To learn more about Constellation and Kubernetes, see [product overview](../overview/product.md). + +## About orchestration and updates + +As a cluster administrator, you can use the [Constellation CLI](orchestration.md) to install and deploy a cluster. +Updates are provided in accordance with the [support policy](versions.md). + +## About microservices and attestation + +Constellation manages the nodes and network in your cluster. All nodes are bootstrapped by the [*Bootstrapper*](microservices.md#bootstrapper). They're verified and authenticated by the [*JoinService*](microservices.md#joinservice) before being added to the cluster and the network. Finally, the entire cluster can be verified via the [*VerificationService*](microservices.md#verificationservice) using [remote attestation](attestation.md). + +## About node images and verified boot + +Constellation comes with operating system images for Kubernetes control-plane and worker nodes. +They're highly optimized for running containerized workloads and specifically prepared for running inside confidential VMs. +You can learn more about [the images](images.md) and how verified boot ensures their integrity during boot and beyond. + +## About key management and cryptographic primitives + +Encryption of data at-rest, in-transit, and in-use is the fundamental building block for confidential computing and Constellation. Learn more about the [keys and cryptographic primitives](keys.md) used in Constellation, [encrypted persistent storage](encrypted-storage.md), and [network encryption](networking.md). + +## About observability + +Observability in Kubernetes refers to the capability to troubleshoot issues using telemetry signals such as logs, metrics, and traces. +In the realm of Confidential Computing, it's crucial that observability aligns with confidentiality, necessitating careful implementation. +Learn more about the [observability capabilities in Constellation](./observability.md). diff --git a/docs/versioned_docs/version-2.19/architecture/versions.md b/docs/versioned_docs/version-2.19/architecture/versions.md new file mode 100644 index 000000000..6127bfb0c --- /dev/null +++ b/docs/versioned_docs/version-2.19/architecture/versions.md @@ -0,0 +1,21 @@ +# Versions and support policy + +All components of Constellation use a three-digit version number of the form `v..`. +The components are released in lock step, usually on the first Tuesday of every month. This release primarily introduces new features, but may also include security or performance improvements. The `MINOR` version will be incremented as part of this release. + +Additional `PATCH` releases may be created on demand, to fix security issues or bugs before the next `MINOR` release window. + +New releases are published on [GitHub](https://github.com/edgelesssys/constellation/releases). + +## Kubernetes support policy + +Constellation is aligned to the [version support policy of Kubernetes](https://kubernetes.io/releases/version-skew-policy/#supported-versions), and therefore usually supports the most recent three minor versions. +When a new minor version of Kubernetes is released, support is added to the next Constellation release, and that version then supports four Kubernetes versions. +Subsequent Constellation releases drop support for the oldest (and deprecated) Kubernetes version. + +The following Kubernetes versions are currently supported: + + +* v1.28.14 +* v1.29.9 +* v1.30.5 diff --git a/docs/versioned_docs/version-2.19/getting-started/examples.md b/docs/versioned_docs/version-2.19/getting-started/examples.md new file mode 100644 index 000000000..fded84980 --- /dev/null +++ b/docs/versioned_docs/version-2.19/getting-started/examples.md @@ -0,0 +1,6 @@ +# Examples + +After you [installed the CLI](install.md) and [created your first cluster](first-steps.md), you're ready to deploy applications. Why not start with one of the following examples? +* [Emojivoto](examples/emojivoto.md): a simple but fun web application +* [Online Boutique](examples/online-boutique.md): an e-commerce demo application by Google consisting of 11 separate microservices +* [Horizontal Pod Autoscaling](examples/horizontal-scaling.md): an example demonstrating Constellation's autoscaling capabilities diff --git a/docs/versioned_docs/version-2.19/getting-started/examples/emojivoto.md b/docs/versioned_docs/version-2.19/getting-started/examples/emojivoto.md new file mode 100644 index 000000000..2bbe27917 --- /dev/null +++ b/docs/versioned_docs/version-2.19/getting-started/examples/emojivoto.md @@ -0,0 +1,22 @@ +# Emojivoto +[Emojivoto](https://github.com/BuoyantIO/emojivoto) is a simple and fun application that's well suited to test the basic functionality of your cluster. + + + +emojivoto - Web UI + + + +1. Deploy the application: + ```bash + kubectl apply -k github.com/BuoyantIO/emojivoto/kustomize/deployment + ``` +2. Wait until it becomes available: + ```bash + kubectl wait --for=condition=available --timeout=60s -n emojivoto --all deployments + ``` +3. Forward the web service to your machine: + ```bash + kubectl -n emojivoto port-forward svc/web-svc 8080:80 + ``` +4. Visit [http://localhost:8080](http://localhost:8080) diff --git a/docs/versioned_docs/version-2.19/getting-started/examples/filestash-s3proxy.md b/docs/versioned_docs/version-2.19/getting-started/examples/filestash-s3proxy.md new file mode 100644 index 000000000..b9a394256 --- /dev/null +++ b/docs/versioned_docs/version-2.19/getting-started/examples/filestash-s3proxy.md @@ -0,0 +1,107 @@ + +# Deploying Filestash + +Filestash is a web frontend for different storage backends, including S3. +It's a useful application to showcase s3proxy in action. + +1. Deploy s3proxy as described in [Deployment](../../workflows/s3proxy.md#deployment). +2. Create a deployment file for Filestash with one pod: + +```sh +cat << EOF > "deployment-filestash.yaml" +apiVersion: apps/v1 +kind: Deployment +metadata: + name: filestash +spec: + replicas: 1 + selector: + matchLabels: + app: filestash + template: + metadata: + labels: + app: filestash + spec: + hostAliases: + - ip: $(kubectl get svc s3proxy-service -o=jsonpath='{.spec.clusterIP}') + hostnames: + - "s3.us-east-1.amazonaws.com" + - "s3.us-east-2.amazonaws.com" + - "s3.us-west-1.amazonaws.com" + - "s3.us-west-2.amazonaws.com" + - "s3.eu-north-1.amazonaws.com" + - "s3.eu-south-1.amazonaws.com" + - "s3.eu-south-2.amazonaws.com" + - "s3.eu-west-1.amazonaws.com" + - "s3.eu-west-2.amazonaws.com" + - "s3.eu-west-3.amazonaws.com" + - "s3.eu-central-1.amazonaws.com" + - "s3.eu-central-2.amazonaws.com" + - "s3.ap-northeast-1.amazonaws.com" + - "s3.ap-northeast-2.amazonaws.com" + - "s3.ap-northeast-3.amazonaws.com" + - "s3.ap-east-1.amazonaws.com" + - "s3.ap-southeast-1.amazonaws.com" + - "s3.ap-southeast-2.amazonaws.com" + - "s3.ap-southeast-3.amazonaws.com" + - "s3.ap-southeast-4.amazonaws.com" + - "s3.ap-south-1.amazonaws.com" + - "s3.ap-south-2.amazonaws.com" + - "s3.me-south-1.amazonaws.com" + - "s3.me-central-1.amazonaws.com" + - "s3.il-central-1.amazonaws.com" + - "s3.af-south-1.amazonaws.com" + - "s3.ca-central-1.amazonaws.com" + - "s3.sa-east-1.amazonaws.com" + containers: + - name: filestash + image: machines/filestash:latest + ports: + - containerPort: 8334 + volumeMounts: + - name: ca-cert + mountPath: /etc/ssl/certs/kube-ca.crt + subPath: kube-ca.crt + volumes: + - name: ca-cert + secret: + secretName: s3proxy-tls + items: + - key: ca.crt + path: kube-ca.crt +EOF +``` + +The pod spec includes the `hostAliases` key, which adds an entry to the pod's `/etc/hosts`. +The entry forwards all requests for any of the currently defined AWS regions to the Kubernetes service `s3proxy-service`. +If you followed the s3proxy [Deployment](../../workflows/s3proxy.md#deployment) guide, this service points to a s3proxy pod. + +The deployment specifies all regions explicitly to prevent accidental data leaks. +If one of your buckets were located in a region that's not part of the `hostAliases` key, traffic towards those buckets would not be redirected to s3proxy. +Similarly, if you want to exclude data for specific regions from going through s3proxy you can remove those regions from the deployment. + +The spec also includes a volume mount for the TLS certificate and adds it to the pod's certificate trust store. +The volume is called `ca-cert`. +The key `ca.crt` of that volume is mounted to `/etc/ssl/certs/kube-ca.crt`, which is the default certificate trust store location for that container's OpenSSL library. +Not adding the CA certificate will result in TLS authentication errors. + +3. Apply the file: `kubectl apply -f deployment-filestash.yaml` + +Afterward, you can use a port forward to access the Filestash pod: +`kubectl port-forward pod/$(kubectl get pod --selector='app=filestash' -o=jsonpath='{.items[*].metadata.name}') 8334:8334` + +4. After browsing to `localhost:8443`, Filestash will ask you to set an administrator password. +After setting it, you can directly leave the admin area by clicking the blue cloud symbol in the top left corner. +Subsequently, you can select S3 as storage backend and enter your credentials. +This will bring you to an overview of your buckets. +If you want to deploy Filestash in production, take a look at its [documentation](https://www.filestash.app/docs/). + +5. To see the logs of s3proxy intercepting requests made to S3, run: `kubectl logs -f pod/$(kubectl get pod --selector='app=s3proxy' -o=jsonpath='{.items[*].metadata.name}')` +Look out for log messages labeled `intercepting`. +There is one such log message for each message that's encrypted, decrypted, or blocked. + +6. Once you have uploaded a file with Filestash, you should be able to view the file in Filestash. +However, if you go to the AWS S3 [Web UI](https://s3.console.aws.amazon.com/s3/home) and download the file you just uploaded in Filestash, you won't be able to read it. +Another way to spot encrypted files without downloading them is to click on a file, scroll to the Metadata section, and look for the header named `x-amz-meta-constellation-encryption`. +This header holds the encrypted data encryption key of the object and is only present on objects that are encrypted by s3proxy. diff --git a/docs/versioned_docs/version-2.19/getting-started/examples/horizontal-scaling.md b/docs/versioned_docs/version-2.19/getting-started/examples/horizontal-scaling.md new file mode 100644 index 000000000..dfaf9e742 --- /dev/null +++ b/docs/versioned_docs/version-2.19/getting-started/examples/horizontal-scaling.md @@ -0,0 +1,98 @@ +# Horizontal Pod Autoscaling +This example demonstrates Constellation's autoscaling capabilities. It's based on the Kubernetes [HorizontalPodAutoscaler Walkthrough](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). During the following steps, Constellation will spawn new VMs on demand, verify them, add them to the cluster, and delete them again when the load has settled down. + +## Requirements +The cluster needs to be initialized with Kubernetes 1.23 or later. In addition, [autoscaling must be enabled](../../workflows/scale.md) to enable Constellation to assign new nodes dynamically. + +Just for this example specifically, the cluster should have as few worker nodes in the beginning as possible. Start with a small cluster with only *one* low-powered node for the control-plane node and *one* low-powered worker node. + +:::info +We tested the example using instances of types `Standard_DC4as_v5` on Azure and `n2d-standard-4` on GCP. +::: + +## Setup + +1. Install the Kubernetes Metrics Server: + ```bash + kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml + ``` + +2. Deploy the HPA example server that's supposed to be scaled under load. + + This manifest is similar to the one from the Kubernetes HPA walkthrough, but with increased CPU limits and requests to facilitate the triggering of node scaling events. + ```bash + cat < + +Online Boutique - Web UI + + + +1. Create a namespace: + ```bash + kubectl create ns boutique + ``` +2. Deploy the application: + ```bash + kubectl apply -n boutique -f https://github.com/GoogleCloudPlatform/microservices-demo/raw/main/release/kubernetes-manifests.yaml + ``` +3. Wait for all services to become available: + ```bash + kubectl wait --for=condition=available --timeout=300s -n boutique --all deployments + ``` +4. Get the frontend's external IP address: + ```shell-session + $ kubectl get service frontend-external -n boutique | awk '{print $4}' + EXTERNAL-IP + + ``` + (`` is a placeholder for the IP assigned by your CSP.) +5. Enter the IP from the result in your browser to browse the online shop. diff --git a/docs/versioned_docs/version-2.19/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.19/getting-started/first-steps-local.md new file mode 100644 index 000000000..98f0302de --- /dev/null +++ b/docs/versioned_docs/version-2.19/getting-started/first-steps-local.md @@ -0,0 +1,277 @@ +# First steps with a local cluster + +A local cluster lets you deploy and test Constellation without a cloud subscription. +You have two options: + +* Use MiniConstellation to automatically deploy a two-node cluster. +* For more fine-grained control, create the cluster using the QEMU provider. + +Both options use virtualization to create a local cluster with control-plane nodes and worker nodes. They **don't** require hardware with Confidential VM (CVM) support. For attestation, they currently use a software-based vTPM provided by KVM/QEMU. + +You need an x64 machine with a Linux OS. +You can use a VM, but it needs nested virtualization. + +## Prerequisites + +* Machine requirements: + * An x86-64 CPU with at least 4 cores (6 cores are recommended) + * At least 4 GB RAM (6 GB are recommended) + * 20 GB of free disk space + * Hardware virtualization enabled in the BIOS/UEFI (often referred to as Intel VT-x or AMD-V/SVM) / nested-virtualization support when using a VM +* Software requirements: + * Linux OS with [KVM kernel module](https://www.linux-kvm.org/page/Main_Page) + * Recommended: Ubuntu 22.04 LTS + * [Docker](https://docs.docker.com/engine/install/) + * [xsltproc](https://gitlab.gnome.org/GNOME/libxslt/-/wikis/home) + * (Optional) [virsh](https://www.libvirt.org/manpages/virsh.html) to observe and access your nodes + +### Software installation on Ubuntu + +```bash +# install Docker +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null +sudo apt update +sudo apt install docker-ce +# install other dependencies +sudo apt install xsltproc +sudo snap install kubectl --classic +# install Constellation CLI +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-linux-amd64 +sudo install constellation-linux-amd64 /usr/local/bin/constellation +# do not drop forwarded packages +sudo iptables -P FORWARD ACCEPT +``` + +## Create a cluster + + + + + +With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). + + +:::caution + +MiniConstellation has specific soft- and hardware requirements such as a Linux OS running on an x86-64 CPU. Pay attention to all [prerequisites](#prerequisites) when setting up. + +::: + +:::note + +Since MiniConstellation runs on your local system, cloud features such as load balancing, +attaching persistent storage, or autoscaling aren't available. + +::: + +The following creates your MiniConstellation cluster (may take up to 10 minutes to complete): + +```bash +constellation mini up +``` + +This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. +All `constellation` commands concerning this cluster need to be issued from this directory. + + + + +With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. + +:::caution + +Constellation on QEMU has specific soft- and hardware requirements such as a Linux OS running on an x86-64 CPU. Pay attention to all [prerequisites](#prerequisites) when setting up. + +::: + +:::note + +Since Constellation on QEMU runs on your local system, cloud features such as load balancing, +attaching persistent storage, or autoscaling aren't available. + +::: + +1. To set up your local cluster, you need to create a configuration file for Constellation first. + + ```bash + constellation config generate qemu + ``` + + This creates a [configuration file](../workflows/config.md) for QEMU called `constellation-conf.yaml`. After that, your current folder also becomes your [workspace](../architecture/orchestration.md#workspaces). All `constellation` commands for your cluster need to be executed from this directory. + +2. Now you can create your cluster and its nodes. `constellation apply` uses the options set in `constellation-conf.yaml`. + + ```bash + constellation apply -y + ``` + + The Output should look like the following: + + ```shell-session + $ constellation apply -y + Checking for infrastructure changes + The following Constellation cluster will be created: + 3 control-plane nodes of type 2-vCPUs will be created. + 1 worker node of type 2-vCPUs will be created. + Creating + Cloud infrastructure created successfully. + Your Constellation master secret was successfully written to ./constellation-mastersecret.json + Connecting + Initializing cluster + Installing Kubernetes components + Your Constellation cluster was successfully initialized. + + Constellation cluster identifier g6iMP5wRU1b7mpOz2WEISlIYSfdAhB0oNaOg6XEwKFY= + Kubernetes configuration constellation-admin.conf + + You can now connect to your cluster by executing: + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + + The cluster's identifier will be different in your output. + Keep `constellation-mastersecret.json` somewhere safe. + This will allow you to [recover your cluster](../workflows/recovery.md) in case of a disaster. + + :::info + + Depending on your setup, `constellation apply` may take 10+ minutes to complete. + + ::: + +3. Configure kubectl + + ```bash + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + + + + +## Connect to the cluster + +Your cluster initially consists of a single control-plane node: + +```shell-session +$ kubectl get nodes +NAME STATUS ROLES AGE VERSION +control-plane-0 Ready control-plane 66s v1.24.6 +``` + +Additional nodes will request to join the cluster shortly. Before each additional node is allowed to join the cluster, its state is verified using remote attestation by the [JoinService](../architecture/microservices.md#joinservice). +If verification passes successfully, the new node receives keys and certificates to join the cluster. + +You can follow this process by viewing the logs of the JoinService: + +```shell-session +$ kubectl logs -n kube-system daemonsets/join-service -f +{"level":"INFO","ts":"2022-10-14T09:32:20Z","caller":"cmd/main.go:48","msg":"Constellation Node Join Service","version":"2.1.0","cloudProvider":"qemu"} +{"level":"INFO","ts":"2022-10-14T09:32:20Z","logger":"validator","caller":"watcher/validator.go:96","msg":"Updating expected measurements"} +... +``` + +Once all nodes have joined your cluster, it may take a couple of minutes for all resources to become available. +You can check on the state of your cluster by running the following: + +```shell-session +$ kubectl get nodes +NAME STATUS ROLES AGE VERSION +control-plane-0 Ready control-plane 2m59s v1.24.6 +worker-0 Ready 32s v1.24.6 +``` + +## Deploy a sample application + +1. Deploy the [emojivoto app](https://github.com/BuoyantIO/emojivoto) + + ```bash + kubectl apply -k github.com/BuoyantIO/emojivoto/kustomize/deployment + ``` + +2. Expose the frontend service locally + + ```bash + kubectl wait --for=condition=available --timeout=60s -n emojivoto --all deployments + kubectl -n emojivoto port-forward svc/web-svc 8080:80 & + curl http://localhost:8080 + kill %1 + ``` + +## Terminate your cluster + + + + +Once you are done, you can clean up the created resources using the following command: + +```bash +constellation mini down +``` + +This will destroy your cluster and clean up your workspace. +The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. + + + + +Once you are done, you can clean up the created resources using the following command: + +```bash +constellation terminate +``` + +This should give the following output: + +```shell-session +$ constellation terminate +You are about to terminate a Constellation cluster. +All of its associated resources will be DESTROYED. +This action is irreversible and ALL DATA WILL BE LOST. +Do you want to continue? [y/n]: +``` + +Confirm with `y` to terminate the cluster: + +```shell-session +Terminating ... +Your Constellation cluster was terminated successfully. +``` + +This will destroy your cluster and clean up your workspace. +The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. + + + + +## Troubleshooting + +Make sure to use the [latest release](https://github.com/edgelesssys/constellation/releases/latest) and check out the [known issues](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22). + +### VMs have no internet access / CLI remains in "Initializing cluster" state + +`iptables` rules may prevent your VMs from accessing the internet. +Make sure your rules aren't dropping forwarded packages. + +List your rules: + +```bash +sudo iptables -S +``` + +The output may look similar to the following: + +```shell-session +-P INPUT ACCEPT +-P FORWARD DROP +-P OUTPUT ACCEPT +-N DOCKER +-N DOCKER-ISOLATION-STAGE-1 +-N DOCKER-ISOLATION-STAGE-2 +-N DOCKER-USER +``` + +If your `FORWARD` chain is set to `DROP`, you need to update your rules: + +```bash +sudo iptables -P FORWARD ACCEPT +``` diff --git a/docs/versioned_docs/version-2.19/getting-started/first-steps.md b/docs/versioned_docs/version-2.19/getting-started/first-steps.md new file mode 100644 index 000000000..128ac2849 --- /dev/null +++ b/docs/versioned_docs/version-2.19/getting-started/first-steps.md @@ -0,0 +1,229 @@ +# First steps with Constellation + +The following steps guide you through the process of creating a cluster and deploying a sample app. This example assumes that you have successfully [installed and set up Constellation](install.md), +and have access to a cloud subscription. + +:::tip +If you don't have a cloud subscription, you can also set up a [local Constellation cluster using virtualization](../getting-started/first-steps-local.md) for testing. +::: + +:::note +If you encounter any problem with the following steps, make sure to use the [latest release](https://github.com/edgelesssys/constellation/releases/latest) and check out the [known issues](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22). +::: + +## Create a cluster + +1. Create the [configuration file](../workflows/config.md) and state file for your cloud provider. If you are following the steps of this guide, there is no need to edit the file. + + + + + ```bash + constellation config generate aws + ``` + + + + + ```bash + constellation config generate azure + ``` + + + + + ```bash + constellation config generate gcp + ``` + + + + + ```bash + constellation config generate stackit + ``` + + + + +2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). + + + + + ```bash + constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config + ``` + + This command creates IAM configuration for the AWS zone `us-east-2a` using the prefix `constellTest` for all named resources being created. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. + + Depending on the attestation variant selected on config generation, different regions are available. + AMD SEV-SNP machines (requires the default attestation variant `awsSEVSNP`) are currently available in the following regions: + * `eu-west-1` + * `us-east-2` + + You can find a list of regions that support AMD SEV-SNP in [AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/snp-requirements.html). + + NitroTPM machines (requires the attestation variant `awsNitroTPM`) are available in all regions. + Constellation OS images are currently replicated to the following regions: + * `eu-central-1` + * `eu-west-1` + * `eu-west-3` + * `us-east-2` + * `ap-south-1` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+AWS+image+region:+xx-xxxx-x). + + You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). + + + + + ```bash + constellation iam create azure --subscriptionID 00000000-0000-0000-0000-000000000000 --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config + ``` + + This command creates IAM configuration on the Azure region `westus` creating a new resource group `constellTest` and a new service principal `spTest`. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. + + CVMs are available in several Azure regions. Constellation OS images are currently replicated to the following: + + * `germanywestcentral` + * `westus` + * `eastus` + * `northeurope` + * `westeurope` + * `southeastasia` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+Azure+image+region:+xx-xxxx-x). + + You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). + + + + + ```bash + constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config + ``` + + This command creates IAM configuration in the GCP project `yourproject-12345` on the GCP zone `europe-west2-a` creating a new service account `constell-test`. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. + + Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. + + + + + To use Constellation on STACKIT, the cluster will use the User Access Token (UAT) that's generated [during the install step](./install.md). + After creating the accounts, fill in the STACKIT details in `constellation-conf.yaml` under `provider.openstack`: + + * `stackitProjectID`: STACKIT project id (can be found after login on the [STACKIT portal](https://portal.stackit.cloud)) + + + + + :::tip + To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). + ::: + + + +3. Create the cluster. `constellation apply` uses options set in `constellation-conf.yaml`. + If you want to manually manage your cloud resources, for example by using [Terraform](../reference/terraform.md), follow the corresponding instructions in the [Create workflow](../workflows/create.md). + + :::tip + + On Azure, you may need to wait 15+ minutes at this point for role assignments to propagate. + + ::: + + ```bash + constellation apply -y + ``` + + This should look similar to the following: + + ```shell-session + $ constellation apply -y + Checking for infrastructure changes + The following Constellation cluster will be created: + 3 control-plane nodes of type n2d-standard-4 will be created. + 1 worker node of type n2d-standard-4 will be created. + Creating + Cloud infrastructure created successfully + Your Constellation master secret was successfully written to ./constellation-mastersecret.json + Connecting + Initializing cluster + Installing Kubernetes components + Your Constellation cluster was successfully initialized. + + Constellation cluster identifier g6iMP5wRU1b7mpOz2WEISlIYSfdAhB0oNaOg6XEwKFY= + Kubernetes configuration constellation-admin.conf + + You can now connect to your cluster by executing: + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + + The cluster's identifier will be different in your output. + Keep `constellation-mastersecret.json` somewhere safe. + This will allow you to [recover your cluster](../workflows/recovery.md) in case of a disaster. + + :::info + + Depending on your CSP and region, `constellation apply` may take 10+ minutes to complete. + + ::: + +4. Configure kubectl. + + ```bash + export KUBECONFIG="$PWD/constellation-admin.conf" + ``` + +## Deploy a sample application + +1. Deploy the [emojivoto app](https://github.com/BuoyantIO/emojivoto) + + ```bash + kubectl apply -k github.com/BuoyantIO/emojivoto/kustomize/deployment + ``` + +2. Expose the frontend service locally + + ```bash + kubectl wait --for=condition=available --timeout=60s -n emojivoto --all deployments + kubectl -n emojivoto port-forward svc/web-svc 8080:80 & + curl http://localhost:8080 + kill %1 + ``` + +## Terminate your cluster + +Use the CLI to terminate your cluster. If you manually used [Terraform](../reference/terraform.md) to manage your cloud resources, follow the corresponding instructions in the [Terminate workflow](../workflows/terminate.md). + +```bash +constellation terminate +``` + +This should give the following output: + +```shell-session +$ constellation terminate +You are about to terminate a Constellation cluster. +All of its associated resources will be DESTROYED. +This action is irreversible and ALL DATA WILL BE LOST. +Do you want to continue? [y/n]: +``` + +Confirm with `y` to terminate the cluster: + +```shell-session +Terminating ... +Your Constellation cluster was terminated successfully. +``` + +Optionally, you can also [delete your IAM resources](../workflows/config.md#deleting-an-iam-configuration). diff --git a/docs/versioned_docs/version-2.19/getting-started/install.md b/docs/versioned_docs/version-2.19/getting-started/install.md new file mode 100644 index 000000000..bc0a8c959 --- /dev/null +++ b/docs/versioned_docs/version-2.19/getting-started/install.md @@ -0,0 +1,439 @@ +# Installation and setup + +Constellation runs entirely in your cloud environment and can be controlled via a dedicated [command-line interface (CLI)](../reference/cli.md) or a [Terraform provider](../workflows/terraform-provider.md). + +## Prerequisites + +Make sure the following requirements are met: + +* Your machine is running Linux, macOS, or Windows +* You have admin rights on your machine +* [kubectl](https://kubernetes.io/docs/tasks/tools/) is installed +* Your CSP is Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), or STACKIT + +## Install the Constellation CLI + +:::tip + +If you prefer to use Terraform, you can alternatively use the [Terraform provider](../workflows/terraform-provider.md) to manage the cluster's lifecycle. + +::: + +The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). +Install it with the following commands: + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-linux-amd64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-linux-amd64 /usr/local/bin/constellation +``` + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-linux-arm64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-linux-arm64 /usr/local/bin/constellation +``` + + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-darwin-arm64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-darwin-arm64 /usr/local/bin/constellation +``` + + + + + +1. Download the CLI: + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/constellation-darwin-amd64 +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI to your PATH: + +```bash +sudo install constellation-darwin-amd64 /usr/local/bin/constellation +``` + + + + + +1. Download the CLI: + +```bash +Invoke-WebRequest -OutFile ./constellation.exe -Uri 'https://github.com/edgelesssys/constellation/releases/latest/download/constellation-windows-amd64.exe' +``` + +2. [Verify the signature](../workflows/verify-cli.md) (optional) + +3. Install the CLI under `C:\Program Files\Constellation\bin\constellation.exe` + +3. Add the CLI to your PATH: + + 1. Open `Advanced system settings` by searching for the App in the Windows search + 2. Go to the `Advanced` tab + 3. Click `Environment Variables…` + 4. Click variable called `Path` and click `Edit…` + 5. Click `New` + 6. Enter the path to the folder containing the binary you want on your PATH: `C:\Program Files\Constellation\bin` + + + + +:::tip +The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. +::: + +## Set up cloud credentials + +Constellation makes authenticated calls to the CSP API. Therefore, you need to set up Constellation with the credentials for your CSP. + +:::tip +If you don't have a cloud subscription, you can also set up a [local Constellation cluster using virtualization](../getting-started/first-steps-local.md) for testing. +::: + +### Required permissions + + + + +To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. + +To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:DescribeAccountAttributes", + "iam:AddRoleToInstanceProfile", + "iam:AttachRolePolicy", + "iam:CreateInstanceProfile", + "iam:CreatePolicy", + "iam:CreateRole", + "iam:DeleteInstanceProfile", + "iam:DeletePolicy", + "iam:DeletePolicyVersion", + "iam:DeleteRole", + "iam:DetachRolePolicy", + "iam:GetInstanceProfile", + "iam:GetPolicy", + "iam:GetPolicyVersion", + "iam:GetRole", + "iam:ListAttachedRolePolicies", + "iam:ListInstanceProfilesForRole", + "iam:ListPolicyVersions", + "iam:ListRolePolicies", + "iam:PassRole", + "iam:RemoveRoleFromInstanceProfile", + "sts:GetCallerIdentity" + ], + "Resource": "*" + } + ] +} +``` + +The built-in `AdministratorAccess` policy is a superset of these permissions. + +To [create a Constellation cluster](../workflows/create.md), see the permissions of [main.tf](https://github.com/edgelesssys/constellation/blob/main/terraform/infrastructure/iam/aws/main.tf). + +The built-in `PowerUserAccess` policy is a superset of these permissions. + +Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). + + + + +The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: + +* `Microsoft.Attestation` +* `Microsoft.Compute` +* `Microsoft.Insights` +* `Microsoft.ManagedIdentity` +* `Microsoft.Network` + +By default, Constellation tries to register these automatically if they haven't been registered before. + +To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: + +* `*/register/action` \[1] +* `Microsoft.Authorization/roleAssignments/*` +* `Microsoft.Authorization/roleDefinitions/*` +* `Microsoft.ManagedIdentity/userAssignedIdentities/*` +* `Microsoft.Resources/subscriptions/resourcegroups/*` + +The built-in `Owner` role is a superset of these permissions. + +To [create a Constellation cluster](../workflows/create.md), you need the following permissions: + +* `Microsoft.Attestation/attestationProviders/*` +* `Microsoft.Compute/virtualMachineScaleSets/*` +* `Microsoft.Insights/components/*` +* `Microsoft.ManagedIdentity/userAssignedIdentities/*` +* `Microsoft.Network/loadBalancers/*` +* `Microsoft.Network/loadBalancers/backendAddressPools/*` +* `Microsoft.Network/networkSecurityGroups/*` +* `Microsoft.Network/publicIPAddresses/*` +* `Microsoft.Network/virtualNetworks/*` +* `Microsoft.Network/virtualNetworks/subnets/*` +* `Microsoft.Network/natGateways/*` + +The built-in `Contributor` role is a superset of these permissions. + +Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-definitions) and [assigning roles](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments). + +1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. + + + + +Create a new project for Constellation or use an existing one. +Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. + +To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: + +* `iam.serviceAccountKeys.create` +* `iam.serviceAccountKeys.delete` +* `iam.serviceAccountKeys.get` +* `iam.serviceAccounts.create` +* `iam.serviceAccounts.delete` +* `iam.serviceAccounts.get` +* `resourcemanager.projects.getIamPolicy` +* `resourcemanager.projects.setIamPolicy` + +Together, the built-in roles `roles/editor` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. + +To [create a Constellation cluster](../workflows/create.md), you need the following permissions: + +* `compute.addresses.createInternal` +* `compute.addresses.deleteInternal` +* `compute.addresses.get` +* `compute.addresses.useInternal` +* `compute.backendServices.create` +* `compute.backendServices.delete` +* `compute.backendServices.get` +* `compute.backendServices.use` +* `compute.disks.create` +* `compute.firewalls.create` +* `compute.firewalls.delete` +* `compute.firewalls.get` +* `compute.firewalls.update` +* `compute.globalAddresses.create` +* `compute.globalAddresses.delete` +* `compute.globalAddresses.get` +* `compute.globalAddresses.use` +* `compute.globalForwardingRules.create` +* `compute.globalForwardingRules.delete` +* `compute.globalForwardingRules.get` +* `compute.globalForwardingRules.setLabels` +* `compute.globalOperations.get` +* `compute.healthChecks.create` +* `compute.healthChecks.delete` +* `compute.healthChecks.get` +* `compute.healthChecks.useReadOnly` +* `compute.instanceGroupManagers.create` +* `compute.instanceGroupManagers.delete` +* `compute.instanceGroupManagers.get` +* `compute.instanceGroupManagers.update` +* `compute.instanceGroups.create` +* `compute.instanceGroups.delete` +* `compute.instanceGroups.get` +* `compute.instanceGroups.update` +* `compute.instanceGroups.use` +* `compute.instances.create` +* `compute.instances.setLabels` +* `compute.instances.setMetadata` +* `compute.instances.setTags` +* `compute.instanceTemplates.create` +* `compute.instanceTemplates.delete` +* `compute.instanceTemplates.get` +* `compute.instanceTemplates.useReadOnly` +* `compute.networks.create` +* `compute.networks.delete` +* `compute.networks.get` +* `compute.networks.updatePolicy` +* `compute.routers.create` +* `compute.routers.delete` +* `compute.routers.get` +* `compute.routers.update` +* `compute.subnetworks.create` +* `compute.subnetworks.delete` +* `compute.subnetworks.get` +* `compute.subnetworks.use` +* `compute.targetTcpProxies.create` +* `compute.targetTcpProxies.delete` +* `compute.targetTcpProxies.get` +* `compute.targetTcpProxies.use` +* `iam.serviceAccounts.actAs` + +Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. + +Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). + + + + +Constellation on STACKIT requires a User Access Token (UAT) for the OpenStack API and a STACKIT service account. +The UAT already has all required permissions by default. +The STACKIT service account needs the `editor` role to create STACKIT LoadBalancers. +Look at the [STACKIT documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) on how to create the service account and assign the role. + + + + +### Authentication + +You need to authenticate with your CSP. The following lists the required steps for *testing* and *production* environments. + +:::note +The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. +::: + + + + +**Testing** + +You can use the [AWS CloudShell](https://console.aws.amazon.com/cloudshell/home). Make sure you are [authorized to use it](https://docs.aws.amazon.com/cloudshell/latest/userguide/sec-auth-with-identities.html). + +**Production** + +Use the latest version of the [AWS CLI](https://aws.amazon.com/cli/) on a trusted machine: + +```bash +aws configure +``` + +Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). + + + + +**Testing** + +Simply open the [Azure Cloud Shell](https://docs.microsoft.com/en-us/azure/cloud-shell/overview). + +**Production** + +Use the latest version of the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/) on a trusted machine: + +```bash +az login +``` + +Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). + + + + +**Testing** + +You can use the [Google Cloud Shell](https://cloud.google.com/shell). Make sure your [session is authorized](https://cloud.google.com/shell/docs/auth). For example, execute `gsutil` and accept the authorization prompt. + +**Production** + +Use one of the following options on a trusted machine: + +* Use the [`gcloud` CLI](https://cloud.google.com/sdk/gcloud) + + ```bash + gcloud auth application-default login + ``` + + This will ask you to log-in to your Google account and create your credentials. + The Constellation CLI will automatically load these credentials when needed. + +* Set up a service account and pass the credentials manually + + Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. + + + + +You need to authenticate with the infrastructure API (OpenStack) and create a service account (STACKIT API). + +1. [Follow the STACKIT documentation](https://docs.stackit.cloud/stackit/en/step-1-generating-of-user-access-token-11763726.html) for obtaining a User Access Token (UAT) to use the infrastructure API +2. Create a configuration file with the credentials from the User Access Token under: + * Linux: `~/.config/openstack/clouds.yaml` + * macOS: `/Users//Library/Application Support/openstack/clouds.yaml` or `/etc/openstack/clouds.yaml` + * Windows: `%AppData%\openstack\clouds.yaml` + + + ```yaml + clouds: + stackit: + auth: + auth_url: https://keystone.api.iaas.eu01.stackit.cloud/v3 + username: REPLACE_WITH_UAT_USERNAME + password: REPLACE_WITH_UAT_PASSWORD + project_id: REPLACE_WITH_STACKIT_PROJECT_ID + project_name: REPLACE_WITH_STACKIT_PROJECT_NAME + user_domain_name: portal_mvp + project_domain_name: portal_mvp + region_name: RegionOne + identity_api_version: 3 + ``` + +:::caution + +`project_id` refers to the ID of your STACKIT project. The STACKIT portal also shows the OpenStack ID that's associated with your project in some places. Make sure you insert the STACKIT project ID in the `clouds.yaml` file. It's of the format "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX". + +::: + +3. [Follow the STACKIT documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) for creating a service account and an access token +4. Assign the `editor` role to the service account by [following the documentation](https://docs.stackit.cloud/stackit/en/getting-started-in-service-accounts-134415831.html) +5. Create a configuration file under `~/.stackit/credentials.json` (`%USERPROFILE%\.stackit\credentials.json` on Windows) + + ```json + {"STACKIT_SERVICE_ACCOUNT_TOKEN":"REPLACE_WITH_TOKEN"} + ``` + + + + + +## Next steps + +You are now ready to [deploy your first confidential Kubernetes cluster and application](first-steps.md). diff --git a/docs/versioned_docs/version-2.19/getting-started/marketplaces.md b/docs/versioned_docs/version-2.19/getting-started/marketplaces.md new file mode 100644 index 000000000..a6763a42a --- /dev/null +++ b/docs/versioned_docs/version-2.19/getting-started/marketplaces.md @@ -0,0 +1,56 @@ +# Using Constellation via Cloud Marketplaces + +Constellation is available through the Marketplaces of AWS, Azure, GCP, and STACKIT. This allows you to create self-managed Constellation clusters that are billed on a pay-per-use basis (hourly, per vCPU) with your CSP account. You can still get direct support by Edgeless Systems. For more information, please [contact us](https://www.edgeless.systems/enterprise-support/). + +This document explains how to run Constellation with the dynamically billed cloud marketplace images. + + + + +To use Constellation's marketplace images, ensure that you are subscribed to the [marketplace offering](https://aws.amazon.com/marketplace/pp/prodview-2mbn65nv57oys) through the web portal. + +Then, enable the use of marketplace images in your Constellation `constellation-conf.yaml` [config file](../workflows/config.md): + +```bash +yq eval -i ".provider.aws.useMarketplaceImage = true" constellation-conf.yaml +``` + + + + +Constellation has a private marketplace plan. Please [contact us](https://www.edgeless.systems/enterprise-support/) to gain access. + +To use a marketplace image, you need to accept the marketplace image's terms once for your subscription with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/vm/image/terms?view=azure-cli-latest): + +```bash +az vm image terms accept --publisher edgelesssystems --offer constellation --plan constellation +``` + +Then, enable the use of marketplace images in your Constellation `constellation-conf.yaml` [config file](../workflows/config.md): + +```bash +yq eval -i ".provider.azure.useMarketplaceImage = true" constellation-conf.yaml +``` + + + + +To use a marketplace image, ensure that the account is entitled to use marketplace images by Edgeless Systems by accepting the terms through the [web portal](https://console.cloud.google.com/marketplace/vm/config/edgeless-systems-public/constellation). + +Then, enable the use of marketplace images in your Constellation `constellation-conf.yaml` [config file](../workflows/config.md): + +```bash +yq eval -i ".provider.gcp.useMarketplaceImage = true" constellation-conf.yaml +``` + + + + +On STACKIT, the selected Constellation image is always a marketplace image. You can find more information on the STACKIT portal. + + + + +Ensure that the cluster uses an official release image version (i.e., `.image=vX.Y.Z` in the `constellation-conf.yaml` file). + +From there, you can proceed with the [cluster creation](../workflows/create.md) as usual. diff --git a/docs/versioned_docs/version-2.19/intro.md b/docs/versioned_docs/version-2.19/intro.md new file mode 100644 index 000000000..0bfe86da9 --- /dev/null +++ b/docs/versioned_docs/version-2.19/intro.md @@ -0,0 +1,34 @@ +--- +slug: / +id: intro +--- +# Introduction + +Welcome to the documentation of Constellation! Constellation is a Kubernetes engine that aims to provide the best possible data security. + +![Constellation concept](/img/concept.svg) + + Constellation shields your entire Kubernetes cluster from the underlying cloud infrastructure. Everything inside is always encrypted, including at runtime in memory. For this, Constellation leverages a technology called *confidential computing* and more specifically Confidential VMs. + +:::tip +See the 📄[whitepaper](https://content.edgeless.systems/hubfs/Confidential%20Computing%20Whitepaper.pdf) for more information on confidential computing. +::: + +## Goals + +From a security perspective, Constellation is designed to keep all data always encrypted and to prevent any access from the underlying (cloud) infrastructure. This includes access from datacenter employees, privileged cloud admins, and attackers coming through the infrastructure. Such attackers could be malicious co-tenants escalating their privileges or hackers who managed to compromise a cloud server. + +From a DevOps perspective, Constellation is designed to work just like what you would expect from a modern Kubernetes engine. + +## Use cases + +Constellation provides unique security [features](overview/confidential-kubernetes.md) and [benefits](overview/security-benefits.md). The core use cases are: + +* Increasing the overall security of your clusters +* Increasing the trustworthiness of your SaaS offerings +* Moving sensitive workloads from on-prem to the cloud +* Meeting regulatory requirements + +## Next steps + +You can learn more about the concept of Confidential Kubernetes, features, security benefits, and performance of Constellation in the *Basics* section. To jump right into the action head to *Getting started*. diff --git a/docs/versioned_docs/version-2.19/overview/clouds.md b/docs/versioned_docs/version-2.19/overview/clouds.md new file mode 100644 index 000000000..b2695d28e --- /dev/null +++ b/docs/versioned_docs/version-2.19/overview/clouds.md @@ -0,0 +1,66 @@ +# Feature status of clouds + +What works on which cloud? Currently, Confidential VMs (CVMs) are available in varying quality on the different clouds and software stacks. + +For Constellation, the ideal environment provides the following: + +1. Ability to run arbitrary software and images inside CVMs +2. CVMs based on AMD SEV-SNP (available in EPYC CPUs since the Milan generation) or Intel TDX (available in Xeon CPUs since the Sapphire Rapids generation) +3. Ability for CVM guests to obtain raw hardware attestation statements +4. Reviewable, open-source firmware inside CVMs +5. Capability of the firmware to attest the integrity of the code it passes control to, e.g., with an embedded virtual TPM (vTPM) + +(1) is a functional must-have. (2)--(5) are required for remote attestation that fully keeps the infrastructure/cloud out. Constellation can work without them or with approximations, but won't protect against certain privileged attackers anymore. + +The following table summarizes the state of features for different infrastructures. + +| **Feature** | **AWS** | **Azure** | **GCP** | **STACKIT** | **OpenStack (Yoga)** | +|-----------------------------------|---------|-----------|---------|--------------|----------------------| +| **1. Custom images** | Yes | Yes | Yes | Yes | Yes | +| **2. SEV-SNP or TDX** | Yes | Yes | Yes | No | Depends on kernel/HV | +| **3. Raw guest attestation** | Yes | Yes | Yes | No | Depends on kernel/HV | +| **4. Reviewable firmware** | Yes | No* | No | No | Depends on kernel/HV | +| **5. Confidential measured boot** | No | Yes | No | No | Depends on kernel/HV | + +## Amazon Web Services (AWS) + +Amazon EC2 [supports AMD SEV-SNP](https://aws.amazon.com/de/about-aws/whats-new/2023/04/amazon-ec2-amd-sev-snp/). +Regarding (3), AWS provides direct access to attestation statements. +However, regarding (5), attestation is partially based on the [NitroTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) for [measured boot](../architecture/attestation.md#measured-boot), which is a vTPM managed by the Nitro hypervisor. +Hence, the hypervisor is currently part of Constellation's TCB. +Regarding (4), the [firmware is open source](https://github.com/aws/uefi) and can be reproducibly built. + +## Microsoft Azure + +With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. +Regarding (3), Azure provides direct access to attestation statements. +The firmware runs in an isolated domain inside the CVM and exposes a vTPM (5), but it's closed source (4). +On SEV-SNP, Azure uses VM Privilege Level (VMPL) isolation for the separation of firmware and the rest of the VM; on TDX, they use TD partitioning. +This firmware is signed by Azure. +The signature is reflected in the attestation statements of CVMs. +Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). + +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. + +## Google Cloud Platform (GCP) + +The [CVMs Generally Available in GCP](https://cloud.google.com/confidential-computing/confidential-vm/docs/confidential-vm-overview#technologies) are based on AMD SEV-ES or SEV-SNP. +Regarding (3), with their SEV-SNP offering Google provides direct access to attestation statements. +However, regarding (5), attestation is partially based on the [Shielded VM vTPM](https://cloud.google.com/compute/shielded-vm/docs/shielded-vm#vtpm) for [measured boot](../architecture/attestation.md#measured-boot), which is a vTPM managed by Google's hypervisor. +Hence, the hypervisor is currently part of Constellation's TCB. +Regarding (4), the CVMs still include closed-source firmware. + +[TDX on Google](https://cloud.google.com/blog/products/identity-security/confidential-vms-on-intel-cpus-your-datas-new-intelligent-defense) is in public preview. +With it, Constellation would have a similar TCB and attestation flow as with the current SEV-SNP offering. + +## STACKIT + +[STACKIT Compute Engine](https://www.stackit.de/en/product/stackit-compute-engine/) supports AMD SEV-ES. A vTPM is used for measured boot, which is a vTPM managed by STACKIT's hypervisor. Hence, the hypervisor is currently part of Constellation's TCB. + +## OpenStack + +OpenStack is an open-source cloud and infrastructure management software. It's used by many smaller CSPs and datacenters. In the latest *Yoga* version, OpenStack has basic support for CVMs. However, much depends on the employed kernel and hypervisor. Features (2)--(4) are likely to be a *Yes* with Linux kernel version 6.2. Thus, going forward, OpenStack on corresponding AMD or Intel hardware will be a viable underpinning for Constellation. + +## Conclusion + +The different clouds and software like the Linux kernel and OpenStack are in the process of building out their support for state-of-the-art CVMs. Azure has already most features in place. For Constellation, the status quo means that the TCB has different shapes on different infrastructures. With broad SEV-SNP support coming to the Linux kernel, we soon expect a normalization of features across infrastructures. diff --git a/docs/versioned_docs/version-2.19/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.19/overview/confidential-kubernetes.md new file mode 100644 index 000000000..bff8c3322 --- /dev/null +++ b/docs/versioned_docs/version-2.19/overview/confidential-kubernetes.md @@ -0,0 +1,42 @@ +# Confidential Kubernetes + +We use the term *Confidential Kubernetes* to refer to the concept of using confidential-computing technology to shield entire Kubernetes clusters from the infrastructure. The three defining properties of this concept are: + +1. **Workload shielding**: the confidentiality and integrity of all workload-related data and code are enforced. +2. **Control plane shielding**: the confidentiality and integrity of the cluster's control plane, state, and workload configuration are enforced. +3. **Attestation and verifiability**: the two properties above can be verified remotely based on hardware-rooted cryptographic certificates. + +Each of the above properties is equally important. Only with all three in conjunction, an entire cluster can be shielded without gaps. + +## Constellation security features + +Constellation implements the Confidential Kubernetes concept with the following security features. + +* **Runtime encryption**: Constellation runs all Kubernetes nodes inside Confidential VMs (CVMs). This gives runtime encryption for the entire cluster. +* **Network and storage encryption**: Constellation augments this with transparent encryption of the [network](../architecture/networking.md), [persistent storage](../architecture/encrypted-storage.md), and other managed storage like [AWS S3](../architecture/encrypted-storage.md#encrypted-s3-object-storage). Thus, workloads and control plane are truly end-to-end encrypted: at rest, in transit, and at runtime. +* **Transparent key management**: Constellation manages the corresponding [cryptographic keys](../architecture/keys.md) inside CVMs. +* **Node attestation and verification**: Constellation verifies the integrity of each new CVM-based node using [remote attestation](../architecture/attestation.md). Only "good" nodes receive the cryptographic keys required to access the network and storage of a cluster. +* **Confidential computing-optimized images**: A node is "good" if it's running a signed Constellation [node image](../architecture/images.md) inside a CVM and is in the expected state. (Node images are hardware-measured during boot. The measurements are reflected in the attestation statements that are produced by nodes and verified by Constellation.) +* **"Whole cluster" attestation**: Towards the DevOps engineer, Constellation provides a single hardware-rooted certificate from which all of the above can be verified. + +With the above, Constellation wraps an entire cluster into one coherent and verifiable *confidential context*. The concept is depicted in the following. + +![Confidential Kubernetes](../_media/concept-constellation.svg) + +## Comparison: Managed Kubernetes with CVMs + +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. + +![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) + +The following table highlights the key differences in terms of features. + +| | Managed Kubernetes with CVMs | Confidential Kubernetes (Constellation✨) | +|-------------------------------------|------------------------------|--------------------------------------------| +| Runtime encryption | Partial (data plane only)| **Yes** | +| Node image verification | No | **Yes** | +| Full cluster attestation | No | **Yes** | +| Transparent network encryption | No | **Yes** | +| Transparent storage encryption | No | **Yes** | +| Confidential key management | No | **Yes** | +| Cloud agnostic / multi-cloud | No | **Yes** | diff --git a/docs/versioned_docs/version-2.19/overview/license.md b/docs/versioned_docs/version-2.19/overview/license.md new file mode 100644 index 000000000..34122c025 --- /dev/null +++ b/docs/versioned_docs/version-2.19/overview/license.md @@ -0,0 +1,33 @@ +# License + +## Source code + +Constellation's source code is available on [GitHub](https://github.com/edgelesssys/constellation) under the [GNU Affero General Public License v3.0](https://github.com/edgelesssys/constellation/blob/main/LICENSE). + +## Binaries + +Edgeless Systems provides ready-to-use and [signed](../architecture/attestation.md#chain-of-trust) binaries of Constellation. This includes the CLI and the [node images](../architecture/images.md). + +These binaries may be used free of charge within the bounds of Constellation's [**Community License**](#community-license). An [**Enterprise License**](#enterprise-license) can be purchased from Edgeless Systems. + +The Constellation CLI displays relevant license information when you initialize your cluster. You are responsible for staying within the bounds of your respective license. Constellation doesn't enforce any limits so as not to endanger your cluster's availability. + +## Terraform provider + +Edgeless Systems provides a [Terraform provider](https://github.com/edgelesssys/terraform-provider-constellation/releases), which may be used free of charge within the bounds of Constellation's [**Community License**](#community-license). An [**Enterprise License**](#enterprise-license) can be purchased from Edgeless Systems. + +You are responsible for staying within the bounds of your respective license. Constellation doesn't enforce any limits so as not to endanger your cluster's availability. + +## Community License + +You are free to use the Constellation binaries provided by Edgeless Systems to create services for internal consumption, evaluation purposes, or non-commercial use. You must not use the Constellation binaries to provide commercial hosted services to third parties. Edgeless Systems gives no warranties and offers no support. + +## Enterprise License + +Enterprise Licenses don't have the above limitations and come with support and additional features. Find out more at the [product website](https://www.edgeless.systems/products/constellation/). + +Once you have received your Enterprise License file, place it in your [Constellation workspace](../architecture/orchestration.md#workspaces) in a file named `constellation.license`. + +## CSP Marketplaces + +Constellation is available through the Marketplaces of AWS, Azure, GCP, and STACKIT. This allows you to create self-managed Constellation clusters that are billed on a pay-per-use basis (hourly, per vCPU) with your CSP account. You can still get direct support by Edgeless Systems. For more information, please [contact us](https://www.edgeless.systems/enterprise-support/). diff --git a/docs/versioned_docs/version-2.19/overview/performance/application.md b/docs/versioned_docs/version-2.19/overview/performance/application.md new file mode 100644 index 000000000..c67d59644 --- /dev/null +++ b/docs/versioned_docs/version-2.19/overview/performance/application.md @@ -0,0 +1,102 @@ +# Application benchmarks + +## HashiCorp Vault + +[HashiCorp Vault](https://www.vaultproject.io/) is a distributed secrets management software that can be deployed to Kubernetes. +HashiCorp maintains a benchmarking tool for vault, [vault-benchmark](https://github.com/hashicorp/vault-benchmark/). +Vault-benchmark generates load on a Vault deployment and measures response times. + +This article describes the results from running vault-benchmark on Constellation, AKS, and GKE. +You can find the setup for producing the data discussed in this article in the [vault-benchmarks](https://github.com/edgelesssys/vault-benchmarks) repository. + +The Vault API used during benchmarking is the [transits secret engine](https://developer.hashicorp.com/vault/docs/secrets/transit). +This allows services to send data to Vault for encryption, decryption, signing, and verification. + +## Results + +On each run, vault-benchmark sends requests and measures the latencies. +The measured latencies are aggregated through various statistical features. +After running the benchmark n times, the arithmetic mean over a subset of the reported statistics is calculated. +The selected features are arithmetic mean, 99th percentile, minimum, and maximum. + +Arithmetic mean gives a general sense of the latency on each target. +The 99th percentile shows performance in (most likely) erroneous states. +Minimum and maximum mark the range within which latency varies each run. + +The benchmark was configured with 1300 workers and 10 seconds per run. +Those numbers were chosen empirically. +The latency was stabilizing at 10 seconds runtime, not changing with further increase. +Increasing the number of workers beyond 1300 leads to request failures, marking the limit Vault was able to handle in this setup. +All results are based on 100 runs. + +The following data was generated while running five replicas, one primary, and four standby nodes. +All numbers are in seconds if not indicated otherwise. +``` +========== Results AKS ========== +Mean: mean: 1.632200, variance: 0.002057 +P99: mean: 5.480679, variance: 2.263700 +Max: mean: 6.651001, variance: 2.808401 +Min: mean: 0.011415, variance: 0.000133 +========== Results GKE ========== +Mean: mean: 1.656435, variance: 0.003615 +P99: mean: 6.030807, variance: 3.955051 +Max: mean: 7.164843, variance: 3.300004 +Min: mean: 0.010233, variance: 0.000111 +========== Results C11n ========== +Mean: mean: 1.651549, variance: 0.001610 +P99: mean: 5.780422, variance: 3.016106 +Max: mean: 6.942997, variance: 3.075796 +Min: mean: 0.013774, variance: 0.000228 +========== AKS vs C11n ========== +Mean: +1.171577 % (AKS is faster) +P99: +5.185495 % (AKS is faster) +Max: +4.205618 % (AKS is faster) +Min: +17.128781 % (AKS is faster) +========== GKE vs C11n ========== +Mean: -0.295851 % (GKE is slower) +P99: -4.331603 % (GKE is slower) +Max: -3.195248 % (GKE is slower) +Min: +25.710886 % (GKE is faster) +``` + +**Interpretation**: Latencies are all within ~5% of each other. +AKS performs slightly better than GKE and Constellation (C11n) in all cases except minimum latency. +Minimum latency is the lowest for GKE. +Compared to GKE, Constellation had slightly lower peak latencies (99th percentile and maximum), indicating that Constellation could have handled slightly more concurrent accesses than GKE. +Overall, performance is at comparable levels across all three distributions. +Based on these numbers, you can use a similarly sized Constellation cluster to run your existing Vault deployment. + +### Visualization + +The following plots visualize the data presented above as [box plots](https://en.wikipedia.org/wiki/Box_plot). +The whiskers denote the minimum and maximum. +The box stretches from the 25th to the 75th percentile, with the dividing bar marking the 50th percentile. +The circles outside the whiskers denote outliers. + +
+Mean Latency + +![Mean Latency](../../_media/benchmark_vault/5replicas/mean_latency.png) + +
+ +
+99th Percentile Latency + +![99th Percentile Latency](../../_media/benchmark_vault/5replicas/p99_latency.png) + +
+ +
+Maximum Latency + +![Maximum Latency](../../_media/benchmark_vault/5replicas/max_latency.png) + +
+ +
+Minimum Latency + +![Minimum Latency](../../_media/benchmark_vault/5replicas/min_latency.png) + +
diff --git a/docs/versioned_docs/version-2.19/overview/performance/compute.md b/docs/versioned_docs/version-2.19/overview/performance/compute.md new file mode 100644 index 000000000..88dd4b1b2 --- /dev/null +++ b/docs/versioned_docs/version-2.19/overview/performance/compute.md @@ -0,0 +1,11 @@ +# Impact of runtime encryption on compute performance + +All nodes in a Constellation cluster are executed inside Confidential VMs (CVMs). Consequently, the performance of Constellation is inherently linked to the performance of these CVMs. + +## AMD and Azure benchmarking + +AMD and Azure have collectively released a [performance benchmark](https://community.amd.com/t5/business/microsoft-azure-confidential-computing-powered-by-3rd-gen-epyc/ba-p/497796) for CVMs that utilize 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. This benchmark, which included a variety of mostly compute-intensive tests such as SPEC CPU 2017 and CoreMark, demonstrated that CVMs experience only minor performance degradation (ranging from 2% to 8%) when compared to standard VMs. Such results are indicative of the performance that can be expected from compute-intensive workloads running with Constellation on Azure. + +## AMD and Google benchmarking + +Similarly, AMD and Google have jointly released a [performance benchmark](https://www.amd.com/system/files/documents/3rd-gen-epyc-gcp-c2d-conf-compute-perf-brief.pdf) for CVMs employing 3rd Gen AMD EPYC processors (Milan) with SEV-SNP. With high-performance computing workloads such as WRF, NAMD, Ansys CFS, and Ansys LS_DYNA, they observed analogous findings, with only minor performance degradation (between 2% and 4%) compared to standard VMs. These outcomes are reflective of the performance that can be expected for compute-intensive workloads running with Constellation on GCP. diff --git a/docs/versioned_docs/version-2.19/overview/performance/io.md b/docs/versioned_docs/version-2.19/overview/performance/io.md new file mode 100644 index 000000000..3ae796f8a --- /dev/null +++ b/docs/versioned_docs/version-2.19/overview/performance/io.md @@ -0,0 +1,204 @@ +# I/O performance benchmarks + +To assess the overall performance of Constellation, this benchmark evaluates Constellation v2.6.0 in terms of storage I/O using [`fio`](https://fio.readthedocs.io/en/latest/fio_doc.html) and network performance using the [Kubernetes Network Benchmark](https://github.com/InfraBuilder/k8s-bench-suite#knb--kubernetes-network-be). + +This benchmark tested Constellation on Azure and GCP and compared the results against the managed Kubernetes offerings AKS and GKE. + +## Configurations + +### Constellation + +The benchmark was conducted with Constellation v2.6.0, Kubernetes v1.25.7, and Cilium v1.12. +It ran on the following infrastructure configurations. + +Constellation on Azure: + +- Nodes: 3 (1 Control-plane, 2 Worker) +- Machines: `DC4as_v5`: 3rd Generation AMD EPYC 7763v (Milan) processor with 4 Cores, 16 GiB memory +- CVM: `true` +- Region: `West US` +- Zone: `2` + +Constellation on GCP: + +- Nodes: 3 (1 Control-plane, 2 Worker) +- Machines: `n2d-standard-4`: 2nd Generation AMD EPYC (Rome) processor with 4 Cores, 16 GiB of memory +- CVM: `true` +- Zone: `europe-west3-b` + +### AKS + +On AKS, the benchmark used Kubernetes `v1.24.9` and nodes with version `AKSUbuntu-1804gen2containerd-2023.02.15`. +AKS ran with the [`kubenet`](https://learn.microsoft.com/en-us/azure/aks/concepts-network#kubenet-basic-networking) CNI and the [default CSI driver](https://learn.microsoft.com/en-us/azure/aks/azure-disk-csi) for Azure Disk. + +The following infrastructure configurations was used: + +- Nodes: 2 (2 Worker) +- Machines: `D4as_v5`: 3rd Generation AMD EPYC 7763v (Milan) processor with 4 Cores, 16 GiB memory +- CVM: `false` +- Region: `West US` +- Zone: `2` + +### GKE + +On GKE, the benchmark used Kubernetes `v1.24.9` and nodes with version `1.24.9-gke.3200`. +GKE ran with the [`kubenet`](https://cloud.google.com/kubernetes-engine/docs/concepts/network-overview) CNI and the [default CSI driver](https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/gce-pd-csi-driver) for Compute Engine persistent disk. + +The following infrastructure configurations was used: + +- Nodes: 2 (2 Worker) +- Machines: `n2d-standard-4` 2nd Generation AMD EPYC (Rome) processor with 4 Cores, 16 GiB of memory +- CVM: `false` +- Zone: `europe-west3-b` + +## Results + +### Network + +This section gives a thorough analysis of the network performance of Constellation, specifically focusing on measuring TCP and UDP bandwidth. +The benchmark measured the bandwidth of pod-to-pod and pod-to-service connections between two different nodes using [`iperf`](https://iperf.fr/). + +GKE and Constellation on GCP had a maximum network bandwidth of [10 Gbps](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines). +AKS with `Standard_D4as_v5` machines a maximum network bandwidth of [12.5 Gbps](https://learn.microsoft.com/en-us/azure/virtual-machines/dasv5-dadsv5-series#dasv5-series). +The Confidential VM equivalent `Standard_DC4as_v5` currently has a network bandwidth of [1.25 Gbps](https://learn.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series#dcasv5-series-products). +Therefore, to make the test comparable, both AKS and Constellation on Azure were running with `Standard_DC4as_v5` machines and 1.25 Gbps bandwidth. + +Constellation on Azure and AKS used an MTU of 1500. +Constellation on GCP used an MTU of 8896. GKE used an MTU of 1450. + +The difference in network bandwidth can largely be attributed to two factors. + +- Constellation's [network encryption](../../architecture/networking.md) via Cilium and WireGuard, which protects data in-transit. +- [AMD SEV using SWIOTLB bounce buffers](https://lore.kernel.org/all/20200204193500.GA15564@ashkalra_ubuntu_server/T/) for all DMA including network I/O. + +#### Pod-to-Pod + +In this scenario, the client Pod connects directly to the server pod via its IP address. + +```mermaid +flowchart LR + subgraph Node A + Client[Client] + end + subgraph Node B + Server[Server] + end + Client ==>|traffic| Server +``` + +The results for "Pod-to-Pod" on Azure are as follows: + +![Network Pod2Pod Azure benchmark graph](../../_media/benchmark_net_p2p_azure.png) + +The results for "Pod-to-Pod" on GCP are as follows: + +![Network Pod2Pod GCP benchmark graph](../../_media/benchmark_net_p2p_gcp.png) + +#### Pod-to-Service + +In this scenario, the client Pod connects to the server Pod via a ClusterIP service. This is more relevant to real-world use cases. + +```mermaid +flowchart LR + subgraph Node A + Client[Client] ==>|traffic| Service[Service] + end + subgraph Node B + Server[Server] + end + Service ==>|traffic| Server +``` + +The results for "Pod-to-Pod" on Azure are as follows: + +![Network Pod2SVC Azure benchmark graph](../../_media/benchmark_net_p2svc_azure.png) + +The results for "Pod-to-Pod" on GCP are as follows: + +![Network Pod2SVC GCP benchmark graph](../../_media/benchmark_net_p2svc_gcp.png) + +In our recent comparison of Constellation on GCP with GKE, Constellation has 58% less TCP bandwidth. However, UDP bandwidth was slightly better with Constellation, thanks to its higher MTU. + +Similarly, when comparing Constellation on Azure with AKS using CVMs, Constellation achieved approximately 10% less TCP and 40% less UDP bandwidth. + +### Storage I/O + +Azure and GCP offer persistent storage for their Kubernetes services AKS and GKE via the Container Storage Interface (CSI). CSI storage in Kubernetes is available via `PersistentVolumes` (PV) and consumed via `PersistentVolumeClaims` (PVC). +Upon requesting persistent storage through a PVC, GKE and AKS will provision a PV as defined by a default [storage class](https://kubernetes.io/docs/concepts/storage/storage-classes/). +Constellation provides persistent storage on Azure and GCP [that's encrypted on the CSI layer](../../architecture/encrypted-storage.md). +Similarly, upon a PVC request, Constellation will provision a PV via a default storage class. + +For Constellation on Azure and AKS, the benchmark ran with Azure Disk storage [Standard SSD](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#standard-ssds) of 400 GiB size. +The [DC4as machine type](https://learn.microsoft.com/en-us/azure/virtual-machines/dasv5-dadsv5-series#dasv5-series) with four cores provides the following maximum performance: + +- 6400 (20000 burst) IOPS +- 144 MB/s (600 MB/s burst) throughput + +However, the performance is bound by the capabilities of the [512 GiB Standard SSD size](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#standard-ssds) (the size class of 400 GiB volumes): + +- 500 (600 burst) IOPS +- 60 MB/s (150 MB/s burst) throughput + +For Constellation on GCP and GKE, the benchmark ran with Compute Engine Persistent Disk Storage [pd-balanced](https://cloud.google.com/compute/docs/disks) of 400 GiB size. +The N2D machine type with four cores and pd-balanced provides the following [maximum performance](https://cloud.google.com/compute/docs/disks/performance#n2d_vms): + +- 3,000 read IOPS +- 15,000 write IOPS +- 240 MB/s read throughput +- 240 MB/s write throughput + +However, the performance is bound by the capabilities of a [`Zonal balanced PD`](https://cloud.google.com/compute/docs/disks/performance#zonal-persistent-disks) with 400 GiB size: + +- 2400 read IOPS +- 2400 write IOPS +- 112 MB/s read throughput +- 112 MB/s write throughput + +The [`fio`](https://fio.readthedocs.io/en/latest/fio_doc.html) benchmark consists of several tests. +The benchmark used [`Kubestr`](https://github.com/kastenhq/kubestr) to run `fio` in Kubernetes. +The default test performs randomized access patterns that accurately depict worst-case I/O scenarios for most applications. + +The following `fio` settings were used: + +- No Cloud caching +- No OS caching +- Single CPU +- 60 seconds runtime +- 10 seconds ramp-up time +- 10 GiB file +- IOPS: 4 KB blocks and 128 iodepth +- Bandwidth: 1024 KB blocks and 128 iodepth + +For more details, see the [`fio` test configuration](https://github.com/edgelesssys/constellation/blob/main/.github/actions/e2e_benchmark/fio.ini). + +The results for IOPS on Azure are as follows: + +![I/O IOPS Azure benchmark graph](../../_media/benchmark_fio_azure_iops.png) + +The results for IOPS on GCP are as follows: + +![I/O IOPS GCP benchmark graph](../../_media/benchmark_fio_gcp_iops.png) + +The results for bandwidth on Azure are as follows: + +![I/O bandwidth Azure benchmark graph](../../_media/benchmark_fio_azure_bw.png) + +The results for bandwidth on GCP are as follows: + +![I/O bandwidth GCP benchmark graph](../../_media/benchmark_fio_gcp_bw.png) + +On GCP, the results exceed the maximum performance guarantees of the chosen disk type. There are two possible explanations for this. The first is that there may be cloud caching in place that isn't configurable. Alternatively, the underlying provisioned disk size may be larger than what was requested, resulting in higher performance boundaries. + +When comparing Constellation on GCP with GKE, Constellation has similar bandwidth but about 10% less IOPS performance. On Azure, Constellation has similar IOPS performance compared to AKS, where both likely hit the maximum storage performance. However, Constellation has approximately 15% less read and write bandwidth. + +## Conclusion + +Despite the added [security benefits](../security-benefits.md) that Constellation provides, it only incurs a slight performance overhead when compared to managed Kubernetes offerings such as AKS and GKE. In most compute benchmarks, Constellation is on par with it's alternatives. +While it may be slightly slower in certain I/O scenarios due to network and storage encryption, there is ongoing work to reduce this overhead to single digits. + +For instance, storage encryption only adds between 10% to 15% overhead in terms of bandwidth and IOPS. +Meanwhile, the biggest performance impact that Constellation currently faces is network encryption, which can incur up to 58% overhead on a 10 Gbps network. +However, the Cilium team has conducted [benchmarks with Cilium using WireGuard encryption](https://docs.cilium.io/en/latest/operations/performance/benchmark/#encryption-wireguard-ipsec) on a 100 Gbps network that yielded over 15 Gbps. +We're confident that Constellation will provide a similar level of performance with an upcoming release. + +Overall, Constellation strikes a great balance between security and performance, and we're continuously working to improve its performance capabilities while maintaining its high level of security. diff --git a/docs/versioned_docs/version-2.19/overview/performance/performance.md b/docs/versioned_docs/version-2.19/overview/performance/performance.md new file mode 100644 index 000000000..59bf86602 --- /dev/null +++ b/docs/versioned_docs/version-2.19/overview/performance/performance.md @@ -0,0 +1,17 @@ +# Performance analysis of Constellation + +This section provides a comprehensive examination of the performance characteristics of Constellation. + +## Runtime encryption + +Runtime encryption affects compute performance. [Benchmarks by Azure and Google](compute.md) show that the performance degradation of Confidential VMs (CVMs) is small, ranging from 2% to 8% for compute-intensive workloads. + +## I/O performance benchmarks + +We evaluated the [I/O performance](io.md) of Constellation, utilizing a collection of synthetic benchmarks targeting networking and storage. +We further compared this performance to native managed Kubernetes offerings from various cloud providers, to better understand how Constellation stands in relation to standard practices. + +## Application benchmarking + +To gauge Constellation's applicability to well-known applications, we performed a [benchmark of HashiCorp Vault](application.md) running on Constellation. +The results were then compared to deployments on the managed Kubernetes offerings from different cloud providers, providing a tangible perspective on Constellation's performance in actual deployment scenarios. diff --git a/docs/versioned_docs/version-2.19/overview/product.md b/docs/versioned_docs/version-2.19/overview/product.md new file mode 100644 index 000000000..4b5d90706 --- /dev/null +++ b/docs/versioned_docs/version-2.19/overview/product.md @@ -0,0 +1,12 @@ +# Product features + +Constellation is a Kubernetes engine that aims to provide the best possible data security in combination with enterprise-grade scalability and reliability features---and a smooth user experience. + +From a security perspective, Constellation implements the [Confidential Kubernetes](confidential-kubernetes.md) concept and corresponding security features, which shield your entire cluster from the underlying infrastructure. + +From an operational perspective, Constellation provides the following key features: + +* **Native support for different clouds**: Constellation works on Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), and STACKIT. Support for OpenStack-based environments is coming with a future release. Constellation securely interfaces with the cloud infrastructure to provide [cluster autoscaling](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler), [dynamic persistent volumes](https://kubernetes.io/docs/concepts/storage/dynamic-provisioning/), and [service load balancing](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer). +* **High availability**: Constellation uses a [multi-master architecture](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/high-availability/) with a [stacked etcd topology](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/ha-topology/#stacked-etcd-topology) to ensure high availability. +* **Integrated Day-2 operations**: Constellation lets you securely [upgrade](../workflows/upgrade.md) your cluster to a new release. It also lets you securely [recover](../workflows/recovery.md) a failed cluster. Both with a single command. +* **Support for Terraform**: Constellation includes a [Terraform provider](../workflows/terraform-provider.md) that lets you manage the full lifecycle of your cluster via Terraform. diff --git a/docs/versioned_docs/version-2.19/overview/security-benefits.md b/docs/versioned_docs/version-2.19/overview/security-benefits.md new file mode 100644 index 000000000..51a8b64f5 --- /dev/null +++ b/docs/versioned_docs/version-2.19/overview/security-benefits.md @@ -0,0 +1,22 @@ +# Security benefits and threat model + +Constellation implements the [Confidential Kubernetes](confidential-kubernetes.md) concept and shields entire Kubernetes deployments from the infrastructure. More concretely, Constellation decreases the size of the trusted computing base (TCB) of a Kubernetes deployment. The TCB is the totality of elements in a computing environment that must be trusted not to be compromised. A smaller TCB results in a smaller attack surface. The following diagram shows how Constellation removes the *cloud & datacenter infrastructure* and the *physical hosts*, including the hypervisor, the host OS, and other components, from the TCB (red). Inside the confidential context (green), Kubernetes remains part of the TCB, but its integrity is attested and can be [verified](../workflows/verify-cluster.md). + +![TCB comparison](../_media/tcb.svg) + +Given this background, the following describes the concrete threat classes that Constellation addresses. + +## Insider access + +Employees and third-party contractors of cloud service providers (CSPs) have access to different layers of the cloud infrastructure. +This opens up a large attack surface where workloads and data can be read, copied, or manipulated. With Constellation, Kubernetes deployments are shielded from the infrastructure and thus such accesses are prevented. + +## Infrastructure-based attacks + +Malicious cloud users ("hackers") may break out of their tenancy and access other tenants' data. Advanced attackers may even be able to establish a permanent foothold within the infrastructure and access data over a longer period. Analogously to the *insider access* scenario, Constellation also prevents access to a deployment's data in this scenario. + +## Supply chain attacks + +Supply chain security is receiving lots of attention recently due to an [increasing number of recorded attacks](https://www.enisa.europa.eu/news/enisa-news/understanding-the-increase-in-supply-chain-security-attacks). For instance, a malicious actor could attempt to tamper Constellation node images (including Kubernetes and other software) before they're loaded in the confidential VMs of a cluster. Constellation uses [remote attestation](../architecture/attestation.md) in conjunction with public [transparency logs](../workflows/verify-cli.md) to prevent this. + +In the future, Constellation will extend this feature to customer workloads. This will enable cluster owners to create auditable policies that precisely define which containers can run in a given deployment. diff --git a/docs/versioned_docs/version-2.19/reference/cli.md b/docs/versioned_docs/version-2.19/reference/cli.md new file mode 100644 index 000000000..99acef520 --- /dev/null +++ b/docs/versioned_docs/version-2.19/reference/cli.md @@ -0,0 +1,844 @@ +# CLI reference + + + +Use the Constellation CLI to create and manage your clusters. + +Usage: + +``` +constellation [command] +``` +Commands: + +* [config](#constellation-config): Work with the Constellation configuration file + * [generate](#constellation-config-generate): Generate a default configuration and state file + * [fetch-measurements](#constellation-config-fetch-measurements): Fetch measurements for configured cloud provider and image + * [instance-types](#constellation-config-instance-types): Print the supported instance types for all cloud providers + * [kubernetes-versions](#constellation-config-kubernetes-versions): Print the Kubernetes versions supported by this CLI + * [migrate](#constellation-config-migrate): Migrate a configuration file to a new version +* [create](#constellation-create): Create instances on a cloud platform for your Constellation cluster +* [apply](#constellation-apply): Apply a configuration to a Constellation cluster +* [mini](#constellation-mini): Manage MiniConstellation clusters + * [up](#constellation-mini-up): Create and initialize a new MiniConstellation cluster + * [down](#constellation-mini-down): Destroy a MiniConstellation cluster +* [status](#constellation-status): Show status of a Constellation cluster +* [verify](#constellation-verify): Verify the confidential properties of a Constellation cluster +* [upgrade](#constellation-upgrade): Find and apply upgrades to your Constellation cluster + * [check](#constellation-upgrade-check): Check for possible upgrades + * [apply](#constellation-upgrade-apply): Apply an upgrade to a Constellation cluster +* [recover](#constellation-recover): Recover a completely stopped Constellation cluster +* [terminate](#constellation-terminate): Terminate a Constellation cluster +* [iam](#constellation-iam): Work with the IAM configuration on your cloud provider + * [create](#constellation-iam-create): Create IAM configuration on a cloud platform for your Constellation cluster + * [aws](#constellation-iam-create-aws): Create IAM configuration on AWS for your Constellation cluster + * [azure](#constellation-iam-create-azure): Create IAM configuration on Microsoft Azure for your Constellation cluster + * [gcp](#constellation-iam-create-gcp): Create IAM configuration on GCP for your Constellation cluster + * [destroy](#constellation-iam-destroy): Destroy an IAM configuration and delete local Terraform files + * [upgrade](#constellation-iam-upgrade): Find and apply upgrades to your IAM profile + * [apply](#constellation-iam-upgrade-apply): Apply an upgrade to an IAM profile +* [version](#constellation-version): Display version of this CLI +* [init](#constellation-init): Initialize the Constellation cluster + +## constellation config + +Work with the Constellation configuration file + +### Synopsis + +Work with the Constellation configuration file. + +### Options + +``` + -h, --help help for config +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config generate + +Generate a default configuration and state file + +### Synopsis + +Generate a default configuration and state file for your selected cloud provider. + +``` +constellation config generate {aws|azure|gcp|openstack|qemu|stackit} [flags] +``` + +### Options + +``` + -a, --attestation string attestation variant to use {aws-sev-snp|aws-nitro-tpm|azure-sev-snp|azure-tdx|azure-trustedlaunch|gcp-sev-snp|gcp-sev-es|qemu-vtpm}. If not specified, the default for the cloud provider is used + -h, --help help for generate + -k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR (default "v1.29") + -t, --tags strings additional tags for created resources given a list of key=value +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config fetch-measurements + +Fetch measurements for configured cloud provider and image + +### Synopsis + +Fetch measurements for configured cloud provider and image. + +A config needs to be generated first. + +``` +constellation config fetch-measurements [flags] +``` + +### Options + +``` + -h, --help help for fetch-measurements + -s, --signature-url string alternative URL to fetch measurements' signature from + -u, --url string alternative URL to fetch measurements from +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config instance-types + +Print the supported instance types for all cloud providers + +### Synopsis + +Print the supported instance types for all cloud providers. + +``` +constellation config instance-types [flags] +``` + +### Options + +``` + -h, --help help for instance-types +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config kubernetes-versions + +Print the Kubernetes versions supported by this CLI + +### Synopsis + +Print the Kubernetes versions supported by this CLI. + +``` +constellation config kubernetes-versions [flags] +``` + +### Options + +``` + -h, --help help for kubernetes-versions +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation config migrate + +Migrate a configuration file to a new version + +### Synopsis + +Migrate a configuration file to a new version. + +``` +constellation config migrate [flags] +``` + +### Options + +``` + -h, --help help for migrate +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation create + +Create instances on a cloud platform for your Constellation cluster + +### Synopsis + +Create instances on a cloud platform for your Constellation cluster. + +``` +constellation create [flags] +``` + +### Options + +``` + -h, --help help for create + -y, --yes create the cluster without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation apply + +Apply a configuration to a Constellation cluster + +### Synopsis + +Apply a configuration to a Constellation cluster to initialize or upgrade the cluster. + +``` +constellation apply [flags] +``` + +### Options + +``` + --conformance enable conformance mode + -h, --help help for apply + --merge-kubeconfig merge Constellation kubeconfig file with default kubeconfig file in $HOME/.kube/config + --skip-helm-wait install helm charts without waiting for deployments to be ready + --skip-phases strings comma-separated list of upgrade phases to skip + one or multiple of { infrastructure | init | attestationconfig | certsans | helm | image | k8s } + -y, --yes run command without further confirmation + WARNING: the command might delete or update existing resources without additional checks. Please read the docs. + +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation mini + +Manage MiniConstellation clusters + +### Synopsis + +Manage MiniConstellation clusters. + +### Options + +``` + -h, --help help for mini +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation mini up + +Create and initialize a new MiniConstellation cluster + +### Synopsis + +Create and initialize a new MiniConstellation cluster. + +A mini cluster consists of a single control-plane and worker node, hosted using QEMU/KVM. + +``` +constellation mini up [flags] +``` + +### Options + +``` + -h, --help help for up + --merge-kubeconfig merge Constellation kubeconfig file with default kubeconfig file in $HOME/.kube/config (default true) +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation mini down + +Destroy a MiniConstellation cluster + +### Synopsis + +Destroy a MiniConstellation cluster. + +``` +constellation mini down [flags] +``` + +### Options + +``` + -h, --help help for down + -y, --yes terminate the cluster without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation status + +Show status of a Constellation cluster + +### Synopsis + +Show the status of a constellation cluster. + +Shows microservice, image, and Kubernetes versions installed in the cluster. Also shows status of current version upgrades. + +``` +constellation status [flags] +``` + +### Options + +``` + -h, --help help for status +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation verify + +Verify the confidential properties of a Constellation cluster + +### Synopsis + +Verify the confidential properties of a Constellation cluster. +If arguments aren't specified, values are read from `constellation-state.yaml`. + +``` +constellation verify [flags] +``` + +### Options + +``` + --cluster-id string expected cluster identifier + -h, --help help for verify + -e, --node-endpoint string endpoint of the node to verify, passed as HOST[:PORT] + -o, --output string print the attestation document in the output format {json|raw} +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation upgrade + +Find and apply upgrades to your Constellation cluster + +### Synopsis + +Find and apply upgrades to your Constellation cluster. + +### Options + +``` + -h, --help help for upgrade +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation upgrade check + +Check for possible upgrades + +### Synopsis + +Check which upgrades can be applied to your Constellation Cluster. + +``` +constellation upgrade check [flags] +``` + +### Options + +``` + -h, --help help for check + --ref string the reference to use for querying new versions (default "-") + --stream string the stream to use for querying new versions (default "stable") + -u, --update-config update the specified config file with the suggested versions +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation upgrade apply + +Apply an upgrade to a Constellation cluster + +### Synopsis + +Apply an upgrade to a Constellation cluster by applying the chosen configuration. + +``` +constellation upgrade apply [flags] +``` + +### Options + +``` + --conformance enable conformance mode + -h, --help help for apply + --skip-helm-wait install helm charts without waiting for deployments to be ready + --skip-phases strings comma-separated list of upgrade phases to skip + one or multiple of { infrastructure | helm | image | k8s } + -y, --yes run upgrades without further confirmation + WARNING: might delete your resources in case you are using cert-manager in your cluster. Please read the docs. + WARNING: might unintentionally overwrite measurements in the running cluster. +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation recover + +Recover a completely stopped Constellation cluster + +### Synopsis + +Recover a Constellation cluster by sending a recovery key to an instance in the boot stage. + +This is only required if instances restart without other instances available for bootstrapping. + +``` +constellation recover [flags] +``` + +### Options + +``` + -e, --endpoint string endpoint of the instance, passed as HOST[:PORT] + -h, --help help for recover +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation terminate + +Terminate a Constellation cluster + +### Synopsis + +Terminate a Constellation cluster. + +The cluster can't be started again, and all persistent storage will be lost. + +``` +constellation terminate [flags] +``` + +### Options + +``` + -h, --help help for terminate + -y, --yes terminate the cluster without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam + +Work with the IAM configuration on your cloud provider + +### Synopsis + +Work with the IAM configuration on your cloud provider. + +### Options + +``` + -h, --help help for iam +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam create + +Create IAM configuration on a cloud platform for your Constellation cluster + +### Synopsis + +Create IAM configuration on a cloud platform for your Constellation cluster. + +### Options + +``` + -h, --help help for create + --update-config update the config file with the specific IAM information + -y, --yes create the IAM configuration without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam create aws + +Create IAM configuration on AWS for your Constellation cluster + +### Synopsis + +Create IAM configuration on AWS for your Constellation cluster. + +``` +constellation iam create aws [flags] +``` + +### Options + +``` + -h, --help help for aws + --prefix string name prefix for all resources (required) + --zone string AWS availability zone the resources will be created in, e.g., us-east-2a (required) + See the Constellation docs for a list of currently supported regions. +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + --update-config update the config file with the specific IAM information + -C, --workspace string path to the Constellation workspace + -y, --yes create the IAM configuration without further confirmation +``` + +## constellation iam create azure + +Create IAM configuration on Microsoft Azure for your Constellation cluster + +### Synopsis + +Create IAM configuration on Microsoft Azure for your Constellation cluster. + +``` +constellation iam create azure [flags] +``` + +### Options + +``` + -h, --help help for azure + --region string region the resources will be created in, e.g., westus (required) + --resourceGroup string name prefix of the two resource groups your cluster / IAM resources will be created in (required) + --servicePrincipal string name of the service principal that will be created (required) + --subscriptionID string subscription ID of the Azure account. Required if the 'ARM_SUBSCRIPTION_ID' environment variable is not set +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + --update-config update the config file with the specific IAM information + -C, --workspace string path to the Constellation workspace + -y, --yes create the IAM configuration without further confirmation +``` + +## constellation iam create gcp + +Create IAM configuration on GCP for your Constellation cluster + +### Synopsis + +Create IAM configuration on GCP for your Constellation cluster. + +``` +constellation iam create gcp [flags] +``` + +### Options + +``` + -h, --help help for gcp + --projectID string ID of the GCP project the configuration will be created in (required) + Find it on the welcome screen of your project: https://console.cloud.google.com/welcome + --serviceAccountID string ID for the service account that will be created (required) + Must be 6 to 30 lowercase letters, digits, or hyphens. + --zone string GCP zone the cluster will be deployed in (required) + Find a list of available zones here: https://cloud.google.com/compute/docs/regions-zones#available +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + --update-config update the config file with the specific IAM information + -C, --workspace string path to the Constellation workspace + -y, --yes create the IAM configuration without further confirmation +``` + +## constellation iam destroy + +Destroy an IAM configuration and delete local Terraform files + +### Synopsis + +Destroy an IAM configuration and delete local Terraform files. + +``` +constellation iam destroy [flags] +``` + +### Options + +``` + -h, --help help for destroy + -y, --yes destroy the IAM configuration without asking for confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam upgrade + +Find and apply upgrades to your IAM profile + +### Synopsis + +Find and apply upgrades to your IAM profile. + +### Options + +``` + -h, --help help for upgrade +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation iam upgrade apply + +Apply an upgrade to an IAM profile + +### Synopsis + +Apply an upgrade to an IAM profile. + +``` +constellation iam upgrade apply [flags] +``` + +### Options + +``` + -h, --help help for apply + -y, --yes run upgrades without further confirmation +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation version + +Display version of this CLI + +### Synopsis + +Display version of this CLI. + +``` +constellation version [flags] +``` + +### Options + +``` + -h, --help help for version +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + +## constellation init + +Initialize the Constellation cluster + +### Synopsis + +Initialize the Constellation cluster. + +Start your confidential Kubernetes. + +``` +constellation init [flags] +``` + +### Options + +``` + --conformance enable conformance mode + -h, --help help for init + --merge-kubeconfig merge Constellation kubeconfig file with default kubeconfig file in $HOME/.kube/config + --skip-helm-wait install helm charts without waiting for deployments to be ready +``` + +### Options inherited from parent commands + +``` + --debug enable debug logging + --force disable version compatibility checks - might result in corrupted clusters + --tf-log string Terraform log level (default "NONE") + -C, --workspace string path to the Constellation workspace +``` + diff --git a/docs/versioned_docs/version-2.19/reference/migration.md b/docs/versioned_docs/version-2.19/reference/migration.md new file mode 100644 index 000000000..0252c409f --- /dev/null +++ b/docs/versioned_docs/version-2.19/reference/migration.md @@ -0,0 +1,128 @@ +# Migrations + +This document describes breaking changes and migrations between Constellation releases. +Use [`constellation config migrate`](./cli.md#constellation-config-migrate) to automatically update an old config file to a new format. + +## Migrations to v2.19.1 + +### Azure + +* During the upgrade, security rules are migrated and the old ones need to be cleaned up manually by the user. The below script shows how to delete them through the Azure CLI: + +```bash +#!/usr/bin/env bash +name="" # the name provided in the config +uid="" # the cluster id can be retrieved via `yq '.infrastructure.uid' constellation-state.yaml` +resource_group="" # the RG can be retrieved via `yq '.provider.azure.resourceGroup' constellation-conf.yaml` + +rules=( + "kubernetes" + "bootstrapper" + "verify" + "recovery" + "join" + "debugd" + "konnectivity" +) + +for rule in "${rules[@]}"; do + echo "Deleting rule: ${rule}" + az network nsg rule delete \ + --resource-group "${resource_group}" \ + --nsg-name "${name}-${uid}" \ + --name "${rule}" +done + +echo "All specified rules have been deleted." +``` + +## Migrations to v2.19.0 + +### Azure + +* To allow seamless upgrades on Azure when Kubernetes services of type `LoadBalancer` are deployed, the target + load balancer in which the `cloud-controller-manager` creates load balancing rules was changed. Instead of using the load balancer + created and maintained by the CLI's Terraform code, the `cloud-controller-manager` now creates its own load balancer in Azure. + If your Constellation has services of type `LoadBalancer`, please remove them before the upgrade and re-apply them + afterward. + +## Migrating from Azure's service principal authentication to managed identity authentication (during the upgrade to Constellation v2.8.0) + +* The `provider.azure.appClientID` and `provider.azure.appClientSecret` fields are no longer supported and should be removed. +* To keep using an existing UAMI, add the `Owner` permission with the scope of your `resourceGroup`. +* Otherwise, simply [create new Constellation IAM credentials](../workflows/config.md#creating-an-iam-configuration) and use the created UAMI. +* To migrate the authentication for an existing cluster on Azure to an UAMI with the necessary permissions: + 1. Remove the `aadClientId` and `aadClientSecret` from the azureconfig secret. + 2. Set `useManagedIdentityExtension` to `true` and use the `userAssignedIdentity` from the Constellation config for the value of `userAssignedIdentityID`. + 3. Restart the CSI driver, cloud controller manager, cluster autoscaler, and Constellation operator pods. + +## Migrating from CLI versions before 2.10 + +* AWS cluster upgrades require additional IAM permissions for the newly introduced `aws-load-balancer-controller`. Please upgrade your IAM roles using `iam upgrade apply`. This will show necessary changes and apply them, if desired. +* The global `nodeGroups` field was added. +* The fields `instanceType`, `stateDiskSizeGB`, and `stateDiskType` for each cloud provider are now part of the configuration of individual node groups. +* The `constellation create` command no longer uses the flags `--control-plane-count` and `--worker-count`. Instead, the initial node count is configured per node group in the `nodeGroups` field. + +## Migrating from CLI versions before 2.9 + +* The `provider.azure.appClientID` and `provider.azure.clientSecretValue` fields were removed to enforce migration to managed identity authentication + +## Migrating from CLI versions before 2.8 + +* The `measurements` field for each cloud service provider was replaced with a global `attestation` field. +* The `confidentialVM`, `idKeyDigest`, and `enforceIdKeyDigest` fields for the Azure cloud service provider were removed in favor of using the global `attestation` field. +* The optional global field `attestationVariant` was replaced by the now required `attestation` field. + +## Migrating from CLI versions before 2.3 + +* The `sshUsers` field was deprecated in v2.2 and has been removed from the configuration in v2.3. + As an alternative for SSH, check the workflow section [Connect to nodes](../workflows/troubleshooting.md#node-shell-access). +* The `image` field for each cloud service provider has been replaced with a global `image` field. Use the following mapping to migrate your configuration: +
+ Show all + + | CSP | old image | new image | + | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | + | AWS | `ami-06b8cbf4837a0a57c` | `v2.2.2` | + | AWS | `ami-02e96dc04a9e438cd` | `v2.2.2` | + | AWS | `ami-028ead928a9034b2f` | `v2.2.2` | + | AWS | `ami-032ac10dd8d8266e3` | `v2.2.1` | + | AWS | `ami-032e0d57cc4395088` | `v2.2.1` | + | AWS | `ami-053c3e49e19b96bdd` | `v2.2.1` | + | AWS | `ami-0e27ebcefc38f648b` | `v2.2.0` | + | AWS | `ami-098cd37f66523b7c3` | `v2.2.0` | + | AWS | `ami-04a87d302e2509aad` | `v2.2.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.2.2` | `v2.2.2` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.2.2` | `v2.2.2` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.2.1` | `v2.2.1` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.2.1` | `v2.2.1` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.2.0` | `v2.2.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.2.0` | `v2.2.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.1.0` | `v2.1.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.1.0` | `v2.1.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.0.0` | `v2.0.0` | + | Azure | `/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation_CVM/images/constellation/versions/2.0.0` | `v2.0.0` | + | GCP | `projects/constellation-images/global/images/constellation-v2-2-2` | `v2.2.2` | + | GCP | `projects/constellation-images/global/images/constellation-v2-2-1` | `v2.2.1` | + | GCP | `projects/constellation-images/global/images/constellation-v2-2-0` | `v2.2.0` | + | GCP | `projects/constellation-images/global/images/constellation-v2-1-0` | `v2.1.0` | + | GCP | `projects/constellation-images/global/images/constellation-v2-0-0` | `v2.0.0` | + +
+* The `enforcedMeasurements` field has been removed and merged with the `measurements` field. + * To migrate your config containing a new image (`v2.3` or greater), remove the old `measurements` and `enforcedMeasurements` entries from your config and run `constellation fetch-measurements` + * To migrate your config containing an image older than `v2.3`, remove the `enforcedMeasurements` entry and replace the entries in `measurements` as shown in the example below: + + ```diff + measurements: + - 0: DzXCFGCNk8em5ornNZtKi+Wg6Z7qkQfs5CfE3qTkOc8= + + 0: + + expected: DzXCFGCNk8em5ornNZtKi+Wg6Z7qkQfs5CfE3qTkOc8= + + warnOnly: true + - 8: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + + 8: + + expected: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + + warnOnly: false + -enforcedMeasurements: + - - 8 + ``` diff --git a/docs/versioned_docs/version-2.19/reference/slsa.md b/docs/versioned_docs/version-2.19/reference/slsa.md new file mode 100644 index 000000000..21f4e713c --- /dev/null +++ b/docs/versioned_docs/version-2.19/reference/slsa.md @@ -0,0 +1,73 @@ +# Supply chain levels for software artifacts (SLSA) adoption + +[Supply chain Levels for Software Artifacts, or SLSA (salsa)](https://slsa.dev/) is a framework for improving and grading a project's build system and engineering processes. SLSA focuses on security improvements for source code storage as well as build system definition, execution, and observation. SLSA is structured in [four levels](https://slsa.dev/spec/v0.1/levels). This page describes the adoption of SLSA for Constellation. + +:::info +SLSA is still in alpha status. The presented levels and their requirements might change in the future. We will adopt any changes into our engineering processes, as they get defined. +::: + +## Level 1 - Adopted + +**[Build - Scripted](https://slsa.dev/spec/v0.1/requirements#scripted-build)** + +All build steps are automated via [Bazel](https://github.com/edgelesssys/constellation/tree/main/bazel/ci) and [GitHub Actions](https://github.com/edgelesssys/constellation/tree/main/.github). + +**[Provenance - Available](https://slsa.dev/spec/v0.1/requirements#available)** + +Provenance for the CLI is generated using the [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator). + +## Level 2 - Adopted + +**[Source - Version Controlled](https://slsa.dev/spec/v0.1/requirements#version-controlled)** + +Constellation is hosted on GitHub using git. + +**[Build - Build Service](https://slsa.dev/spec/v0.1/requirements#build-service)** + +All builds are carried out by [GitHub Actions](https://github.com/edgelesssys/constellation/tree/main/.github). + +**[Provenance - Authenticated](https://slsa.dev/spec/v0.1/requirements#authenticated)** + +Provenance for the CLI is signed using the [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator). Learn [how to verify the CLI](../workflows/verify-cli.md) using the signed provenance, before using it for the first time. + +**[Provenance - Service Generated](https://slsa.dev/spec/v0.1/requirements#service-generated)** + +Provenance for the CLI is generated using the [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator) in GitHub Actions. + +## Level 3 - Adopted + +**[Source - Verified History](https://slsa.dev/spec/v0.1/requirements#verified-history)** + +The [Edgeless Systems](https://github.com/edgelesssys) GitHub organization [requires two-factor authentication](https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization) for all members. + +**[Source - Retained Indefinitely](https://slsa.dev/spec/v0.1/requirements#retained-indefinitely)** + +Since we use GitHub to host the repository, an external person can't modify or delete the history. Before a pull request can be merged, an explicit approval from an [Edgeless Systems](https://github.com/edgelesssys) team member is required. + +The same holds true for changes proposed by team members. Each change to `main` needs to be proposed via a pull request and requires at least one approval. + +The [Edgeless Systems](https://github.com/edgelesssys) GitHub organization admins control these settings and are able to make changes to the repository's history should legal requirements necessitate it. These changes require two-party approval following the obliterate policy. + +**[Build - Build as Code](https://slsa.dev/spec/v0.1/requirements#build-as-code)** + +All build files for Constellation are stored in [the same repository](https://github.com/edgelesssys/constellation/tree/main/.github). + +**[Build - Ephemeral Environment](https://slsa.dev/spec/v0.1/requirements#ephemeral-environment)** + +All GitHub Action workflows are executed on [GitHub-hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners). These runners are only available during workflow. + +We currently don't use [self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners). + +**[Build - Isolated](https://slsa.dev/spec/v0.1/requirements#isolated)** + +As outlined in the previous section, we use GitHub-hosted runners, which provide a new, isolated and ephemeral environment for each build. + +Additionally, the [SLSA GitHub generator](https://github.com/slsa-framework/slsa-github-generator#generation-of-provenance) itself is run in an isolated workflow with the artifact hash as defined inputs. + +**[Provenance - Non-falsifiable](https://slsa.dev/spec/v0.1/requirements#non-falsifiable)** + +As outlined by [SLSA GitHub generator](https://github.com/slsa-framework/slsa-github-generator) it already fulfills the non-falsifiable requirements for SLSA Level 3. The generated provenance is signed using [sigstore](https://sigstore.dev/) with an OIDC based proof of identity. + +## Level 4 - In Progress + +We strive to adopt certain aspect of SLSA Level 4 that support our engineering process. At the same time, SLSA is still in alpha status and the biggest changes to SLSA are expected to be around Level 4. diff --git a/docs/versioned_docs/version-2.19/reference/terraform.md b/docs/versioned_docs/version-2.19/reference/terraform.md new file mode 100644 index 000000000..9825a8bb8 --- /dev/null +++ b/docs/versioned_docs/version-2.19/reference/terraform.md @@ -0,0 +1,37 @@ +# Terraform usage + +[Terraform](https://www.terraform.io/) is an Infrastructure as Code (IaC) framework to manage cloud resources. This page explains how Constellation uses it internally and how advanced users may manually use it to have more control over the resource creation. + +:::info +Information on this page is intended for users who are familiar with Terraform. +It's not required for common usage of Constellation. +See the [Terraform documentation](https://developer.hashicorp.com/terraform/docs) if you want to learn more about it. +::: + +## Terraform state files + +Constellation keeps Terraform state files in subdirectories of the workspace together with the corresponding Terraform configuration files and metadata. +The subdirectories are created on the first Constellation CLI action that uses Terraform internally. + +Currently, these subdirectories are: + +* `constellation-terraform` - Terraform state files for the resources of the Constellation cluster +* `constellation-iam-terraform` - Terraform state files for IAM configuration + +As with all commands, commands that work with these files (e.g., `apply`, `terminate`, `iam`) have to be executed from the root of the cluster's [workspace directory](../architecture/orchestration.md#workspaces). You usually don't need and shouldn't manipulate or delete the subdirectories manually. + +## Interacting with Terraform manually + +Manual interaction with Terraform state created by Constellation (i.e., via the Terraform CLI) should only be performed by experienced users. It may lead to unrecoverable loss of cloud resources. For the majority of users and use cases, the interaction done by the [Constellation CLI](cli.md) is sufficient. + +## Terraform debugging + +To debug Terraform issues, the Constellation CLI offers the `tf-log` flag. You can set it to any of [Terraform's log levels](https://developer.hashicorp.com/terraform/internals/debugging): +* `JSON` (JSON-formatted logs at `TRACE` level) +* `TRACE` +* `DEBUG` +* `INFO` +* `WARN` +* `ERROR` + +The log output is written to the `terraform.log` file in the workspace directory. The output is appended to the file on each run. diff --git a/docs/versioned_docs/version-2.19/workflows/cert-manager.md b/docs/versioned_docs/version-2.19/workflows/cert-manager.md new file mode 100644 index 000000000..1d847e8bf --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/cert-manager.md @@ -0,0 +1,13 @@ +# Install cert-manager + +:::caution +If you want to use cert-manager with Constellation, pay attention to the following to avoid potential pitfalls. +::: + +Constellation ships with cert-manager preinstalled. +The default installation is part of the `kube-system` namespace, as all other Constellation-managed microservices. +You are free to install more instances of cert-manager into other namespaces. +However, be aware that any new installation needs to use the same version as the one installed with Constellation or rely on the same CRD versions. +Also remember to set the `installCRDs` value to `false` when installing new cert-manager instances. +It will create problems if you have two installations of cert-manager depending on different versions of the installed CRDs. +CRDs are cluster-wide resources and cert-manager depends on specific versions of those CRDs for each release. diff --git a/docs/versioned_docs/version-2.19/workflows/config.md b/docs/versioned_docs/version-2.19/workflows/config.md new file mode 100644 index 000000000..95f791acd --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/config.md @@ -0,0 +1,353 @@ +# Configure your cluster + +:::info +This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. +::: + + + +--- + +Before you can create your cluster, you need to configure the identity and access management (IAM) for your cloud service provider (CSP) and choose machine types for the nodes. + +## Creating the configuration file + +You can generate a configuration file for your CSP by using the following CLI command: + + + + +```bash +constellation config generate aws +``` + + + + +```bash +constellation config generate azure +``` + + + + +```bash +constellation config generate gcp +``` + + + + +```bash +constellation config generate stackit +``` + + + + +This creates the file `constellation-conf.yaml` in the current directory. + +## Choosing a VM type + +Constellation supports the following VM types: + + + +By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. +Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. +If you are using the default attestation variant `awsSEVSNP`, you can use the instance types described in [AWS's AMD SEV-SNP docs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/snp-requirements.html). +Please mind the region restrictions mentioned in the [Getting started](../getting-started/first-steps.md#create-a-cluster) section. + +If you are using the attestation variant `awsNitroTPM`, you can choose any of the [nitroTPM-enabled instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-prerequisites.html). + +The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. + + + + +By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. + +You can also run `constellation config instance-types` to get the list of all supported options. + + + + +By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. + + + + +By default, Constellation uses `m1a.4cd` VMs (4 vCPUs, 30 GB RAM) to create your cluster. +Optionally, you can switch to a different VM type by modifying `instanceType` in the configuration file. + +The following instance types are known to be supported: + +| name | vCPUs | GB RAM | +|----------|-------|--------| +| m1a.4cd | 4 | 30 | +| m1a.8cd | 8 | 60 | +| m1a.16cd | 16 | 120 | +| m1a.30cd | 30 | 230 | + +You can choose any of the SEV-enabled instance types. You can find a list of all supported instance types in the [STACKIT documentation](https://docs.stackit.cloud/stackit/en/virtual-machine-flavors-75137231.html). + +The Constellation CLI can also print the supported instance types with: `constellation config instance-types`. + + + + +Fill the desired VM type into the `instanceType` fields in the `constellation-conf.yml` file. + +## Creating additional node groups + +By default, Constellation creates the node groups `control_plane_default` and `worker_default` for control-plane nodes and workers, respectively. +If you require additional control-plane or worker groups with different instance types, zone placements, or disk sizes, you can add additional node groups to the `constellation-conf.yml` file. +Each node group can be scaled individually. + +Consider the following example for AWS: + +```yaml +nodeGroups: + control_plane_default: + role: control-plane + instanceType: c6a.xlarge + stateDiskSizeGB: 30 + stateDiskType: gp3 + zone: eu-west-1c + initialCount: 3 + worker_default: + role: worker + instanceType: c6a.xlarge + stateDiskSizeGB: 30 + stateDiskType: gp3 + zone: eu-west-1c + initialCount: 2 + high_cpu: + role: worker + instanceType: c6a.24xlarge + stateDiskSizeGB: 128 + stateDiskType: gp3 + zone: eu-west-1c + initialCount: 1 +``` + +This configuration creates an additional node group `high_cpu` with a larger instance type and disk. + +You can use the field `zone` to specify what availability zone nodes of the group are placed in. +On Azure, this field is empty by default and nodes are automatically spread across availability zones. +STACKIT currently offers SEV-enabled CPUs in the `eu01-1`, `eu01-2`, and `eu01-3` zones. +Consult the documentation of your cloud provider for more information: + +* [AWS](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) +* [Azure](https://azure.microsoft.com/en-us/explore/global-infrastructure/availability-zones) +* [GCP](https://cloud.google.com/compute/docs/regions-zones) +* [STACKIT](https://docs.stackit.cloud/stackit/en/regions-and-availability-zones-75137212.html) + +## Choosing a Kubernetes version + +To learn which Kubernetes versions can be installed with your current CLI, you can run `constellation config kubernetes-versions`. +See also Constellation's [Kubernetes support policy](../architecture/versions.md#kubernetes-support-policy). + +## Creating an IAM configuration + +You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. +If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. + + + + +You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). + +```bash +constellation iam create aws --zone=us-east-2a --prefix=constellTest +``` + +This command creates IAM configuration for the AWS zone `us-east-2a` using the prefix `constellTest` for all named resources being created. + +Constellation OS images are currently replicated to the following regions: + +* `eu-central-1` +* `eu-west-1` +* `eu-west-3` +* `us-east-2` +* `ap-south-1` + +If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+AWS+image+region:+xx-xxxx-x). + +You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). + +Paste the output into the corresponding fields of the `constellation-conf.yaml` file. + + + + +You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). + +```bash +constellation iam create azure --subscriptionID 00000000-0000-0000-0000-000000000000 --region=westus --resourceGroup=constellTest --servicePrincipal=spTest +``` + +This command creates IAM configuration on the Azure region `westus` creating a new resource group `constellTest` and a new service principal `spTest`. + +CVMs are available in several Azure regions. Constellation OS images are currently replicated to the following: + +* `germanywestcentral` +* `westus` +* `eastus` +* `northeurope` +* `westeurope` +* `southeastasia` + +If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+Azure+image+region:+xx-xxxx-x). + +You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). + +Paste the output into the corresponding fields of the `constellation-conf.yaml` file. + + + + +You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). + +```bash +constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test +``` + +This command creates IAM configuration in the GCP project `yourproject-12345` on the GCP zone `europe-west2-a` creating a new service account `constell-test`. + +Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `N2D`. + +Paste the output into the corresponding fields of the `constellation-conf.yaml` file. + + + + +STACKIT requires manual creation and configuration of service accounts. Look at the [first steps](../getting-started/first-steps.md) for more information. + + + + +
+Alternatively, you can manually create the IAM configuration on your CSP. + +The following describes the configuration fields and how you obtain the required information or create the required resources. + + + + +* **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. + + Constellation OS images are currently replicated to the following regions: + * `eu-central-1` + * `eu-west-1` + * `eu-west-3` + * `us-east-2` + * `ap-south-1` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+AWS+image+region:+xx-xxxx-x). + + You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). + +* **zone**: The name of your chosen AWS data center availability zone, e.g., `us-east-2a`. + + Learn more about [availability zones in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-availability-zones). + +* **iamProfileControlPlane**: The name of an IAM instance profile attached to all control-plane nodes. + + You can create the resource with [Terraform](https://www.terraform.io/). For that, use the [provided Terraform script](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam) to generate the necessary profile. The profile name will be provided as Terraform output value: `control_plane_instance_profile_name`. + + Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.control_plane_policy`. + +* **iamProfileWorkerNodes**: The name of an IAM instance profile attached to all worker nodes. + + You can create the resource with [Terraform](https://www.terraform.io/). For that, use the [provided Terraform script](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam) to generate the necessary profile. The profile name will be provided as Terraform output value: `worker_nodes_instance_profile_name`. + + Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. + + + + +* **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. + + You can view your subscription UUID via `az account show` and read the `id` field. For more information refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-subscription). + +* **tenant**: The UUID of your Azure tenant, e.g., `3400e5a2-8fe2-492a-886c-38cb66170f25`. + + You can view your tenant UUID via `az account show` and read the `tenant` field. For more information refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-ad-tenant). + +* **location**: The Azure datacenter location you want to deploy your cluster in, e.g., `westus`. + + CVMs are available in several Azure regions. Constellation OS images are currently replicated to the following: + + * `germanywestcentral` + * `westus` + * `eastus` + * `northeurope` + * `westeurope` + * `southeastasia` + + If you require the OS image to be available in another region, [let us know](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&template=feature_request.md&title=Support+new+Azure+image+region:+xx-xxxx-x). + + You can find a list of all [regions in Azure's documentation](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines®ions=all). + +* **resourceGroup**: [Create a new resource group in Azure](https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal) for your Constellation cluster. Set this configuration field to the name of the created resource group. + +* **userAssignedIdentity**: [Create a new managed identity in Azure](https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). You should create the identity in a different resource group as all resources within the cluster resource group will be deleted on cluster termination. + + Add three role assignments to the identity: `Owner`, `Virtual Machine Contributor`, and `Application Insights Component Contributor`. The `scope` of all three should refer to the previously created cluster resource group. + + Set the configuration value to the full ID of the created identity, e.g., `/subscriptions/8b8bd01f-efd9-4113-9bd1-c82137c32da7/resourcegroups/constellation-identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/constellation-identity`. You can get it by opening the `JSON View` from the `Overview` section of the identity. + + The user-assigned identity is used by instances of the cluster to access other cloud resources. + For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). + + + + +* **project**: The ID of your GCP project, e.g., `constellation-129857`. + + You can find it on the [welcome screen of your GCP project](https://console.cloud.google.com/welcome). For more information refer to [Google's documentation](https://support.google.com/googleapi/answer/7014113). + +* **region**: The GCP region you want to deploy your cluster in, e.g., `us-west1`. + + You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available). + +* **zone**: The GCP zone you want to deploy your cluster in, e.g., `us-west1-a`. + + You can find a [list of all zones in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available). + +* **serviceAccountKeyPath**: To configure this, you need to create a GCP [service account](https://cloud.google.com/iam/docs/service-accounts) with the following permissions: + + * `Compute Instance Admin (v1) (roles/compute.instanceAdmin.v1)` + * `Compute Network Admin (roles/compute.networkAdmin)` + * `Compute Security Admin (roles/compute.securityAdmin)` + * `Compute Storage Admin (roles/compute.storageAdmin)` + * `Service Account User (roles/iam.serviceAccountUser)` + + Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. + + + + +STACKIT requires manual creation and configuration of service accounts. Look at the [first steps](../getting-started/first-steps.md) for more information. + + + +
+ +Now that you've configured your CSP, you can [create your cluster](./create.md). + +## Deleting an IAM configuration + +You can keep a created IAM configuration and reuse it for new clusters. Alternatively, you can also delete it if you don't want to use it anymore. + +Delete the IAM configuration by executing the following command in the same directory where you executed `constellation iam create` (the directory that contains [`constellation-iam-terraform`](../reference/terraform.md) as a subdirectory): + +```bash +constellation iam destroy +``` + +:::caution +For Azure, deleting the IAM configuration by executing `constellation iam destroy` will delete the whole resource group created by `constellation iam create`. +This also includes any additional resources in the resource group that weren't created by Constellation. +::: diff --git a/docs/versioned_docs/version-2.19/workflows/create.md b/docs/versioned_docs/version-2.19/workflows/create.md new file mode 100644 index 000000000..6074ebb16 --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/create.md @@ -0,0 +1,93 @@ +# Create your cluster + +:::info +This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. +::: + + + +--- + +Creating your cluster happens through multiple phases. +The most significant ones are: + +1. Creating the necessary resources in your cloud environment +2. Bootstrapping the Constellation cluster and setting up a connection +3. Installing the necessary Kubernetes components + +`constellation apply` handles all this in a single command. +You can use the `--skip-phases` flag to skip specific phases of the process. +For example, if you created the infrastructure manually, you can skip the cloud resource creation phase. + +See the [architecture](../architecture/orchestration.md) section for details on the inner workings of this process. + +:::tip +If you don't have a cloud subscription, you can also set up a [local Constellation cluster using virtualization](../getting-started/first-steps-local.md) for testing. +::: + +Before you create the cluster, make sure to have a [valid configuration file](./config.md). + + + + +```bash +constellation apply +``` + +`apply` stores the state of your cluster's cloud resources in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. + + + + +Self-managed infrastructure allows for more flexibility in the setup, by separating the infrastructure setup from the Constellation cluster management. +This provides flexibility in DevOps and can meet potential regulatory requirements. +It's recommended to use Terraform for infrastructure management, but you can use any tool of your choice. + +:::info + + When using Terraform, you can use the [Constellation Terraform provider](./terraform-provider.md) to manage the entire Constellation cluster lifecycle. + +::: + +You can refer to the Terraform files for the selected CSP from the [Constellation GitHub repository](https://github.com/edgelesssys/constellation/tree/main/terraform/infrastructure) for a minimum Constellation cluster configuration. From this base, you can now add, edit, or substitute resources per your own requirements with the infrastructure +management tooling of your choice. You need to keep the essential functionality of the base configuration in order for your cluster to function correctly. + + + +:::info + + On Azure, a manual update to the MAA provider's policy is necessary. + You can apply the update with the following command after creating the infrastructure, with `` being the URL of the MAA provider (i.e., `$(terraform output attestation_url | jq -r)`, when using the minimal Terraform configuration). + + ```bash + constellation maa-patch + ``` + +::: + + + +Make sure all necessary resources are created, e.g., through checking your CSP's portal and retrieve the necessary values, aligned with the outputs (specified in `outputs.tf`) of the base configuration. + +Fill these outputs into the corresponding fields of the `Infrastructure` block inside the `constellation-state.yaml` file. For example, fill the IP or DNS name your cluster can be reached at into the `.Infrastructure.ClusterEndpoint` field. + +With the required cloud resources set up, continue with initializing your cluster. + +```bash +constellation apply --skip-phases=infrastructure +``` + + + + +Finally, configure `kubectl` for your cluster: + +```bash +export KUBECONFIG="$PWD/constellation-admin.conf" +``` + +🏁 That's it. You've successfully created a Constellation cluster. + +### Troubleshooting + +In case `apply` fails, the CLI collects logs from the bootstrapping instance and stores them inside `constellation-cluster.log`. diff --git a/docs/versioned_docs/version-2.19/workflows/lb.md b/docs/versioned_docs/version-2.19/workflows/lb.md new file mode 100644 index 000000000..868e61076 --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/lb.md @@ -0,0 +1,28 @@ +# Expose a service + +Constellation integrates the native load balancers of each CSP. Therefore, to expose a service simply [create a service of type `LoadBalancer`](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer). + +## Internet-facing LB service on AWS + +To expose your application service externally you might want to use a Kubernetes Service of type `LoadBalancer`. On AWS, load-balancing is achieved through the [AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller) as in the managed EKS. + +Since recent versions, the controller deploy an internal LB by default requiring to set an annotation `service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing` to have an internet-facing LB. For more details, see the [official docs](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/guide/service/nlb/). + +For general information on LB with AWS see [Network load balancing on Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/network-load-balancing.html). + +:::caution +Before terminating the cluster, all LB backed services should be deleted, so that the controller can cleanup the related resources. +::: + +## Ingress on AWS + +The AWS Load Balancer Controller also provisions `Ingress` resources of class `alb`. +AWS Application Load Balancers (ALBs) can be configured with a [`target-type`](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/guide/ingress/annotations/#target-type). +The target type `ip` requires using the EKS container network solution, which makes it incompatible with Constellation. +If a service can be exposed on a `NodePort`, the target type `instance` can be used. + +See [Application load balancing on Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html) for more information. + +:::caution +Ingress handlers backed by AWS ALBs reside outside the Constellation cluster, so they shouldn't be handling sensitive traffic! +::: diff --git a/docs/versioned_docs/version-2.19/workflows/recovery.md b/docs/versioned_docs/version-2.19/workflows/recovery.md new file mode 100644 index 000000000..592ae247b --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/recovery.md @@ -0,0 +1,179 @@ +# Recover your cluster + +Recovery of a Constellation cluster means getting it back into a healthy state after too many concurrent node failures in the control plane. +Reasons for an unhealthy cluster can vary from a power outage, or planned reboot, to migration of nodes and regions. +Recovery events are rare, because Constellation is built for high availability and automatically and securely replaces failed nodes. When a node is replaced, Constellation's control plane first verifies the new node before it sends the node the cryptographic keys required to decrypt its [state disk](../architecture/images.md#state-disk). + +Constellation provides a recovery mechanism for cases where the control plane has failed and is unable to replace nodes. +The `constellation recover` command securely connects to all nodes in need of recovery using [attested TLS](../architecture/attestation.md#attested-tls-atls) and provides them with the keys to decrypt their state disks and continue booting. + +## Identify unhealthy clusters + +The first step to recovery is identifying when a cluster becomes unhealthy. +Usually, this can be first observed when the Kubernetes API server becomes unresponsive. + +You can check the health status of the nodes via the cloud service provider (CSP). +Constellation provides logging information on the boot process and status via serial console output. +In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. + + + + +First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. + +Second, check the boot logs of these *Instances*. In the ASG's *Instance management* view, select each desired instance. In the upper right corner, select **Action > Monitor and troubleshoot > Get system log**. + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"gcp"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["192.168.178.4:30090","192.168.178.2:30090"]} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.4:30090"} +{"level":"WARN","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.4:30090: connect: connection refused\"","endpoint":"192.168.178.4:30090"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.2:30090"} +{"level":"WARN","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.2:30090: i/o timeout\"","endpoint":"192.168.178.2:30090"} +{"level":"ERROR","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +In the Azure portal, find the cluster's resource group. +Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. +On the left, go to **Settings** > **Instances** and check that enough members are in a *Running* state. + +Second, check the boot logs of these *Instances*. +In the scale set's *Instances* view, open the details page of the desired instance. +On the left, go to **Support + troubleshooting** > **Serial console**. + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T09:56:41Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"azure"} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["10.9.0.5:30090","10.9.0.6:30090"]} +{"level":"INFO","ts":"2022-09-08T09:56:43Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"10.9.0.5:30090"} +{"level":"WARN","ts":"2022-09-08T09:57:03Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 10.9.0.5:30090: i/o timeout\"","endpoint":"10.9.0.5:30090"} +{"level":"INFO","ts":"2022-09-08T09:57:03Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"10.9.0.6:30090"} +{"level":"WARN","ts":"2022-09-08T09:57:23Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 10.9.0.6:30090: i/o timeout\"","endpoint":"10.9.0.6:30090"} +{"level":"ERROR","ts":"2022-09-08T09:57:23Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +First, check that the control plane *Instance Group* has enough members in a *Ready* state. +In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. + +Second, check the status of the *VM Instances*. +Go to **VM Instances** and open the details of the desired instance. +Check the serial console output of that instance by opening the **Logs** > **Serial port 1 (console)** page: + +![GCP portal serial console link](../_media/recovery-gcp-serial-console-link.png) + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"gcp"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["192.168.178.4:30090","192.168.178.2:30090"]} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.4:30090"} +{"level":"WARN","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.4:30090: connect: connection refused\"","endpoint":"192.168.178.4:30090"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.2:30090"} +{"level":"WARN","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.2:30090: i/o timeout\"","endpoint":"192.168.178.2:30090"} +{"level":"ERROR","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +First, open the STACKIT portal to view all servers in your project. Select individual control plane nodes `--control-plane--` and check that enough members are in a *Running* state. + +Second, check the boot logs of these servers. Click on a server name and select **Overview**. Find the **Machine Setup** section and click on **Web console** > **Open console**. + +In the serial console output, search for `Waiting for decryption key`. +Similar output to the following means your node was restarted and needs to decrypt the [state disk](../architecture/images.md#state-disk): + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","caller":"cmd/main.go:55","msg":"Starting disk-mapper","version":"2.0.0","cloudProvider":"gcp"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"setupManager","caller":"setup/setup.go:72","msg":"Preparing existing state disk"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:65","msg":"Starting RejoinClient"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"recoveryServer","caller":"recoveryserver/server.go:59","msg":"Starting RecoveryServer"} +``` + +The node will then try to connect to the [*JoinService*](../architecture/microservices.md#joinservice) and obtain the decryption key. +If this fails due to an unhealthy control plane, you will see log messages similar to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:77","msg":"Received list with JoinService endpoints","endpoints":["192.168.178.4:30090","192.168.178.2:30090"]} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.4:30090"} +{"level":"WARN","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.4:30090: connect: connection refused\"","endpoint":"192.168.178.4:30090"} +{"level":"INFO","ts":"2022-09-08T10:21:53Z","logger":"rejoinClient","caller":"rejoinclient/client.go:96","msg":"Requesting rejoin ticket","endpoint":"192.168.178.2:30090"} +{"level":"WARN","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:101","msg":"Failed to rejoin on endpoint","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 192.168.178.2:30090: i/o timeout\"","endpoint":"192.168.178.2:30090"} +{"level":"ERROR","ts":"2022-09-08T10:22:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:110","msg":"Failed to rejoin on all endpoints"} +``` + +This means that you have to recover the node manually. + + + + +## Recover a cluster + +Recovering a cluster requires the following parameters: + +* The `constellation-state.yaml` file in your working directory or the cluster's endpoint +* The master secret of the cluster + +A cluster can be recovered like this: + +```bash +$ constellation recover +Pushed recovery key. +Pushed recovery key. +Pushed recovery key. +Recovered 3 control-plane nodes. +``` + +In the serial console output of the node you'll see a similar output to the following: + +```json +{"level":"INFO","ts":"2022-09-08T10:26:59Z","logger":"recoveryServer","caller":"recoveryserver/server.go:93","msg":"Received recover call"} +{"level":"INFO","ts":"2022-09-08T10:26:59Z","logger":"recoveryServer","caller":"recoveryserver/server.go:125","msg":"Received state disk key and measurement secret, shutting down server"} +{"level":"INFO","ts":"2022-09-08T10:26:59Z","logger":"recoveryServer.gRPC","caller":"zap/server_interceptors.go:61","msg":"finished streaming call with code OK","grpc.start_time":"2022-09-08T10:26:59Z","system":"grpc","span.kind":"server","grpc.service":"recoverproto.API","grpc.method":"Recover","peer.address":"192.0.2.3:41752","grpc.code":"OK","grpc.time_ms":15.701} +{"level":"INFO","ts":"2022-09-08T10:27:13Z","logger":"rejoinClient","caller":"rejoinclient/client.go:87","msg":"RejoinClient stopped"} +``` diff --git a/docs/versioned_docs/version-2.19/workflows/s3proxy.md b/docs/versioned_docs/version-2.19/workflows/s3proxy.md new file mode 100644 index 000000000..121e8a461 --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/s3proxy.md @@ -0,0 +1,58 @@ +# Install s3proxy + +Constellation includes a transparent client-side encryption proxy for [AWS S3](https://aws.amazon.com/de/s3/) and compatible stores. +s3proxy encrypts objects before sending them to S3 and automatically decrypts them on retrieval, without requiring changes to your application. +With s3proxy, you can use S3 for storage in a confidential way without having to trust the storage provider. + +## Limitations + +Currently, s3proxy has the following limitations: +- Only `PutObject` and `GetObject` requests are encrypted/decrypted by s3proxy. +By default, s3proxy will block requests that may expose unencrypted data to S3 (e.g. UploadPart). +The `allow-multipart` flag disables request blocking for evaluation purposes. +- Using the [Range](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html#API_GetObject_RequestSyntax) header on `GetObject` is currently not supported and will result in an error. + +These limitations will be removed with future iterations of s3proxy. +If you want to use s3proxy but these limitations stop you from doing so, consider [opening an issue](https://github.com/edgelesssys/constellation/issues/new?assignees=&labels=&projects=&template=feature_request.yml). + +## Deployment + +You can add the s3proxy to your Constellation cluster as follows: +1. Add the Edgeless Systems chart repository: + ```bash + helm repo add edgeless https://helm.edgeless.systems/stable + helm repo update + ``` +2. Set ACCESS_KEY and ACCESS_SECRET to valid credentials you want s3proxy to use to interact with S3. +3. Deploy s3proxy: + ```bash + helm install s3proxy edgeless/s3proxy --set awsAccessKeyID="$ACCESS_KEY" --set awsSecretAccessKey="$ACCESS_SECRET" + ``` + +If you want to run a demo application, check out the [Filestash with s3proxy](../getting-started/examples/filestash-s3proxy.md) example. + + +## Technical details + +### Encryption + +s3proxy relies on Google's [Tink Cryptographic Library](https://developers.google.com/tink) to implement cryptographic operations securely. +The used cryptographic primitives are [NIST SP 800 38f](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf) for key wrapping and [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)-[GCM](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Galois/counter_(GCM)) with 256 bit keys for data encryption. + +s3proxy uses [envelope encryption](https://cloud.google.com/kms/docs/envelope-encryption) to encrypt objects. +This means s3proxy uses a key encryption key (KEK) issued by the [KeyService](../architecture/microservices.md#keyservice) to encrypt data encryption keys (DEKs). +Each S3 object is encrypted with its own DEK. +The encrypted DEK is then saved as metadata of the encrypted object. +This enables key rotation of the KEK without re-encrypting the data in S3. +The approach also allows access to objects from different locations, as long as each location has access to the KEK. + +### Traffic interception + +To use s3proxy, you have to redirect your outbound S3 traffic to s3proxy. +This can either be done by modifying your client application or by changing the deployment of your application. + +The necessary deployment modifications are to add DNS redirection and a trusted TLS certificate to the client's trust store. +DNS redirection can be defined for each pod, allowing you to use s3proxy for one application without changing other applications in the same cluster. +Adding a trusted TLS certificate is necessary as clients communicate with s3proxy via HTTPS. +To have your client application trust s3proxy's TLS certificate, the certificate has to be added to the client's certificate trust store. +The [Filestash with s3proxy](../getting-started/examples/filestash-s3proxy.md) example shows how to do this. diff --git a/docs/versioned_docs/version-2.19/workflows/sbom.md b/docs/versioned_docs/version-2.19/workflows/sbom.md new file mode 100644 index 000000000..6c1702dee --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/sbom.md @@ -0,0 +1,93 @@ +# Consume software bill of materials (SBOMs) + + + +--- + +Constellation builds produce a [software bill of materials (SBOM)](https://www.ntia.gov/SBOM) for each generated [artifact](../architecture/microservices.md). +You can use SBOMs to make informed decisions about dependencies and vulnerabilities in a given application. Enterprises rely on SBOMs to maintain an inventory of used applications, which allows them to take data-driven approaches to managing risks related to vulnerabilities. + +SBOMs for Constellation are generated using [Syft](https://github.com/anchore/syft), signed using [Cosign](https://github.com/sigstore/cosign), and stored with the produced artifact. + +:::note +The public key for Edgeless Systems' long-term code-signing key is: + +``` +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT +JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== +-----END PUBLIC KEY----- +``` + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). + +Make sure the key is available in a file named `cosign.pub` to execute the following examples. +::: + +## Verify and download SBOMs + +The following sections detail how to work with each type of artifact to verify and extract the SBOM. + +### Constellation CLI + +The SBOM for Constellation CLI is made available on the [GitHub release page](https://github.com/edgelesssys/constellation/releases). The SBOM (`constellation.spdx.sbom`) and corresponding signature (`constellation.spdx.sbom.sig`) are valid for each Constellation CLI for a given version, regardless of architecture and operating system. + +```bash +curl -LO https://github.com/edgelesssys/constellation/releases/download/v2.2.0/constellation.spdx.sbom +curl -LO https://github.com/edgelesssys/constellation/releases/download/v2.2.0/constellation.spdx.sbom.sig +cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig constellation.spdx.sbom +``` + +### Container Images + +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. + +As a consumer, use cosign to download and verify the SBOM: + +```bash +# Verify and download the attestation statement +cosign verify-attestation ghcr.io/edgelesssys/constellation/verification-service@v2.2.0 --type 'https://cyclonedx.org/bom' --key cosign.pub --output-file verification-service.att.json +# Extract SBOM from attestation statement +jq -r .payload verification-service.att.json | base64 -d > verification-service.cyclonedx.sbom +``` + +A successful verification should result in similar output: + +```shell-session +$ cosign verify-attestation ghcr.io/edgelesssys/constellation/verification-service@v2.2.0 --type 'https://cyclonedx.org/bom' --key cosign.pub --output-file verification-service.sbom + +Verification for ghcr.io/edgelesssys/constellation/verification-service@v2.2.0 -- +The following checks were performed on each of these signatures: + - The cosign claims were validated + - The signatures were verified against the specified public key +$ jq -r .payload verification-service.sbom | base64 -d > verification-service.cyclonedx.sbom +``` + +:::note + +This example considers only the `verification-service`. The same approach works for all containers in the [Constellation container registry](https://github.com/orgs/edgelesssys/packages?repo_name=constellation). + +::: + + + +## Vulnerability scanning + +You can use a plethora of tools to consume SBOMs. This section provides suggestions for tools that are popular and known to produce reliable results, but any tool that consumes [SPDX](https://spdx.dev/) or [CycloneDX](https://cyclonedx.org/) files should work. + +Syft is able to [convert between the two formats](https://github.com/anchore/syft#format-conversion-experimental) in case you require a specific type. + +### Grype + +[Grype](https://github.com/anchore/grype) is a CLI tool that lends itself well for integration into CI/CD systems or local developer machines. It's also able to consume the signed attestation statement directly and does the verification in one go. + +```bash +grype att:verification-service.sbom --key cosign.pub --add-cpes-if-none -q +``` + +### Dependency Track + +[Dependency Track](https://dependencytrack.org/) is one of the oldest and most mature solutions when it comes to managing software inventory and vulnerabilities. Once imported, it continuously scans SBOMs for new vulnerabilities. It supports the CycloneDX format and provides direct guidance on how to comply with [U.S. Executive Order 14028](https://docs.dependencytrack.org/usage/executive-order-14028/). diff --git a/docs/versioned_docs/version-2.19/workflows/scale.md b/docs/versioned_docs/version-2.19/workflows/scale.md new file mode 100644 index 000000000..28f19e3f1 --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/scale.md @@ -0,0 +1,122 @@ +# Scale your cluster + +Constellation provides all features of a Kubernetes cluster including scaling and autoscaling. + +## Worker node scaling + +### Autoscaling + +Constellation comes with autoscaling disabled by default. To enable autoscaling, find the scaling group of +worker nodes: + +```bash +kubectl get scalinggroups -o json | yq '.items | .[] | select(.spec.role == "Worker") | [{"name": .metadata.name, "nodeGoupName": .spec.nodeGroupName}]' +``` + +This will output a list of scaling groups with the corresponding cloud provider name (`name`) and the cloud provider agnostic name of the node group (`nodeGroupName`). + +Then, patch the `autoscaling` field of the scaling group resource with the desired `name` to `true`: + +```bash +# Replace with the name of the scaling group you want to enable autoscaling for +worker_group= +kubectl patch scalinggroups $worker_group --patch '{"spec":{"autoscaling": true}}' --type='merge' +kubectl get scalinggroup $worker_group -o jsonpath='{.spec}' | yq -P +``` + +The cluster autoscaler now automatically provisions additional worker nodes so that all pods have a place to run. +You can configure the minimum and maximum number of worker nodes in the scaling group by patching the `min` or +`max` fields of the scaling group resource: + +```bash +kubectl patch scalinggroups $worker_group --patch '{"spec":{"max": 5}}' --type='merge' +kubectl get scalinggroup $worker_group -o jsonpath='{.spec}' | yq -P +``` + +The cluster autoscaler will now never provision more than 5 worker nodes. + +If you want to see the autoscaling in action, try to add a deployment with a lot of replicas, like the +following Nginx deployment. The number of replicas needed to trigger the autoscaling depends on the size of +and count of your worker nodes. Wait for the rollout of the deployment to finish and compare the number of +worker nodes before and after the deployment: + +```bash +kubectl create deployment nginx --image=nginx --replicas 150 +kubectl -n kube-system get nodes +kubectl rollout status deployment nginx +kubectl -n kube-system get nodes +``` + +### Manual scaling + +Alternatively, you can manually scale your cluster up or down: + + + + +1. Go to Auto Scaling Groups and select the worker ASG to scale up. +2. Click **Edit** +3. Set the new (increased) **Desired capacity** and **Update**. + + + + +1. Find your Constellation resource group. +2. Select the `scale-set-workers`. +3. Go to **settings** and **scaling**. +4. Set the new **instance count** and **save**. + + + + +1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). +2. **Edit** the **worker** instance group. +3. Set the new **number of instances** and **save**. + + + + +Dynamic cluster scaling isn't yet supported for STACKIT. +Support will be introduced in one of the upcoming releases. + + + + +## Control-plane node scaling + +Control-plane nodes can **only be scaled manually and only scaled up**! + +To increase the number of control-plane nodes, follow these steps: + + + + +1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. +2. Click **Edit** +3. Set the new (increased) **Desired capacity** and **Update**. + + + + +1. Find your Constellation resource group. +2. Select the `scale-set-controlplanes`. +3. Go to **settings** and **scaling**. +4. Set the new (increased) **instance count** and **save**. + + + + +1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). +2. **Edit** the **control-plane** instance group. +3. Set the new (increased) **number of instances** and **save**. + + + + +Dynamic cluster scaling isn't yet supported for STACKIT. +Support will be introduced in one of the upcoming releases. + + + + +If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.19/workflows/storage.md b/docs/versioned_docs/version-2.19/workflows/storage.md new file mode 100644 index 000000000..a5c52be90 --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/storage.md @@ -0,0 +1,281 @@ +# Use persistent storage + +Persistent storage in Kubernetes requires cloud-specific configuration. +For abstraction of container storage, Kubernetes offers [volumes](https://kubernetes.io/docs/concepts/storage/volumes/), +allowing users to mount storage solutions directly into containers. +The [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) is the standard interface for exposing arbitrary block and file storage systems into containers in Kubernetes. +Cloud service providers (CSPs) offer their own CSI-based solutions for cloud storage. + +## Confidential storage + +Most cloud storage solutions support encryption, such as [GCE Persistent Disks (PD)](https://cloud.google.com/kubernetes-engine/docs/how-to/using-cmek). +Constellation supports the available CSI-based storage options for Kubernetes engines in AWS, Azure, GCP, and STACKIT. +However, their encryption takes place in the storage backend and is managed by the CSP. +Thus, using the default CSI drivers for these storage types means trusting the CSP with your persistent data. + +To address this, Constellation provides CSI drivers for AWS EBS, Azure Disk, GCE PD, and OpenStack Cinder, offering [encryption on the node level](../architecture/keys.md#storage-encryption). They enable transparent encryption for persistent volumes without needing to trust the cloud backend. Plaintext data never leaves the confidential VM context, offering you confidential storage. + +For more details see [encrypted persistent storage](../architecture/encrypted-storage.md). + +## CSI drivers + +Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. + + + + +**Constellation CSI driver for AWS Elastic Block Store** +Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. +Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. + + + + +**Constellation CSI driver for Azure Disk**: +Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. +See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. +Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. + + + + +**Constellation CSI driver for GCP Persistent Disk**: +Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. +Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. + + + + +**Constellation CSI driver for STACKIT / OpenStack Cinder** +Mount [Cinder](https://docs.openstack.org/cinder/latest/) block storage volumes into your Constellation cluster. +Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-cloud-provider-openstack) for more information. + + + + +Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. + +## Installation + +The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. +If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. + + + + +AWS comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [SSDs of `gp3` type](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-volume-types.html) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [SSDs of `gp3` type](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-volume-types.html) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +Azure comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [Standard SSDs](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#standard-ssds) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [Premium SSDs](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#premium-ssds) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +GCP comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [standard persistent disks](https://cloud.google.com/compute/docs/disks#pdspecs) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [performance (SSD) persistent disks](https://cloud.google.com/compute/docs/disks#pdspecs) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +STACKIT comes with two storage classes by default. + +* `encrypted-rwo` + * Uses [disks of `storage_premium_perf1` type](https://docs.stackit.cloud/stackit/en/service-plans-blockstorage-75137974.html) + * ext-4 filesystem + * Encryption of all data written to disk +* `integrity-encrypted-rwo` + * Uses [disks of `storage_premium_perf1` type](https://docs.stackit.cloud/stackit/en/service-plans-blockstorage-75137974.html) + * ext-4 filesystem + * Encryption of all data written to disk + * Integrity protection of data written to disk + +For more information on encryption algorithms and key sizes, refer to [cryptographic algorithms](../architecture/encrypted-storage.md#cryptographic-algorithms). + +:::info + +The default storage class is set to `encrypted-rwo` for performance reasons. +If you want integrity-protected storage, set the `storageClassName` parameter of your persistent volume claim to `integrity-encrypted-rwo`. + +Alternatively, you can create your own storage class with integrity protection enabled by adding `csi.storage.k8s.io/fstype: ext4-integrity` to the class `parameters`. +Or use another filesystem by specifying another file system type with the suffix `-integrity`, e.g., `csi.storage.k8s.io/fstype: xfs-integrity`. + +Note that volume expansion isn't supported for integrity-protected disks. + +::: + + + + +1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) + + A [persistent volume claim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) is a request for storage with certain properties. + It can refer to a storage class. + The following creates a persistent volume claim, requesting 20 GB of storage via the `encrypted-rwo` storage class: + + ```bash + cat < + +--- + +You can terminate your cluster using the CLI. For this, you need the Terraform state directory named [`constellation-terraform`](../reference/terraform.md) in the current directory. + +:::danger + +All ephemeral storage and state of your cluster will be lost. Make sure any data is safely stored in persistent storage. Constellation can recreate your cluster and the associated encryption keys, but won't backup your application data automatically. + +::: + + + +Terminate the cluster by running: + +```bash +constellation terminate +``` + +Or without confirmation (e.g., for automation purposes): + +```bash +constellation terminate --yes +``` + +This deletes all resources created by Constellation in your cloud environment. +All local files created by the `apply` command are deleted as well, except for `constellation-mastersecret.json` and the configuration file. + +:::caution + +Termination can fail if additional resources have been created that depend on the ones managed by Constellation. In this case, you need to delete these additional +resources manually. Just run the `terminate` command again afterward to continue the termination process of the cluster. + +::: + + + +Terminate the cluster by running: + +```bash +terraform destroy +``` + +Delete all files that are no longer needed: + +```bash +rm constellation-state.yaml constellation-admin.conf +``` + +Only the `constellation-mastersecret.json` and the configuration file remain. + + + diff --git a/docs/versioned_docs/version-2.19/workflows/terraform-provider.md b/docs/versioned_docs/version-2.19/workflows/terraform-provider.md new file mode 100644 index 000000000..c7a795d3f --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/terraform-provider.md @@ -0,0 +1,140 @@ +# Use the Terraform provider + +The Constellation Terraform provider allows to manage the full lifecycle of a Constellation cluster (namely creation, upgrades, and deletion) via Terraform. +The provider is available through the [Terraform registry](https://registry.terraform.io/providers/edgelesssys/constellation/latest) and is released in lock-step with Constellation releases. + +## Prerequisites + +- a Linux / Mac operating system (ARM64/AMD64) +- a Terraform installation of version `v1.4.4` or above + +## Quick setup + +This example shows how to set up a Constellation cluster with the reference IAM and infrastructure setup. This setup is also used when creating a Constellation cluster through the Constellation CLI. You can either consume the IAM / infrastructure modules through a remote source (recommended) or local files. The latter requires downloading the infrastructure and IAM modules for the corresponding CSP from `terraform-modules.zip` on the [Constellation release page](https://github.com/edgelesssys/constellation/releases/latest) and placing them in the Terraform workspace directory. + +1. Create a directory (workspace) for your Constellation cluster. + + ```bash + mkdir constellation-workspace + cd constellation-workspace + ``` + +2. Use one of the [example configurations for using the Constellation Terraform provider](https://github.com/edgelesssys/constellation/tree/main/terraform-provider-constellation/examples/full) or create a `main.tf` file and fill it with the resources you want to create. The [Constellation Terraform provider documentation](https://registry.terraform.io/providers/edgelesssys/constellation/latest) offers thorough documentation on the resources and their attributes. +3. Initialize and apply the Terraform configuration. + + + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + +:::info +On SEV-SNP, you need to manually patch the policy of the MAA provider before creating the Constellation cluster, as this feature isn't available in Azure's Terraform provider yet. The Constellation CLI provides a utility for patching, but you can also do it manually. + + ```bash + terraform init + terraform apply -target module.azure_iam # adjust resource path if not using the example configuration + terraform apply -target module.azure_infrastructure # adjust resource path if not using the example configuration + constellation maa-patch $(terraform output -raw maa_url) # adjust output path / input if not using the example configuration or manually patch the resource + terraform apply -target constellation_cluster.azure_example # adjust resource path if not using the example configuration + ``` + + Use the following policy if manually performing the patch. + + ``` + version= 1.0; + authorizationrules + { + [type=="x-ms-azurevm-default-securebootkeysvalidated", value==false] => deny(); + [type=="x-ms-azurevm-debuggersdisabled", value==false] => deny(); + // The line below was edited to use the MAA provider within Constellation. Do not edit manually. + //[type=="secureboot", value==false] => deny(); + [type=="x-ms-azurevm-signingdisabled", value==false] => deny(); + [type=="x-ms-azurevm-dbvalidated", value==false] => deny(); + [type=="x-ms-azurevm-dbxvalidated", value==false] => deny(); + => permit(); + }; + issuancerules + { + }; + ``` + +::: + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + Initialize the providers and apply the configuration. + + ```bash + terraform init + terraform apply + ``` + + Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios. + + + +4. Connect to the cluster. + + ```bash + terraform output -raw kubeconfig > constellation-admin.conf + export KUBECONFIG=$(realpath constellation-admin.conf) + ``` + +## Bringing your own infrastructure + +Instead of using the example infrastructure used in the [quick setup](#quick-setup), you can also provide your own infrastructure. +If you need a starting point for a custom infrastructure setup, you can download the infrastructure / IAM Terraform modules for the respective CSP from the Constellation [GitHub releases](https://github.com/edgelesssys/constellation/releases). You can modify and extend the modules per your requirements, while keeping the basic functionality intact. +The module contains: + +- `{csp}`: cloud resources the cluster runs on +- `iam/{csp}`: IAM resources used within the cluster + +When upgrading your cluster, make sure to check the Constellation release notes for potential breaking changes in the reference infrastructure / IAM modules that need to be considered. + +## Cluster upgrades + +:::tip +Also see the [general documentation on cluster upgrades](./upgrade.md). +::: + +The steps for applying the upgrade are as follows: + +1. Update the version constraint of the Constellation Terraform provider in the `required_providers` block in your Terraform configuration. +2. If you explicitly set any of the version attributes of the provider's resources and data sources (e.g. `image_version` or `constellation_microservice_version`), make sure to update them too. Refer to Constellation's [version support policy](https://github.com/edgelesssys/constellation/blob/main/dev-docs/workflows/versions-support.md) for more information on how each Constellation version and its dependencies are supported. +3. Update the IAM / infrastructure configuration. + - For [remote addresses as module sources](https://developer.hashicorp.com/terraform/language/modules/sources#fetching-archives-over-http), update the version number inside the address of the `source` field of the infrastructure / IAM module to the target version. + - For [local paths as module sources](https://developer.hashicorp.com/terraform/language/modules/sources#local-paths) or when [providing your own infrastructure](#bringing-your-own-infrastructure), see the changes made in the reference modules since the upgrade's origin version and adjust your infrastructure / IAM configuration accordingly. +4. Upgrade the Terraform module and provider dependencies and apply the targeted configuration. + +```bash + terraform init -upgrade + terraform apply +``` diff --git a/docs/versioned_docs/version-2.19/workflows/troubleshooting.md b/docs/versioned_docs/version-2.19/workflows/troubleshooting.md new file mode 100644 index 000000000..195bce1cc --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/troubleshooting.md @@ -0,0 +1,151 @@ +# Troubleshooting + +This section aids you in finding problems when working with Constellation. + +## Common issues + +### Issues with creating new clusters + +When you create a new cluster, you should always use the [latest release](https://github.com/edgelesssys/constellation/releases/latest). +If something doesn't work, check out the [known issues](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22). + +### Azure: Resource Providers can't be registered + +On Azure, you may receive the following error when running `apply` or `terminate` with limited IAM permissions: + +```shell-session +Error: Error ensuring Resource Providers are registered. + +Terraform automatically attempts to register the Resource Providers it supports to +ensure it's able to provision resources. + +If you don't have permission to register Resource Providers you may wish to use the +"skip_provider_registration" flag in the Provider block to disable this functionality. + +[...] +``` + +To continue, please ensure that the [required resource providers](../getting-started/install.md#required-permissions) have been registered in your subscription by your administrator. + +Afterward, set `ARM_SKIP_PROVIDER_REGISTRATION=true` as an environment variable and either run `apply` or `terminate` again. +For example: + +```bash +ARM_SKIP_PROVIDER_REGISTRATION=true constellation apply +``` + +Or alternatively, for `terminate`: + +```bash +ARM_SKIP_PROVIDER_REGISTRATION=true constellation terminate +``` + +### Azure: Can't update attestation policy + +On Azure, you may receive the following error when running `apply` from within an Azure environment, e.g., an Azure VM: + +```shell-session +An error occurred: patching policies: updating attestation policy: unexpected status code: 403 Forbidden +``` + +The problem occurs because the Azure SDK we use internally attempts to [authenticate towards the Azure API with the managed identity of your current environment instead of the Azure CLI token](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential). + +We decided not to deviate from this behavior and comply with the ordering of credentials. + +A solution is to add the [required permissions](../getting-started/install.md#required-permissions) to the managed identity of your environment. For example, the managed identity of your Azure VM, instead of the account that you've authenticated with in the Azure CLI. + +If your setup requires a change in the ordering of credentials, please open an issue and explain your desired behavior. + + + +### Nodes fail to join with error `untrusted measurement value` + +This error indicates that a node's [attestation statement](../architecture/attestation.md) contains measurements that don't match the trusted values expected by the [JoinService](../architecture/microservices.md#joinservice). +This may for example happen if the cloud provider updates the VM's firmware such that it influences the [runtime measurements](../architecture/attestation.md#runtime-measurements) in an unforeseen way. +A failed upgrade due to an erroneous attestation config can also cause this error. +You can change the expected measurements to resolve the failure. + +:::caution + +Attestation and trusted measurements are crucial for the security of your cluster. +Be extra careful when manually changing these settings. +When in doubt, check if the encountered [issue is known](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22) or [contact support](https://github.com/edgelesssys/constellation#support). + +::: + +:::tip + +During an upgrade with modified attestation config, a backup of the current configuration is stored in the `join-config` config map in the `kube-system` namespace under the `attestationConfig_backup` key. To restore the old attestation config after a failed upgrade, replace the value of `attestationConfig` with the value from `attestationConfig_backup`: + +```bash +kubectl patch configmaps -n kube-system join-config -p "{\"data\":{\"attestationConfig\":\"$(kubectl get configmaps -n kube-system join-config -o "jsonpath={.data.attestationConfig_backup}")\"}}" +``` + +::: + +You can use the `apply` command to change measurements of a running cluster: + +1. Modify the `measurements` key in your local `constellation-conf.yaml` to the expected values. +2. Run `constellation apply`. + +Keep in mind that running `apply` also applies any version changes from your config to the cluster. + +You can run these commands to learn about the versions currently configured in the cluster: + +- Kubernetes API server version: `kubectl get nodeversion constellation-version -o json -n kube-system | jq .spec.kubernetesClusterVersion` +- image version: `kubectl get nodeversion constellation-version -o json -n kube-system | jq .spec.imageVersion` +- microservices versions: `helm list --filter 'constellation-services' -n kube-system` + +### Upgrading Kubernetes resources fails + +Constellation manages its Kubernetes resources using Helm. +When applying an upgrade, the charts that are about to be installed, and a values override file `overrides.yaml`, +are saved to disk in your current workspace under `constellation-upgrade/upgrade-/helm-charts/`. +If upgrading the charts using the Constellation CLI fails, you can review these charts and try to manually apply the upgrade. + +:::caution + +Changing and manually applying the charts may destroy cluster resources and can lead to broken Constellation deployments. +Proceed with caution and when in doubt, +check if the encountered [issue is known](https://github.com/edgelesssys/constellation/issues?q=is%3Aopen+is%3Aissue+label%3A%22known+issue%22) or [contact support](https://github.com/edgelesssys/constellation#support). + +::: + +## Diagnosing issues + +### Logs + +To get started on diagnosing issues with Constellation, it's often helpful to collect logs from nodes, pods, or other resources in the cluster. Most logs are available through Kubernetes' standard +[logging interfaces](https://kubernetes.io/docs/concepts/cluster-administration/logging/). + +To debug issues occurring at boot time of the nodes, you can use the serial console interface of the CSP while the machine boots to get a read-only view of the boot logs. + +Apart from that, Constellation also offers further [observability integrations](../architecture/observability.md). + +### Node shell access + +Debugging via a shell on a node is [directly supported by Kubernetes](https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/#node-shell-session). + +1. Figure out which node to connect to: + + ```bash + kubectl get nodes + # or to see more information, such as IPs: + kubectl get nodes -o wide + ``` + +2. Connect to the node: + + ```bash + kubectl debug node/constell-worker-xksa0-000000 -it --image=busybox + ``` + + You will be presented with a prompt. + + The nodes file system is mounted at `/host`. + +3. Once finished, clean up the debug pod: + + ```bash + kubectl delete pod node-debugger-constell-worker-xksa0-000000-bjthj + ``` diff --git a/docs/versioned_docs/version-2.19/workflows/trusted-launch.md b/docs/versioned_docs/version-2.19/workflows/trusted-launch.md new file mode 100644 index 000000000..d6d01d8eb --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/trusted-launch.md @@ -0,0 +1,54 @@ +# Use Azure trusted launch VMs + +Constellation also supports [trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch) on Microsoft Azure. Trusted launch VMs don't offer the same level of security as Confidential VMs, but are available in more regions and in larger quantities. The main difference between trusted launch VMs and normal VMs is that the former offer vTPM-based remote attestation. When used with trusted launch VMs, Constellation relies on vTPM-based remote attestation to verify nodes. + +:::caution + +Trusted launch VMs don't provide runtime encryption and don't keep the cloud service provider (CSP) out of your trusted computing base. + +::: + +Constellation supports trusted launch VMs with instance types `Standard_D*_v4` and `Standard_E*_v4`. Run `constellation config instance-types` for a list of all supported instance types. + +## VM images + +Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. + +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. + +After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. +You can use a script to do this: + +```bash +wget https://raw.githubusercontent.com/edgelesssys/constellation/main/hack/importAzure.sh +chmod +x importAzure.sh +AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_IMAGE_FILE=./constellation.img ./importAzure.sh +``` + +The script creates the following resources: + +1. A new image gallery with the default name `constellation-import` +2. A new image definition with the default name `constellation` +3. The actual image with the provided version. In this case `2.2.0` + +Once the import is completed, use the `ID` of the image version in your `constellation-conf.yaml` for the `image` field. Set `confidentialVM` to `false`. + +Fetch the image measurements: + +```bash +IMAGE_VERSION=2.2.0 +URL=https://public-edgeless-constellation.s3.us-east-2.amazonaws.com//communitygalleries/constellationcvm-b3782fa0-0df7-4f2f-963e-fc7fc42663df/images/constellation/versions/$IMAGE_VERSION/measurements.yaml +constellation config fetch-measurements -u$URL -s$URL.sig +``` + +:::info + +The [`constellation apply`](create.md) command will issue a warning because manually imported images aren't recognized as production grade images: + +```shell-session +Configured image doesn't look like a released production image. Double check image before deploying to production. +``` + +Please ignore this warning. + +::: diff --git a/docs/versioned_docs/version-2.19/workflows/upgrade.md b/docs/versioned_docs/version-2.19/workflows/upgrade.md new file mode 100644 index 000000000..3db2ecad6 --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/upgrade.md @@ -0,0 +1,110 @@ +# Upgrade your cluster + +Constellation provides an easy way to upgrade all components of your cluster, without disrupting its availability. +Specifically, you can upgrade the Kubernetes version, the nodes' image, and the Constellation microservices. +You configure the desired versions in your local Constellation configuration and trigger upgrades with the `apply` command. +To learn about available versions you use the `upgrade check` command. +Which versions are available depends on the CLI version you are using. + +## Update the CLI + +Each CLI comes with a set of supported microservice and Kubernetes versions. +Most importantly, a given CLI version can only upgrade a cluster of the previous minor version, but not older ones. +This means that you have to upgrade your CLI and cluster one minor version at a time. + +For example, if you are currently on CLI version v2.6 and the latest version is v2.8, you should + +* upgrade the CLI to v2.7, +* upgrade the cluster to v2.7, +* and only then continue upgrading the CLI (and the cluster) to v2.8 after. + +Also note that if your current Kubernetes version isn't supported by the next CLI version, use your current CLI to upgrade to a newer Kubernetes version first. + +To learn which Kubernetes versions are supported by a particular CLI, run [constellation config kubernetes-versions](../reference/cli.md#constellation-config-kubernetes-versions). + +## Migrate the configuration + +The Constellation configuration file is located in the file `constellation-conf.yaml` in your workspace. +Refer to the [migration reference](../reference/migration.md) to check if you need to update fields in your configuration file. +Use [`constellation config migrate`](../reference/cli.md#constellation-config-migrate) to automatically update an old config file to a new format. + +## Check for upgrades + +To learn which versions the current CLI can upgrade to and what's installed in your cluster, run: + +```bash +# Show possible upgrades +constellation upgrade check + +# Show possible upgrades and write them to config file +constellation upgrade check --update-config +``` + +You can either enter the reported target versions into your config manually or run the above command with the `--update-config` flag. +When using this flag, the `kubernetesVersion`, `image`, `microserviceVersion`, and `attestation` fields are overwritten with the smallest available upgrade. + +## Apply the upgrade + +Once you updated your config with the desired versions, you can trigger the upgrade with this command: + +```bash +constellation apply +``` + +Microservice upgrades will be finished within a few minutes, depending on the cluster size. +If you are interested, you can monitor pods restarting in the `kube-system` namespace with your tool of choice. + +Image and Kubernetes upgrades take longer. +For each node in your cluster, a new node has to be created and joined. +The process usually takes up to ten minutes per node. + +When applying an upgrade, the Helm charts for the upgrade as well as backup files of Constellation-managed Custom Resource Definitions, Custom Resources, and Terraform state are created. +You can use the Terraform state backup to restore previous resources in case an upgrade misconfigured or erroneously deleted a resource. +You can use the Custom Resource (Definition) backup files to restore Custom Resources and Definitions manually (e.g., via `kubectl apply`) if the automatic migration of those resources fails. +You can use the Helm charts to manually apply upgrades to the Kubernetes resources, should an upgrade fail. + +:::note + +For advanced users: the upgrade consists of several phases that can be individually skipped through the `--skip-phases` flag. +The phases are `infrastracture` for the cloud resource management through Terraform, `helm` for the chart management of the microservices, `image` for OS image upgrades, and `k8s` for Kubernetes version upgrades. + +::: + +## Check the status + +Upgrades are asynchronous operations. +After you run `apply`, it will take a while until the upgrade has completed. +To understand if an upgrade is finished, you can run: + +```bash +constellation status +``` + +This command displays the following information: + +* The installed services and their versions +* The image and Kubernetes version the cluster is expecting on each node +* How many nodes are up to date + +Here's an example output: + +```shell-session +Target versions: + Image: v2.6.0 + Kubernetes: v1.25.8 +Service versions: + Cilium: v1.12.1 + cert-manager: v1.10.0 + constellation-operators: v2.6.0 + constellation-services: v2.6.0 +Cluster status: Some node versions are out of date + Image: 23/25 + Kubernetes: 25/25 +``` + +This output indicates that the cluster is running Kubernetes version `1.25.8`, and all nodes have the appropriate binaries installed. +23 out of 25 nodes have already upgraded to the targeted image version of `2.6.0`, while two are still in progress. + +## Apply further upgrades + +After the upgrade is finished, you can run `constellation upgrade check` again to see if there are more upgrades available. If so, repeat the process. diff --git a/docs/versioned_docs/version-2.19/workflows/verify-cli.md b/docs/versioned_docs/version-2.19/workflows/verify-cli.md new file mode 100644 index 000000000..e33569d37 --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/verify-cli.md @@ -0,0 +1,129 @@ +# Verify the CLI + +:::info +This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. +::: + + + +--- + +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. + +:::note +The public key for Edgeless Systems' long-term code-signing key is: + +``` +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEf8F1hpmwE+YCFXzjGtaQcrL6XZVT +JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== +-----END PUBLIC KEY----- +``` + +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +::: + +The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. + +You should always ensure that (1) your CLI executable was signed with the private key corresponding to the above public key and that (2) there is a corresponding entry in the Rekor transparency log. Both can be done as described in the following. + +:::info +You don't need to verify the Constellation node images. This is done automatically by your CLI and the rest of Constellation. +::: + +## Verify the signature + +:::info +This guide assumes Linux on an amd64 processor. The exact steps for other platforms differ slightly. +::: + +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: + +```shell-session +$ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 + +Verified OK +``` + +The above performs an offline verification of the provided public key, signature, and executable. To also verify that a corresponding entry exists in the public Rekor transparency log, add the variable `COSIGN_EXPERIMENTAL=1`: + +```shell-session +$ COSIGN_EXPERIMENTAL=1 cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 + +tlog entry verified with uuid: afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 index: 3477047 +Verified OK +``` + +🏁 You now know that your CLI executable was officially released and signed by Edgeless Systems. + +### Optional: Manually inspect the transparency log + +To further inspect the public Rekor transparency log, [install the Rekor CLI](https://docs.sigstore.dev/logging/installation). A search for the CLI executable should give a single UUID. (Note that this UUID contains the UUID from the previous `cosign` command.) + +```shell-session +$ rekor-cli search --artifact constellation-linux-amd64 + +Found matching entries (listed by UUID): +362f8ecba72f4326afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 +``` + +With this UUID you can get the full entry from the transparency log: + +```shell-session +$ rekor-cli get --uuid=362f8ecba72f4326afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 + +LogID: c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d +Index: 3477047 +IntegratedTime: 2022-09-12T22:28:16Z +UUID: afaba7f6635b3e058888692841848e5514357315be9528474b23f5dcccb82b13 +Body: { + "HashedRekordObj": { + "data": { + "hash": { + "algorithm": "sha256", + "value": "40e137b9b9b8204d672642fd1e181c6d5ccb50cfc5cc7fcbb06a8c2c78f44aff" + } + }, + "signature": { + "content": "MEUCIQCSER3mGj+j5Pr2kOXTlCIHQC3gT30I7qkLr9Awt6eUUQIgcLUKRIlY50UN8JGwVeNgkBZyYD8HMxwC/LFRWoMn180=", + "publicKey": { + "content": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFZjhGMWhwbXdFK1lDRlh6akd0YVFjckw2WFpWVApKbUVlNWlTTHZHMVN5UVNBZXc3V2RNS0Y2bzl0OGUyVEZ1Q2t6bE9oaGx3czJPSFdiaUZabkZXQ0Z3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==" + } + } + } +} +``` + +The field `publicKey` should contain Edgeless Systems' public key in Base64 encoding. + +You can get an exhaustive list of artifact signatures issued by Edgeless Systems via the following command: + +```bash +rekor-cli search --public-key https://edgeless.systems/es.pub --pki-format x509 +``` + +Edgeless Systems monitors this list to detect potential unauthorized use of its private key. + +## Verify the provenance + +Provenance attests that a software artifact was produced by a specific repository and build system invocation. For more information on provenance visit [slsa.dev](https://slsa.dev/provenance/v0.2) and learn about the [adoption of SLSA for Constellation](../reference/slsa.md). + +Just as checking its signature proves that the CLI hasn't been manipulated, checking the provenance proves that the artifact was produced by the expected build process and hasn't been tampered with. + +To verify the provenance, first install the [slsa-verifier](https://github.com/slsa-framework/slsa-verifier). Then make sure you have the provenance file (`constellation.intoto.jsonl`) and Constellation CLI downloaded. Both are available on the [GitHub release page](https://github.com/edgelesssys/constellation/releases). + +:::info +The same provenance file is valid for all Constellation CLI executables of a given version independent of the target platform. +::: + +Use the verifier to perform the check: + +```shell-session +$ slsa-verifier verify-artifact constellation-linux-amd64 \ + --provenance-path constellation.intoto.jsonl \ + --source-uri github.com/edgelesssys/constellation + +Verified signature against tlog entry index 7771317 at URL: https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77af2c04c8b4ae0d5bc5... +Verified build using builder https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v1.2.2 at commit 18e9924b416323c37b9cdfd6cc728de8a947424a +PASSED: Verified SLSA provenance +``` diff --git a/docs/versioned_docs/version-2.19/workflows/verify-cluster.md b/docs/versioned_docs/version-2.19/workflows/verify-cluster.md new file mode 100644 index 000000000..b6595ebf2 --- /dev/null +++ b/docs/versioned_docs/version-2.19/workflows/verify-cluster.md @@ -0,0 +1,97 @@ +# Verify your cluster + +Constellation's [attestation feature](../architecture/attestation.md) allows you, or a third party, to verify the integrity and confidentiality of your Constellation cluster. + +## Fetch measurements + +To verify the integrity of Constellation you need trusted measurements to verify against. For each node image released by Edgeless Systems, there are signed measurements, which you can download using the CLI: + +```bash +constellation config fetch-measurements +``` + +This command performs the following steps: + +1. Download the signed measurements for the configured image. By default, this will use Edgeless Systems' public measurement registry. +2. Verify the signature of the measurements. This will use Edgeless Systems' [public key](https://edgeless.systems/es.pub). +3. Write measurements into configuration file. + +The configuration file then contains a list of `measurements` similar to the following: + +```yaml +# ... +measurements: + 0: + expected: "0f35c214608d93c7a6e68ae7359b4a8be5a0e99eea9107ece427c4dea4e439cf" + warnOnly: false + 4: + expected: "02c7a67c01ec70ffaf23d73a12f749ab150a8ac6dc529bda2fe1096a98bf42ea" + warnOnly: false + 5: + expected: "e6949026b72e5045706cd1318889b3874480f7a3f7c5c590912391a2d15e6975" + warnOnly: true + 8: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false + 9: + expected: "f0a6e8601b00e2fdc57195686cd4ef45eb43a556ac1209b8e25d993213d68384" + warnOnly: false + 11: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false + 12: + expected: "da99eb6cf7c7fbb692067c87fd5ca0b7117dc293578e4fea41f95d3d3d6af5e2" + warnOnly: false + 13: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false + 14: + expected: "d7c4cc7ff7933022f013e03bdee875b91720b5b86cf1753cad830f95e791926f" + warnOnly: true + 15: + expected: "0000000000000000000000000000000000000000000000000000000000000000" + warnOnly: false +# ... +``` + +Each entry specifies the expected value of the Constellation node, and whether the measurement should be enforced (`warnOnly: false`), or only a warning should be logged (`warnOnly: true`). +By default, the subset of the [available measurements](../architecture/attestation.md#runtime-measurements) that can be locally reproduced and verified is enforced. + +During attestation, the validating side (CLI or [join service](../architecture/microservices.md#joinservice)) compares each measurement reported by the issuing side (first node or joining node) individually. +For mismatching measurements that have set `warnOnly` to `true` only a warning is emitted. +For mismatching measurements that have set `warnOnly` to `false` an error is emitted and attestation fails. +If attestation fails for a new node, it isn't permitted to join the cluster. + +## The *verify* command + +:::note +The steps below are purely optional. They're automatically executed by `constellation apply` when you initialize your cluster. The `constellation verify` command mostly has an illustrative purpose. +::: + +The `verify` command obtains and verifies an attestation statement from a running Constellation cluster. + +```bash +constellation verify [--cluster-id ...] +``` + +From the attestation statement, the command verifies the following properties: + +* The cluster is using the correct Confidential VM (CVM) type. +* Inside the CVMs, the correct node images are running. The node images are identified through the measurements obtained in the previous step. +* The unique ID of the cluster matches the one from your `constellation-state.yaml` file or passed in via `--cluster-id`. + +Once the above properties are verified, you know that you are talking to the right Constellation cluster and it's in a good and trustworthy shape. + +### Custom arguments + +The `verify` command also allows you to verify any Constellation deployment that you have network access to. For this you need the following: + +* The IP address of a running Constellation cluster's [VerificationService](../architecture/microservices.md#verificationservice). The `VerificationService` is exposed via a `NodePort` service using the external IP address of your cluster. Run `kubectl get nodes -o wide` and look for `EXTERNAL-IP`. +* The cluster's *clusterID*. See [cluster identity](../architecture/keys.md#cluster-identity) for more details. +* A `constellation-conf.yaml` file with the expected measurements of the cluster in your working directory. + +For example: + +```shell-session +constellation verify -e 192.0.2.1 --cluster-id Q29uc3RlbGxhdGlvbkRvY3VtZW50YXRpb25TZWNyZXQ= +``` diff --git a/docs/versioned_docs/version-2.2/architecture/attestation.md b/docs/versioned_docs/version-2.2/architecture/attestation.md index c70a61264..c09d0f546 100644 --- a/docs/versioned_docs/version-2.2/architecture/attestation.md +++ b/docs/versioned_docs/version-2.2/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,8 +217,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.2/getting-started/first-steps.md b/docs/versioned_docs/version-2.2/getting-started/first-steps.md index 2850176a0..3dcb4f6c5 100644 --- a/docs/versioned_docs/version-2.2/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.2/getting-started/first-steps.md @@ -11,36 +11,36 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step 1. Create the configuration file for your selected cloud provider. - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in your current working directory. 2. Fill in your cloud provider specific information. - - + + You need several resources for the cluster. You can use the following `az` script to create them: @@ -71,8 +71,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step Run `constellation config instance-types` to get the list of all supported options. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -118,8 +118,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step Run `constellation config instance-types` to get the list of all supported options. - - + + You need a service account for the cluster. You can use the following `gcloud` script to create it: @@ -142,8 +142,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines from the N2D family with a minimum of 4 vCPUs. Refer to [N2D machine series](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) or run `constellation config instance-types` to get the list of all supported options. - - + + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -171,8 +171,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step Supported are all machines from the N2D family with a minimum of 4 vCPUs. It defaults to `n2d-standard-4` (4 vCPUs, 16 GB RAM), but you can use any other VMs from the same family. Refer to [N2D machine series](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) or run `constellation config instance-types` to get the list of all supported options. - - + + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -211,8 +211,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - - + + :::info diff --git a/docs/versioned_docs/version-2.2/getting-started/install.md b/docs/versioned_docs/version-2.2/getting-started/install.md index 6bf421b16..439b734dd 100644 --- a/docs/versioned_docs/version-2.2/getting-started/install.md +++ b/docs/versioned_docs/version-2.2/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,14 +105,15 @@ If you don't have a cloud subscription, you can try [MiniConstellation](first-st ### Required permissions - - + + The following [resource providers need to be need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Compute` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` -* `microsoft.insights` + +- `Microsoft.Compute` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` +- `microsoft.insights` By default, Constellation tries to register these automatically if they haven't been registered before. @@ -124,8 +125,8 @@ You need the following permissions for your user account: If you don't have these permissions with scope *subscription*, ask your administrator to [create the service account and a resource group for your Constellation cluster](first-steps.md). Your user account needs the `Contributor` permission scoped to this resource group. - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -137,8 +138,8 @@ You need the following permissions on this project: Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -269,8 +270,8 @@ such as `PowerUserAccess`, or use the following minimal set of permissions: Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -280,8 +281,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -297,8 +298,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -321,8 +322,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -338,9 +339,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.2/overview/clouds.md b/docs/versioned_docs/version-2.2/overview/clouds.md index 745507c52..c48f23cf0 100644 --- a/docs/versioned_docs/version-2.2/overview/clouds.md +++ b/docs/versioned_docs/version-2.2/overview/clouds.md @@ -24,7 +24,7 @@ The following table summarizes the state of features for different infrastructur With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. Regarding (3), Azure provides direct access to remote-attestation statements. However, regarding (4), the standard CVMs still include closed-source firmware running in VM Privilege Level (VMPL) 0. This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.2/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.2/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.2/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.2/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.2/workflows/create.md b/docs/versioned_docs/version-2.2/workflows/create.md index d886fb347..dcb3ff285 100644 --- a/docs/versioned_docs/version-2.2/workflows/create.md +++ b/docs/versioned_docs/version-2.2/workflows/create.md @@ -19,29 +19,29 @@ This step creates the necessary resources for your cluster in your cloud environ Generate a configuration file for your cloud service provider (CSP): - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. [Fill in your CSP-specific information](../getting-started/first-steps.md#create-a-cluster) before you continue. diff --git a/docs/versioned_docs/version-2.2/workflows/recovery.md b/docs/versioned_docs/version-2.2/workflows/recovery.md index fd610fc67..0fd171036 100644 --- a/docs/versioned_docs/version-2.2/workflows/recovery.md +++ b/docs/versioned_docs/version-2.2/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.2/workflows/sbom.md b/docs/versioned_docs/version-2.2/workflows/sbom.md index ec9834b4f..e8ba25a64 100644 --- a/docs/versioned_docs/version-2.2/workflows/sbom.md +++ b/docs/versioned_docs/version-2.2/workflows/sbom.md @@ -15,7 +15,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -36,7 +36,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.2/workflows/scale.md b/docs/versioned_docs/version-2.2/workflows/scale.md index 3b7c0d479..bce045c66 100644 --- a/docs/versioned_docs/version-2.2/workflows/scale.md +++ b/docs/versioned_docs/version-2.2/workflows/scale.md @@ -48,23 +48,23 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + :::caution @@ -72,8 +72,8 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + ## Control-plane node scaling @@ -81,24 +81,24 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + :::caution @@ -106,7 +106,7 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.2/workflows/storage.md b/docs/versioned_docs/version-2.2/workflows/storage.md index 878449fa5..c322d97d1 100644 --- a/docs/versioned_docs/version-2.2/workflows/storage.md +++ b/docs/versioned_docs/version-2.2/workflows/storage.md @@ -21,14 +21,14 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as ReadWriteOnce, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. @@ -36,8 +36,8 @@ This includes support for [volume snapshots](https://cloud.google.com/kubernetes You can use them to bring a volume back to a prior state or provision new volumes. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for information about the configuration. - - + + :::caution @@ -47,8 +47,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction) or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -56,8 +56,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The following installation guide gives an overview of how to securely use CSI-based cloud storage for persistent volumes in Constellation. - - + + 1. Install the driver: @@ -67,8 +67,8 @@ The following installation guide gives an overview of how to securely use CSI-ba helm install azuredisk-csi-driver charts/edgeless --namespace kube-system ``` - - + + 1. Install the driver: @@ -77,8 +77,8 @@ The following installation guide gives an overview of how to securely use CSI-ba helm install gcp-compute-persistent-disk-csi-driver charts/ --namespace kube-system ``` - - + + :::caution @@ -88,8 +88,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + :::info @@ -160,8 +160,8 @@ The default storage class is responsible for all persistent volume claims that d The previous instructions create a storage class with encryption enabled and sets this as the default class. In case you wish to change it, follow the steps below: - - + + 1. List the storage classes in your cluster: @@ -207,8 +207,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) azuredisk.csi.confidential.cloud Delete Immediate false 1d ``` - - + + 1. List the storage classes in your cluster: @@ -254,8 +254,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) gcp.csi.confidential.cloud Delete Immediate false 1d ``` - - + + :::caution @@ -265,5 +265,5 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + diff --git a/docs/versioned_docs/version-2.2/workflows/troubleshooting.md b/docs/versioned_docs/version-2.2/workflows/troubleshooting.md index ad5e1c51b..59015efcb 100644 --- a/docs/versioned_docs/version-2.2/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.2/workflows/troubleshooting.md @@ -5,6 +5,7 @@ This section aids you in finding problems when working with Constellation. ## Azure: Resource Providers can't be registered On Azure, you may receive the following error when running `create` or `terminate` with limited IAM permissions: + ```shell-session Error: Error ensuring Resource Providers are registered. @@ -21,11 +22,13 @@ To continue, please ensure that the [required resource providers](../getting-sta Afterward, set `ARM_SKIP_PROVIDER_REGISTRATION=true` as an environment variable and either run `create` or `terminate` again. For example: + ```bash ARM_SKIP_PROVIDER_REGISTRATION=true constellation create --control-plane-nodes 1 --worker-nodes 2 -y ``` Or alternatively, for `terminate`: + ```bash ARM_SKIP_PROVIDER_REGISTRATION=true constellation terminate ``` @@ -36,8 +39,8 @@ To provide information during early stages of the node's boot process, Constella You can view these information in the follow places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -47,8 +50,8 @@ You can view these information in the follow places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -63,16 +66,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ## Connect to nodes via SSH diff --git a/docs/versioned_docs/version-2.2/workflows/trusted-launch.md b/docs/versioned_docs/version-2.2/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.2/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.2/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.2/workflows/verify-cli.md b/docs/versioned_docs/version-2.2/workflows/verify-cli.md index 0a52fedd4..52ed24d95 100644 --- a/docs/versioned_docs/version-2.2/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.2/workflows/verify-cli.md @@ -1,6 +1,6 @@ # Verify the CLI -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -12,7 +12,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -25,7 +25,7 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.3/architecture/attestation.md b/docs/versioned_docs/version-2.3/architecture/attestation.md index f335038f6..28e8e62cf 100644 --- a/docs/versioned_docs/version-2.3/architecture/attestation.md +++ b/docs/versioned_docs/version-2.3/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,8 +217,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.3/getting-started/first-steps.md b/docs/versioned_docs/version-2.3/getting-started/first-steps.md index a749ca6a9..02fbdb696 100644 --- a/docs/versioned_docs/version-2.3/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.3/getting-started/first-steps.md @@ -11,29 +11,29 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step 1. Create the configuration file for your selected cloud provider. - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in your current working directory. @@ -41,9 +41,9 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step First you need to create an [IAM configuration](../workflows/config.md#creating-an-iam-configuration). The easiest way to do this is the following CLI command: - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest @@ -57,9 +57,9 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step * `northeurope` * `westeurope` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test @@ -69,9 +69,9 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step Note that only regions offering CVMs of the `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `N2D`. - + - + ```bash constellation iam create aws --zone=eu-central-1a --prefix=constellTest @@ -88,8 +88,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + Now, fill the output values of the command into the corresponding fields of the `constellation-conf.yaml` file. diff --git a/docs/versioned_docs/version-2.3/getting-started/install.md b/docs/versioned_docs/version-2.3/getting-started/install.md index d830c7792..36d8f541a 100644 --- a/docs/versioned_docs/version-2.3/getting-started/install.md +++ b/docs/versioned_docs/version-2.3/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,14 +105,15 @@ If you don't have a cloud subscription, you can try [MiniConstellation](first-st ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Compute` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` -* `microsoft.insights` + +- `Microsoft.Compute` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` +- `microsoft.insights` By default, Constellation tries to register these automatically if they haven't been registered before. @@ -124,8 +125,8 @@ You need the following permissions for your user account: If you don't have these permissions with scope *subscription*, ask your administrator to [create the service account and a resource group for your Constellation cluster](first-steps.md). Your user account needs the `Contributor` permission scoped to this resource group. - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -137,8 +138,8 @@ You need the following permissions on this project: Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -269,8 +270,8 @@ such as `PowerUserAccess`, or use the following minimal set of permissions: Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -280,8 +281,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -297,8 +298,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -321,8 +322,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -338,9 +339,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.3/overview/clouds.md b/docs/versioned_docs/version-2.3/overview/clouds.md index 745507c52..c48f23cf0 100644 --- a/docs/versioned_docs/version-2.3/overview/clouds.md +++ b/docs/versioned_docs/version-2.3/overview/clouds.md @@ -24,7 +24,7 @@ The following table summarizes the state of features for different infrastructur With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. Regarding (3), Azure provides direct access to remote-attestation statements. However, regarding (4), the standard CVMs still include closed-source firmware running in VM Privilege Level (VMPL) 0. This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.3/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.3/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.3/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.3/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.3/workflows/config.md b/docs/versioned_docs/version-2.3/workflows/config.md index afd53812e..652e58a38 100644 --- a/docs/versioned_docs/version-2.3/workflows/config.md +++ b/docs/versioned_docs/version-2.3/workflows/config.md @@ -6,62 +6,62 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the N2D family. Refer to [N2D machine series](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) or run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all nitroTPM-enabled machines with a minimum of 4 vCPUs (`xlarge` or larger). Refer to the [list of nitroTPM-enabled instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-prerequisites.html) or run `constellation config instance-types` to get the list of all supported options. - - + + Fill the desired VM type into the **instanceType** field in the `constellation-conf.yml` file. ## Creating an IAM configuration You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session. @@ -84,8 +84,8 @@ Paste the output into the corresponding fields of the `constellation-conf.yaml` Since `clientSecretValue` is a sensitive value, you can leave it empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session. @@ -99,8 +99,8 @@ Note that only regions offering CVMs of the `N2D` series are supported. You can Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session. @@ -122,16 +122,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -175,9 +175,9 @@ The following describes the configuration fields and how you obtain the required Since this is a sensitive value, alternatively you can leave `clientSecretValue` empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -201,9 +201,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -232,9 +232,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.3/workflows/recovery.md b/docs/versioned_docs/version-2.3/workflows/recovery.md index fd610fc67..0fd171036 100644 --- a/docs/versioned_docs/version-2.3/workflows/recovery.md +++ b/docs/versioned_docs/version-2.3/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.3/workflows/sbom.md b/docs/versioned_docs/version-2.3/workflows/sbom.md index ec9834b4f..e8ba25a64 100644 --- a/docs/versioned_docs/version-2.3/workflows/sbom.md +++ b/docs/versioned_docs/version-2.3/workflows/sbom.md @@ -15,7 +15,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -36,7 +36,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.3/workflows/scale.md b/docs/versioned_docs/version-2.3/workflows/scale.md index 3b7c0d479..bce045c66 100644 --- a/docs/versioned_docs/version-2.3/workflows/scale.md +++ b/docs/versioned_docs/version-2.3/workflows/scale.md @@ -48,23 +48,23 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + :::caution @@ -72,8 +72,8 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + ## Control-plane node scaling @@ -81,24 +81,24 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + :::caution @@ -106,7 +106,7 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.3/workflows/storage.md b/docs/versioned_docs/version-2.3/workflows/storage.md index d0e5b188f..be9998676 100644 --- a/docs/versioned_docs/version-2.3/workflows/storage.md +++ b/docs/versioned_docs/version-2.3/workflows/storage.md @@ -21,14 +21,14 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as ReadWriteOnce, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. @@ -36,8 +36,8 @@ This includes support for [volume snapshots](https://cloud.google.com/kubernetes You can use them to bring a volume back to a prior state or provision new volumes. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for information about the configuration. - - + + :::caution @@ -47,8 +47,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction) or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -57,8 +57,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -86,8 +86,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -115,8 +115,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + :::caution @@ -126,8 +126,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) @@ -186,8 +186,8 @@ The default storage class is responsible for all persistent volume claims that d Constellation creates a storage class with encryption enabled and sets this as the default class. In case you wish to change it, follow the steps below: - - + + 1. List the storage classes in your cluster: @@ -233,8 +233,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) azuredisk.csi.confidential.cloud Delete Immediate false 1d ``` - - + + 1. List the storage classes in your cluster: @@ -280,8 +280,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) gcp.csi.confidential.cloud Delete Immediate false 1d ``` - - + + :::caution @@ -291,5 +291,5 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + diff --git a/docs/versioned_docs/version-2.3/workflows/troubleshooting.md b/docs/versioned_docs/version-2.3/workflows/troubleshooting.md index 3a28c9cd0..f948f5d06 100644 --- a/docs/versioned_docs/version-2.3/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.3/workflows/troubleshooting.md @@ -5,6 +5,7 @@ This section aids you in finding problems when working with Constellation. ## Azure: Resource Providers can't be registered On Azure, you may receive the following error when running `create` or `terminate` with limited IAM permissions: + ```shell-session Error: Error ensuring Resource Providers are registered. @@ -21,11 +22,13 @@ To continue, please ensure that the [required resource providers](../getting-sta Afterward, set `ARM_SKIP_PROVIDER_REGISTRATION=true` as an environment variable and either run `create` or `terminate` again. For example: + ```bash ARM_SKIP_PROVIDER_REGISTRATION=true constellation create --control-plane-nodes 1 --worker-nodes 2 -y ``` Or alternatively, for `terminate`: + ```bash ARM_SKIP_PROVIDER_REGISTRATION=true constellation terminate ``` @@ -36,8 +39,8 @@ To provide information during early stages of the node's boot process, Constella You can view these information in the follow places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -47,8 +50,8 @@ You can view these information in the follow places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -63,16 +66,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ## Connect to nodes diff --git a/docs/versioned_docs/version-2.3/workflows/trusted-launch.md b/docs/versioned_docs/version-2.3/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.3/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.3/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.3/workflows/verify-cli.md b/docs/versioned_docs/version-2.3/workflows/verify-cli.md index 4f6008cd0..01a2583d6 100644 --- a/docs/versioned_docs/version-2.3/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.3/workflows/verify-cli.md @@ -1,6 +1,6 @@ # Verify the CLI -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -12,7 +12,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -25,7 +25,7 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.4/architecture/attestation.md b/docs/versioned_docs/version-2.4/architecture/attestation.md index f335038f6..28e8e62cf 100644 --- a/docs/versioned_docs/version-2.4/architecture/attestation.md +++ b/docs/versioned_docs/version-2.4/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,8 +217,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.4/getting-started/first-steps.md b/docs/versioned_docs/version-2.4/getting-started/first-steps.md index 768e8dfcd..d277b9e09 100644 --- a/docs/versioned_docs/version-2.4/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.4/getting-started/first-steps.md @@ -11,29 +11,29 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step 1. Create the configuration file for your selected cloud provider. - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in your current working directory. @@ -41,9 +41,9 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step First you need to create an [IAM configuration](../workflows/config.md#creating-an-iam-configuration). The easiest way to do this is the following CLI command: - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest @@ -57,9 +57,9 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step * `northeurope` * `westeurope` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test @@ -69,9 +69,9 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step Note that only regions offering CVMs of the `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `N2D`. - + - + ```bash constellation iam create aws --zone=eu-central-1a --prefix=constellTest @@ -88,8 +88,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + Now, fill the output values of the command into the corresponding fields of the `constellation-conf.yaml` file. diff --git a/docs/versioned_docs/version-2.4/getting-started/install.md b/docs/versioned_docs/version-2.4/getting-started/install.md index d830c7792..36d8f541a 100644 --- a/docs/versioned_docs/version-2.4/getting-started/install.md +++ b/docs/versioned_docs/version-2.4/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,14 +105,15 @@ If you don't have a cloud subscription, you can try [MiniConstellation](first-st ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Compute` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` -* `microsoft.insights` + +- `Microsoft.Compute` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` +- `microsoft.insights` By default, Constellation tries to register these automatically if they haven't been registered before. @@ -124,8 +125,8 @@ You need the following permissions for your user account: If you don't have these permissions with scope *subscription*, ask your administrator to [create the service account and a resource group for your Constellation cluster](first-steps.md). Your user account needs the `Contributor` permission scoped to this resource group. - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -137,8 +138,8 @@ You need the following permissions on this project: Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -269,8 +270,8 @@ such as `PowerUserAccess`, or use the following minimal set of permissions: Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -280,8 +281,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -297,8 +298,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -321,8 +322,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -338,9 +339,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.4/overview/clouds.md b/docs/versioned_docs/version-2.4/overview/clouds.md index 745507c52..c48f23cf0 100644 --- a/docs/versioned_docs/version-2.4/overview/clouds.md +++ b/docs/versioned_docs/version-2.4/overview/clouds.md @@ -24,7 +24,7 @@ The following table summarizes the state of features for different infrastructur With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. Regarding (3), Azure provides direct access to remote-attestation statements. However, regarding (4), the standard CVMs still include closed-source firmware running in VM Privilege Level (VMPL) 0. This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.4/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.4/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.4/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.4/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.4/workflows/config.md b/docs/versioned_docs/version-2.4/workflows/config.md index afd53812e..652e58a38 100644 --- a/docs/versioned_docs/version-2.4/workflows/config.md +++ b/docs/versioned_docs/version-2.4/workflows/config.md @@ -6,62 +6,62 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the N2D family. Refer to [N2D machine series](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) or run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all nitroTPM-enabled machines with a minimum of 4 vCPUs (`xlarge` or larger). Refer to the [list of nitroTPM-enabled instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-prerequisites.html) or run `constellation config instance-types` to get the list of all supported options. - - + + Fill the desired VM type into the **instanceType** field in the `constellation-conf.yml` file. ## Creating an IAM configuration You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session. @@ -84,8 +84,8 @@ Paste the output into the corresponding fields of the `constellation-conf.yaml` Since `clientSecretValue` is a sensitive value, you can leave it empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session. @@ -99,8 +99,8 @@ Note that only regions offering CVMs of the `N2D` series are supported. You can Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session. @@ -122,16 +122,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -175,9 +175,9 @@ The following describes the configuration fields and how you obtain the required Since this is a sensitive value, alternatively you can leave `clientSecretValue` empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -201,9 +201,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -232,9 +232,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.4/workflows/recovery.md b/docs/versioned_docs/version-2.4/workflows/recovery.md index fd610fc67..0fd171036 100644 --- a/docs/versioned_docs/version-2.4/workflows/recovery.md +++ b/docs/versioned_docs/version-2.4/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.4/workflows/sbom.md b/docs/versioned_docs/version-2.4/workflows/sbom.md index ec9834b4f..e8ba25a64 100644 --- a/docs/versioned_docs/version-2.4/workflows/sbom.md +++ b/docs/versioned_docs/version-2.4/workflows/sbom.md @@ -15,7 +15,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -36,7 +36,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.4/workflows/scale.md b/docs/versioned_docs/version-2.4/workflows/scale.md index 3b7c0d479..bce045c66 100644 --- a/docs/versioned_docs/version-2.4/workflows/scale.md +++ b/docs/versioned_docs/version-2.4/workflows/scale.md @@ -48,23 +48,23 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + :::caution @@ -72,8 +72,8 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + ## Control-plane node scaling @@ -81,24 +81,24 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + :::caution @@ -106,7 +106,7 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.4/workflows/storage.md b/docs/versioned_docs/version-2.4/workflows/storage.md index d0e5b188f..be9998676 100644 --- a/docs/versioned_docs/version-2.4/workflows/storage.md +++ b/docs/versioned_docs/version-2.4/workflows/storage.md @@ -21,14 +21,14 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as ReadWriteOnce, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. @@ -36,8 +36,8 @@ This includes support for [volume snapshots](https://cloud.google.com/kubernetes You can use them to bring a volume back to a prior state or provision new volumes. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for information about the configuration. - - + + :::caution @@ -47,8 +47,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction) or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -57,8 +57,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -86,8 +86,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -115,8 +115,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + :::caution @@ -126,8 +126,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) @@ -186,8 +186,8 @@ The default storage class is responsible for all persistent volume claims that d Constellation creates a storage class with encryption enabled and sets this as the default class. In case you wish to change it, follow the steps below: - - + + 1. List the storage classes in your cluster: @@ -233,8 +233,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) azuredisk.csi.confidential.cloud Delete Immediate false 1d ``` - - + + 1. List the storage classes in your cluster: @@ -280,8 +280,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) gcp.csi.confidential.cloud Delete Immediate false 1d ``` - - + + :::caution @@ -291,5 +291,5 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + diff --git a/docs/versioned_docs/version-2.4/workflows/troubleshooting.md b/docs/versioned_docs/version-2.4/workflows/troubleshooting.md index 3a28c9cd0..f948f5d06 100644 --- a/docs/versioned_docs/version-2.4/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.4/workflows/troubleshooting.md @@ -5,6 +5,7 @@ This section aids you in finding problems when working with Constellation. ## Azure: Resource Providers can't be registered On Azure, you may receive the following error when running `create` or `terminate` with limited IAM permissions: + ```shell-session Error: Error ensuring Resource Providers are registered. @@ -21,11 +22,13 @@ To continue, please ensure that the [required resource providers](../getting-sta Afterward, set `ARM_SKIP_PROVIDER_REGISTRATION=true` as an environment variable and either run `create` or `terminate` again. For example: + ```bash ARM_SKIP_PROVIDER_REGISTRATION=true constellation create --control-plane-nodes 1 --worker-nodes 2 -y ``` Or alternatively, for `terminate`: + ```bash ARM_SKIP_PROVIDER_REGISTRATION=true constellation terminate ``` @@ -36,8 +39,8 @@ To provide information during early stages of the node's boot process, Constella You can view these information in the follow places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -47,8 +50,8 @@ You can view these information in the follow places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -63,16 +66,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ## Connect to nodes diff --git a/docs/versioned_docs/version-2.4/workflows/trusted-launch.md b/docs/versioned_docs/version-2.4/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.4/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.4/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.4/workflows/verify-cli.md b/docs/versioned_docs/version-2.4/workflows/verify-cli.md index 4f6008cd0..01a2583d6 100644 --- a/docs/versioned_docs/version-2.4/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.4/workflows/verify-cli.md @@ -1,6 +1,6 @@ # Verify the CLI -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -12,7 +12,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -25,7 +25,7 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.5/architecture/attestation.md b/docs/versioned_docs/version-2.5/architecture/attestation.md index f335038f6..28e8e62cf 100644 --- a/docs/versioned_docs/version-2.5/architecture/attestation.md +++ b/docs/versioned_docs/version-2.5/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,8 +217,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.5/getting-started/first-steps.md b/docs/versioned_docs/version-2.5/getting-started/first-steps.md index 4e89bb0f2..02b60d45a 100644 --- a/docs/versioned_docs/version-2.5/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.5/getting-started/first-steps.md @@ -13,9 +13,9 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step First, you need to create a [configuration file](../workflows/config.md) and an [IAM configuration](../workflows/config.md#creating-an-iam-configuration). The easiest way to do this is the following CLI command: - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --generate-config @@ -29,9 +29,9 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step * `northeurope` * `westeurope` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --generate-config @@ -41,9 +41,9 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step Note that only regions offering CVMs of the `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `N2D`. - + - + ```bash constellation iam create aws --zone=eu-central-1a --prefix=constellTest --generate-config @@ -60,8 +60,8 @@ If you don't have a cloud subscription, check out [MiniConstellation](first-step You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.5/getting-started/install.md b/docs/versioned_docs/version-2.5/getting-started/install.md index d830c7792..36d8f541a 100644 --- a/docs/versioned_docs/version-2.5/getting-started/install.md +++ b/docs/versioned_docs/version-2.5/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,14 +105,15 @@ If you don't have a cloud subscription, you can try [MiniConstellation](first-st ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Compute` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` -* `microsoft.insights` + +- `Microsoft.Compute` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` +- `microsoft.insights` By default, Constellation tries to register these automatically if they haven't been registered before. @@ -124,8 +125,8 @@ You need the following permissions for your user account: If you don't have these permissions with scope *subscription*, ask your administrator to [create the service account and a resource group for your Constellation cluster](first-steps.md). Your user account needs the `Contributor` permission scoped to this resource group. - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -137,8 +138,8 @@ You need the following permissions on this project: Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -269,8 +270,8 @@ such as `PowerUserAccess`, or use the following minimal set of permissions: Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -280,8 +281,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -297,8 +298,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -321,8 +322,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -338,9 +339,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.5/overview/clouds.md b/docs/versioned_docs/version-2.5/overview/clouds.md index 3e4a50d27..c48f23cf0 100644 --- a/docs/versioned_docs/version-2.5/overview/clouds.md +++ b/docs/versioned_docs/version-2.5/overview/clouds.md @@ -24,7 +24,7 @@ The following table summarizes the state of features for different infrastructur With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. Regarding (3), Azure provides direct access to remote-attestation statements. However, regarding (4), the standard CVMs still include closed-source firmware running in VM Privilege Level (VMPL) 0. This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -\* Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.5/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.5/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.5/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.5/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.5/workflows/config.md b/docs/versioned_docs/version-2.5/workflows/config.md index 100dedc8c..2edf3bdf6 100644 --- a/docs/versioned_docs/version-2.5/workflows/config.md +++ b/docs/versioned_docs/version-2.5/workflows/config.md @@ -6,29 +6,29 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. @@ -39,25 +39,25 @@ You can also automatically generate a configuration file by adding the `--genera ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the N2D family. Refer to [N2D machine series](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) or run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all nitroTPM-enabled machines with a minimum of 4 vCPUs (`xlarge` or larger). Refer to the [list of nitroTPM-enabled instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-prerequisites.html) or run `constellation config instance-types` to get the list of all supported options. - - + + Fill the desired VM type into the **instanceType** field in the `constellation-conf.yml` file. @@ -66,8 +66,8 @@ Fill the desired VM type into the **instanceType** field in the `constellation-c You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you haven't generated a configuration file yet, you can do so by adding the `--generate-config` flag to the command. This creates a configuration file and populates it with the created IAM values. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session. @@ -90,8 +90,8 @@ Paste the output into the corresponding fields of the `constellation-conf.yaml` Since `clientSecretValue` is a sensitive value, you can leave it empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session. @@ -105,8 +105,8 @@ Note that only regions offering CVMs of the `N2D` series are supported. You can Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session. @@ -128,16 +128,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -181,9 +181,9 @@ The following describes the configuration fields and how you obtain the required Since this is a sensitive value, alternatively you can leave `clientSecretValue` empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -207,9 +207,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -238,9 +238,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.5/workflows/create.md b/docs/versioned_docs/version-2.5/workflows/create.md index 7fc991fd7..115effbdf 100644 --- a/docs/versioned_docs/version-2.5/workflows/create.md +++ b/docs/versioned_docs/version-2.5/workflows/create.md @@ -18,8 +18,8 @@ Before you create the cluster, make sure to have a [valid configuration file](./ ### Create - - + + Choose the initial size of your cluster. The following command creates a cluster with one control-plane and two worker nodes: @@ -32,8 +32,8 @@ For details on the flags, consult the command help via `constellation create -h` *create* stores your cluster's state into a [`terraform.tfstate`](../architecture/orchestration.md#cluster-creation-process) file in your workspace. - - + + Constellation supports managing the infrastructure via Terraform. This allows for an easier GitOps integration as well as meeting regulatory requirements. Since the Constellation CLI also uses Terraform under the hood, you can reuse the same Terraform files. @@ -68,8 +68,8 @@ CONSTELL_CSP=$(cat constellation-conf.yaml | yq ".provider | keys | .[0]") jq --null-input --arg cloudprovider "$CONSTELL_CSP" --arg ip "$CONSTELL_IP" --arg initsecret "$CONSTELL_INIT_SECRET" '{"cloudprovider":$cloudprovider,"ip":$ip,"initsecret":$initsecret}' > constellation-id.json ``` - - + + ## The *init* step diff --git a/docs/versioned_docs/version-2.5/workflows/recovery.md b/docs/versioned_docs/version-2.5/workflows/recovery.md index fd610fc67..0fd171036 100644 --- a/docs/versioned_docs/version-2.5/workflows/recovery.md +++ b/docs/versioned_docs/version-2.5/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.5/workflows/sbom.md b/docs/versioned_docs/version-2.5/workflows/sbom.md index ec9834b4f..e8ba25a64 100644 --- a/docs/versioned_docs/version-2.5/workflows/sbom.md +++ b/docs/versioned_docs/version-2.5/workflows/sbom.md @@ -15,7 +15,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -36,7 +36,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.5/workflows/scale.md b/docs/versioned_docs/version-2.5/workflows/scale.md index 3b7c0d479..bce045c66 100644 --- a/docs/versioned_docs/version-2.5/workflows/scale.md +++ b/docs/versioned_docs/version-2.5/workflows/scale.md @@ -48,23 +48,23 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + :::caution @@ -72,8 +72,8 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + ## Control-plane node scaling @@ -81,24 +81,24 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + :::caution @@ -106,7 +106,7 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.5/workflows/storage.md b/docs/versioned_docs/version-2.5/workflows/storage.md index d0e5b188f..be9998676 100644 --- a/docs/versioned_docs/version-2.5/workflows/storage.md +++ b/docs/versioned_docs/version-2.5/workflows/storage.md @@ -21,14 +21,14 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as ReadWriteOnce, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. @@ -36,8 +36,8 @@ This includes support for [volume snapshots](https://cloud.google.com/kubernetes You can use them to bring a volume back to a prior state or provision new volumes. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for information about the configuration. - - + + :::caution @@ -47,8 +47,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction) or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -57,8 +57,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -86,8 +86,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -115,8 +115,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + :::caution @@ -126,8 +126,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) @@ -186,8 +186,8 @@ The default storage class is responsible for all persistent volume claims that d Constellation creates a storage class with encryption enabled and sets this as the default class. In case you wish to change it, follow the steps below: - - + + 1. List the storage classes in your cluster: @@ -233,8 +233,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) azuredisk.csi.confidential.cloud Delete Immediate false 1d ``` - - + + 1. List the storage classes in your cluster: @@ -280,8 +280,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) gcp.csi.confidential.cloud Delete Immediate false 1d ``` - - + + :::caution @@ -291,5 +291,5 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + diff --git a/docs/versioned_docs/version-2.5/workflows/terminate.md b/docs/versioned_docs/version-2.5/workflows/terminate.md index a2556fe95..ee64a2784 100644 --- a/docs/versioned_docs/version-2.5/workflows/terminate.md +++ b/docs/versioned_docs/version-2.5/workflows/terminate.md @@ -8,8 +8,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -32,8 +32,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -48,5 +48,5 @@ rm constellation-id.json constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.5/workflows/troubleshooting.md b/docs/versioned_docs/version-2.5/workflows/troubleshooting.md index 3a28c9cd0..f948f5d06 100644 --- a/docs/versioned_docs/version-2.5/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.5/workflows/troubleshooting.md @@ -5,6 +5,7 @@ This section aids you in finding problems when working with Constellation. ## Azure: Resource Providers can't be registered On Azure, you may receive the following error when running `create` or `terminate` with limited IAM permissions: + ```shell-session Error: Error ensuring Resource Providers are registered. @@ -21,11 +22,13 @@ To continue, please ensure that the [required resource providers](../getting-sta Afterward, set `ARM_SKIP_PROVIDER_REGISTRATION=true` as an environment variable and either run `create` or `terminate` again. For example: + ```bash ARM_SKIP_PROVIDER_REGISTRATION=true constellation create --control-plane-nodes 1 --worker-nodes 2 -y ``` Or alternatively, for `terminate`: + ```bash ARM_SKIP_PROVIDER_REGISTRATION=true constellation terminate ``` @@ -36,8 +39,8 @@ To provide information during early stages of the node's boot process, Constella You can view these information in the follow places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -47,8 +50,8 @@ You can view these information in the follow places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -63,16 +66,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ## Connect to nodes diff --git a/docs/versioned_docs/version-2.5/workflows/trusted-launch.md b/docs/versioned_docs/version-2.5/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.5/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.5/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.5/workflows/verify-cli.md b/docs/versioned_docs/version-2.5/workflows/verify-cli.md index 4f6008cd0..01a2583d6 100644 --- a/docs/versioned_docs/version-2.5/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.5/workflows/verify-cli.md @@ -1,6 +1,6 @@ # Verify the CLI -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -12,7 +12,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -25,7 +25,7 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.6/architecture/attestation.md b/docs/versioned_docs/version-2.6/architecture/attestation.md index 0c7a1487b..20f9909fd 100644 --- a/docs/versioned_docs/version-2.6/architecture/attestation.md +++ b/docs/versioned_docs/version-2.6/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,8 +217,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.6/getting-started/first-steps.md b/docs/versioned_docs/version-2.6/getting-started/first-steps.md index ad89d89c8..aba09f5c7 100644 --- a/docs/versioned_docs/version-2.6/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.6/getting-started/first-steps.md @@ -17,9 +17,9 @@ If you encounter any problem with the following steps, make sure to use the [lat First, you need to create a [configuration file](../workflows/config.md) and an [IAM configuration](../workflows/config.md#creating-an-iam-configuration). The easiest way to do this is the following CLI command: - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --generate-config @@ -33,9 +33,9 @@ If you encounter any problem with the following steps, make sure to use the [lat * `northeurope` * `westeurope` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --generate-config @@ -45,9 +45,9 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - + - + ```bash constellation iam create aws --zone=eu-central-1a --prefix=constellTest --generate-config @@ -64,8 +64,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.6/getting-started/install.md b/docs/versioned_docs/version-2.6/getting-started/install.md index d830c7792..36d8f541a 100644 --- a/docs/versioned_docs/version-2.6/getting-started/install.md +++ b/docs/versioned_docs/version-2.6/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,14 +105,15 @@ If you don't have a cloud subscription, you can try [MiniConstellation](first-st ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Compute` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` -* `microsoft.insights` + +- `Microsoft.Compute` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` +- `microsoft.insights` By default, Constellation tries to register these automatically if they haven't been registered before. @@ -124,8 +125,8 @@ You need the following permissions for your user account: If you don't have these permissions with scope *subscription*, ask your administrator to [create the service account and a resource group for your Constellation cluster](first-steps.md). Your user account needs the `Contributor` permission scoped to this resource group. - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. @@ -137,8 +138,8 @@ You need the following permissions on this project: Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -269,8 +270,8 @@ such as `PowerUserAccess`, or use the following minimal set of permissions: Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -280,8 +281,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -297,8 +298,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -321,8 +322,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -338,9 +339,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.6/overview/clouds.md b/docs/versioned_docs/version-2.6/overview/clouds.md index 3e4a50d27..c48f23cf0 100644 --- a/docs/versioned_docs/version-2.6/overview/clouds.md +++ b/docs/versioned_docs/version-2.6/overview/clouds.md @@ -24,7 +24,7 @@ The following table summarizes the state of features for different infrastructur With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. Regarding (3), Azure provides direct access to remote-attestation statements. However, regarding (4), the standard CVMs still include closed-source firmware running in VM Privilege Level (VMPL) 0. This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -\* Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.6/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.6/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.6/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.6/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.6/overview/performance.md b/docs/versioned_docs/version-2.6/overview/performance.md index 8be5b7952..aef594c46 100644 --- a/docs/versioned_docs/version-2.6/overview/performance.md +++ b/docs/versioned_docs/version-2.6/overview/performance.md @@ -181,7 +181,7 @@ The following `fio` settings were used: - IOPS: 4 KB blocks and 128 iodepth - Bandwidth: 1024 KB blocks and 128 iodepth -For more details, see the [`fio` test configuration](../../../../.github/actions/e2e_benchmark/fio.ini). +For more details, see the [`fio` test configuration](https://github.com/edgelesssys/constellation/blob/main/.github/actions/e2e_benchmark/fio.ini). The results for IOPS on Azure are as follows: diff --git a/docs/versioned_docs/version-2.6/workflows/config.md b/docs/versioned_docs/version-2.6/workflows/config.md index 5da01beeb..5a1ba92d1 100644 --- a/docs/versioned_docs/version-2.6/workflows/config.md +++ b/docs/versioned_docs/version-2.6/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,29 +14,29 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. @@ -47,25 +47,25 @@ You can also automatically generate a configuration file by adding the `--genera ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all nitroTPM-enabled machines with a minimum of 4 vCPUs (`xlarge` or larger). Refer to the [list of nitroTPM-enabled instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-prerequisites.html) or run `constellation config instance-types` to get the list of all supported options. - - + + Fill the desired VM type into the **instanceType** field in the `constellation-conf.yml` file. @@ -79,8 +79,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you haven't generated a configuration file yet, you can do so by adding the `--generate-config` flag to the command. This creates a configuration file and populates it with the created IAM values. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session. @@ -103,8 +103,8 @@ Paste the output into the corresponding fields of the `constellation-conf.yaml` Since `clientSecretValue` is a sensitive value, you can leave it empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session. @@ -118,8 +118,8 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session. @@ -141,16 +141,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -194,9 +194,9 @@ The following describes the configuration fields and how you obtain the required Since this is a sensitive value, alternatively you can leave `clientSecretValue` empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -220,9 +220,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -251,9 +251,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.6/workflows/create.md b/docs/versioned_docs/version-2.6/workflows/create.md index d527618b0..81ed55582 100644 --- a/docs/versioned_docs/version-2.6/workflows/create.md +++ b/docs/versioned_docs/version-2.6/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -26,8 +26,8 @@ Before you create the cluster, make sure to have a [valid configuration file](./ ### Create - - + + Choose the initial size of your cluster. The following command creates a cluster with one control-plane and two worker nodes: @@ -40,8 +40,8 @@ For details on the flags, consult the command help via `constellation create -h` *create* stores your cluster's state in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Terraform allows for an easier GitOps integration as well as meeting regulatory requirements. Since the Constellation CLI also uses Terraform under the hood, you can reuse the same Terraform files. @@ -80,8 +80,8 @@ CONSTELL_CSP=$(cat constellation-conf.yaml | yq ".provider | keys | .[0]") jq --null-input --arg cloudprovider "$CONSTELL_CSP" --arg ip "$CONSTELL_IP" --arg initsecret "$CONSTELL_INIT_SECRET" '{"cloudprovider":$cloudprovider,"ip":$ip,"initsecret":$initsecret}' > constellation-id.json ``` - - + + ## The *init* step diff --git a/docs/versioned_docs/version-2.6/workflows/recovery.md b/docs/versioned_docs/version-2.6/workflows/recovery.md index c26fb32eb..35596b8c9 100644 --- a/docs/versioned_docs/version-2.6/workflows/recovery.md +++ b/docs/versioned_docs/version-2.6/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.6/workflows/sbom.md b/docs/versioned_docs/version-2.6/workflows/sbom.md index 44b347a55..92550c182 100644 --- a/docs/versioned_docs/version-2.6/workflows/sbom.md +++ b/docs/versioned_docs/version-2.6/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -19,7 +19,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -40,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.6/workflows/scale.md b/docs/versioned_docs/version-2.6/workflows/scale.md index 3b7c0d479..bce045c66 100644 --- a/docs/versioned_docs/version-2.6/workflows/scale.md +++ b/docs/versioned_docs/version-2.6/workflows/scale.md @@ -48,23 +48,23 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + :::caution @@ -72,8 +72,8 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + ## Control-plane node scaling @@ -81,24 +81,24 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + :::caution @@ -106,7 +106,7 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.6/workflows/storage.md b/docs/versioned_docs/version-2.6/workflows/storage.md index d0e5b188f..be9998676 100644 --- a/docs/versioned_docs/version-2.6/workflows/storage.md +++ b/docs/versioned_docs/version-2.6/workflows/storage.md @@ -21,14 +21,14 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as ReadWriteOnce, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. @@ -36,8 +36,8 @@ This includes support for [volume snapshots](https://cloud.google.com/kubernetes You can use them to bring a volume back to a prior state or provision new volumes. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for information about the configuration. - - + + :::caution @@ -47,8 +47,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction) or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -57,8 +57,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -86,8 +86,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -115,8 +115,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + :::caution @@ -126,8 +126,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) @@ -186,8 +186,8 @@ The default storage class is responsible for all persistent volume claims that d Constellation creates a storage class with encryption enabled and sets this as the default class. In case you wish to change it, follow the steps below: - - + + 1. List the storage classes in your cluster: @@ -233,8 +233,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) azuredisk.csi.confidential.cloud Delete Immediate false 1d ``` - - + + 1. List the storage classes in your cluster: @@ -280,8 +280,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) gcp.csi.confidential.cloud Delete Immediate false 1d ``` - - + + :::caution @@ -291,5 +291,5 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + diff --git a/docs/versioned_docs/version-2.6/workflows/terminate.md b/docs/versioned_docs/version-2.6/workflows/terminate.md index 647eadb42..f33489ca5 100644 --- a/docs/versioned_docs/version-2.6/workflows/terminate.md +++ b/docs/versioned_docs/version-2.6/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-id.json constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.6/workflows/troubleshooting.md b/docs/versioned_docs/version-2.6/workflows/troubleshooting.md index 801bb995a..6bdf1d75c 100644 --- a/docs/versioned_docs/version-2.6/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.6/workflows/troubleshooting.md @@ -10,6 +10,7 @@ If something doesn't work, check out the [known issues](https://github.com/edgel ## Azure: Resource Providers can't be registered On Azure, you may receive the following error when running `create` or `terminate` with limited IAM permissions: + ```shell-session Error: Error ensuring Resource Providers are registered. @@ -26,11 +27,13 @@ To continue, please ensure that the [required resource providers](../getting-sta Afterward, set `ARM_SKIP_PROVIDER_REGISTRATION=true` as an environment variable and either run `create` or `terminate` again. For example: + ```bash ARM_SKIP_PROVIDER_REGISTRATION=true constellation create --control-plane-nodes 1 --worker-nodes 2 -y ``` Or alternatively, for `terminate`: + ```bash ARM_SKIP_PROVIDER_REGISTRATION=true constellation terminate ``` @@ -41,8 +44,8 @@ To provide information during early stages of the node's boot process, Constella You can view these information in the follow places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -52,8 +55,8 @@ You can view these information in the follow places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -68,16 +71,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ## Connect to nodes diff --git a/docs/versioned_docs/version-2.6/workflows/trusted-launch.md b/docs/versioned_docs/version-2.6/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.6/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.6/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.6/workflows/verify-cli.md b/docs/versioned_docs/version-2.6/workflows/verify-cli.md index 1280c51b0..aa2df4be4 100644 --- a/docs/versioned_docs/version-2.6/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.6/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -33,7 +33,7 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.7/architecture/attestation.md b/docs/versioned_docs/version-2.7/architecture/attestation.md index 0c7a1487b..20f9909fd 100644 --- a/docs/versioned_docs/version-2.7/architecture/attestation.md +++ b/docs/versioned_docs/version-2.7/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,8 +217,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.7/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.7/getting-started/first-steps-local.md index 707074bb9..81d8e141d 100644 --- a/docs/versioned_docs/version-2.7/getting-started/first-steps-local.md +++ b/docs/versioned_docs/version-2.7/getting-started/first-steps-local.md @@ -30,8 +30,8 @@ Both options use virtualization to create a local cluster with control-plane nod ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -59,8 +59,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -138,8 +138,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -192,8 +192,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -204,8 +204,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -233,8 +233,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/versioned_docs/version-2.7/getting-started/first-steps.md b/docs/versioned_docs/version-2.7/getting-started/first-steps.md index 1569afc14..eca497438 100644 --- a/docs/versioned_docs/version-2.7/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.7/getting-started/first-steps.md @@ -17,9 +17,9 @@ If you encounter any problem with the following steps, make sure to use the [lat First, you need to create a [configuration file](../workflows/config.md) and an [IAM configuration](../workflows/config.md#creating-an-iam-configuration). The easiest way to do this is the following CLI command: - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --generate-config @@ -33,9 +33,9 @@ If you encounter any problem with the following steps, make sure to use the [lat * `northeurope` * `westeurope` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --generate-config @@ -45,9 +45,9 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - + - + ```bash constellation iam create aws --zone=eu-central-1a --prefix=constellTest --generate-config @@ -66,8 +66,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.7/getting-started/install.md b/docs/versioned_docs/version-2.7/getting-started/install.md index 5975008a2..ac0ef3da8 100644 --- a/docs/versioned_docs/version-2.7/getting-started/install.md +++ b/docs/versioned_docs/version-2.7/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,38 +105,41 @@ If you don't have a cloud subscription, you can try [MiniConstellation](first-st ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] -* `Microsoft.Compute` -* `Microsoft.Insights` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` + +- `Microsoft.Attestation` +- `Microsoft.Compute` +- `Microsoft.Insights` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` By default, Constellation tries to register these automatically if they haven't been registered before. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `*/register/action` \[1] -* `Microsoft.Authorization/roleAssignments/*` -* `Microsoft.Authorization/roleDefinitions/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Resources/subscriptions/resourcegroups/*` + +- `*/register/action` \[1] +- `Microsoft.Authorization/roleAssignments/*` +- `Microsoft.Authorization/roleDefinitions/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Resources/subscriptions/resourcegroups/*` The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] -* `Microsoft.Compute/virtualMachineScaleSets/*` -* `Microsoft.Insights/components/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Network/loadBalancers/*` -* `Microsoft.Network/loadBalancers/backendAddressPools/*` -* `Microsoft.Network/networkSecurityGroups/*` -* `Microsoft.Network/publicIPAddresses/*` -* `Microsoft.Network/virtualNetworks/*` -* `Microsoft.Network/virtualNetworks/subnets/*` + +- `Microsoft.Attestation/attestationProviders/*` +- `Microsoft.Compute/virtualMachineScaleSets/*` +- `Microsoft.Insights/components/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Network/loadBalancers/*` +- `Microsoft.Network/loadBalancers/backendAddressPools/*` +- `Microsoft.Network/networkSecurityGroups/*` +- `Microsoft.Network/publicIPAddresses/*` +- `Microsoft.Network/virtualNetworks/*` +- `Microsoft.Network/virtualNetworks/subnets/*` The built-in `Contributor` role is a superset of these permissions. @@ -144,91 +147,91 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `iam.serviceAccountKeys.create` -* `iam.serviceAccountKeys.delete` -* `iam.serviceAccountKeys.get` -* `iam.serviceAccounts.create` -* `iam.serviceAccounts.delete` -* `iam.serviceAccounts.get` -* `resourcemanager.projects.getIamPolicy` -* `resourcemanager.projects.setIamPolicy` + +- `iam.serviceAccountKeys.create` +- `iam.serviceAccountKeys.delete` +- `iam.serviceAccountKeys.get` +- `iam.serviceAccounts.create` +- `iam.serviceAccounts.delete` +- `iam.serviceAccounts.get` +- `resourcemanager.projects.getIamPolicy` +- `resourcemanager.projects.setIamPolicy` Together, the built-in roles `roles/editor` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `compute.addresses.createInternal` -* `compute.addresses.deleteInternal` -* `compute.addresses.get` -* `compute.addresses.useInternal` -* `compute.backendServices.create` -* `compute.backendServices.delete` -* `compute.backendServices.get` -* `compute.backendServices.use` -* `compute.disks.create` -* `compute.firewalls.create` -* `compute.firewalls.delete` -* `compute.firewalls.get` -* `compute.globalAddresses.create` -* `compute.globalAddresses.delete` -* `compute.globalAddresses.get` -* `compute.globalAddresses.use` -* `compute.globalForwardingRules.create` -* `compute.globalForwardingRules.delete` -* `compute.globalForwardingRules.get` -* `compute.globalForwardingRules.setLabels` -* `compute.globalOperations.get` -* `compute.healthChecks.create` -* `compute.healthChecks.delete` -* `compute.healthChecks.get` -* `compute.healthChecks.useReadOnly` -* `compute.instanceGroupManagers.create` -* `compute.instanceGroupManagers.delete` -* `compute.instanceGroupManagers.get` -* `compute.instanceGroups.create` -* `compute.instanceGroups.delete` -* `compute.instanceGroups.get` -* `compute.instanceGroups.use` -* `compute.instances.create` -* `compute.instances.setLabels` -* `compute.instances.setMetadata` -* `compute.instances.setTags` -* `compute.instanceTemplates.create` -* `compute.instanceTemplates.delete` -* `compute.instanceTemplates.get` -* `compute.instanceTemplates.useReadOnly` -* `compute.networks.create` -* `compute.networks.delete` -* `compute.networks.get` -* `compute.networks.updatePolicy` -* `compute.routers.create` -* `compute.routers.delete` -* `compute.routers.get` -* `compute.routers.update` -* `compute.subnetworks.create` -* `compute.subnetworks.delete` -* `compute.subnetworks.get` -* `compute.subnetworks.use` -* `compute.targetTcpProxies.create` -* `compute.targetTcpProxies.delete` -* `compute.targetTcpProxies.get` -* `compute.targetTcpProxies.use` -* `iam.serviceAccounts.actAs` + +- `compute.addresses.createInternal` +- `compute.addresses.deleteInternal` +- `compute.addresses.get` +- `compute.addresses.useInternal` +- `compute.backendServices.create` +- `compute.backendServices.delete` +- `compute.backendServices.get` +- `compute.backendServices.use` +- `compute.disks.create` +- `compute.firewalls.create` +- `compute.firewalls.delete` +- `compute.firewalls.get` +- `compute.globalAddresses.create` +- `compute.globalAddresses.delete` +- `compute.globalAddresses.get` +- `compute.globalAddresses.use` +- `compute.globalForwardingRules.create` +- `compute.globalForwardingRules.delete` +- `compute.globalForwardingRules.get` +- `compute.globalForwardingRules.setLabels` +- `compute.globalOperations.get` +- `compute.healthChecks.create` +- `compute.healthChecks.delete` +- `compute.healthChecks.get` +- `compute.healthChecks.useReadOnly` +- `compute.instanceGroupManagers.create` +- `compute.instanceGroupManagers.delete` +- `compute.instanceGroupManagers.get` +- `compute.instanceGroups.create` +- `compute.instanceGroups.delete` +- `compute.instanceGroups.get` +- `compute.instanceGroups.use` +- `compute.instances.create` +- `compute.instances.setLabels` +- `compute.instances.setMetadata` +- `compute.instances.setTags` +- `compute.instanceTemplates.create` +- `compute.instanceTemplates.delete` +- `compute.instanceTemplates.get` +- `compute.instanceTemplates.useReadOnly` +- `compute.networks.create` +- `compute.networks.delete` +- `compute.networks.get` +- `compute.networks.updatePolicy` +- `compute.routers.create` +- `compute.routers.delete` +- `compute.routers.get` +- `compute.routers.update` +- `compute.subnetworks.create` +- `compute.subnetworks.delete` +- `compute.subnetworks.get` +- `compute.subnetworks.use` +- `compute.targetTcpProxies.create` +- `compute.targetTcpProxies.delete` +- `compute.targetTcpProxies.get` +- `compute.targetTcpProxies.use` +- `iam.serviceAccounts.actAs` Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -363,8 +366,8 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -374,8 +377,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -391,8 +394,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -415,8 +418,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -432,9 +435,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.7/overview/clouds.md b/docs/versioned_docs/version-2.7/overview/clouds.md index 847c888df..30995a012 100644 --- a/docs/versioned_docs/version-2.7/overview/clouds.md +++ b/docs/versioned_docs/version-2.7/overview/clouds.md @@ -24,7 +24,7 @@ The following table summarizes the state of features for different infrastructur With its [CVM offering](https://docs.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview), Azure provides the best foundations for Constellation. Regarding (3), Azure provides direct access to remote-attestation statements. However, regarding (4), the standard CVMs still include closed-source firmware running in VM Privilege Level (VMPL) 0. This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -\* Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.7/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.7/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.7/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.7/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.7/overview/performance.md b/docs/versioned_docs/version-2.7/overview/performance.md index 8be5b7952..aef594c46 100644 --- a/docs/versioned_docs/version-2.7/overview/performance.md +++ b/docs/versioned_docs/version-2.7/overview/performance.md @@ -181,7 +181,7 @@ The following `fio` settings were used: - IOPS: 4 KB blocks and 128 iodepth - Bandwidth: 1024 KB blocks and 128 iodepth -For more details, see the [`fio` test configuration](../../../../.github/actions/e2e_benchmark/fio.ini). +For more details, see the [`fio` test configuration](https://github.com/edgelesssys/constellation/blob/main/.github/actions/e2e_benchmark/fio.ini). The results for IOPS on Azure are as follows: diff --git a/docs/versioned_docs/version-2.7/workflows/config.md b/docs/versioned_docs/version-2.7/workflows/config.md index dd86a34a2..5640bfd7d 100644 --- a/docs/versioned_docs/version-2.7/workflows/config.md +++ b/docs/versioned_docs/version-2.7/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,29 +14,29 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. @@ -47,25 +47,25 @@ You can also automatically generate a configuration file by adding the `--genera ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all nitroTPM-enabled machines with a minimum of 4 vCPUs (`xlarge` or larger). Refer to the [list of nitroTPM-enabled instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-prerequisites.html) or run `constellation config instance-types` to get the list of all supported options. - - + + Fill the desired VM type into the **instanceType** field in the `constellation-conf.yml` file. @@ -79,8 +79,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you haven't generated a configuration file yet, you can do so by adding the `--generate-config` flag to the command. This creates a configuration file and populates it with the created IAM values. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -103,8 +103,8 @@ Paste the output into the corresponding fields of the `constellation-conf.yaml` Since `clientSecretValue` is a sensitive value, you can leave it empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -118,8 +118,8 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -143,16 +143,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -196,9 +196,9 @@ The following describes the configuration fields and how you obtain the required Since this is a sensitive value, alternatively you can leave `clientSecretValue` empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -222,9 +222,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -255,9 +255,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.7/workflows/create.md b/docs/versioned_docs/version-2.7/workflows/create.md index aff59bb6a..5c4dd2948 100644 --- a/docs/versioned_docs/version-2.7/workflows/create.md +++ b/docs/versioned_docs/version-2.7/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -26,8 +26,8 @@ Before you create the cluster, make sure to have a [valid configuration file](./ ### Create - - + + Choose the initial size of your cluster. The following command creates a cluster with one control-plane and two worker nodes: @@ -40,8 +40,8 @@ For details on the flags, consult the command help via `constellation create -h` *create* stores your cluster's state in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Terraform allows for an easier GitOps integration as well as meeting regulatory requirements. Since the Constellation CLI also uses Terraform under the hood, you can reuse the same Terraform files. @@ -80,8 +80,8 @@ CONSTELL_CSP=$(cat constellation-conf.yaml | yq ".provider | keys | .[0]") jq --null-input --arg cloudprovider "$CONSTELL_CSP" --arg ip "$CONSTELL_IP" --arg initsecret "$CONSTELL_INIT_SECRET" '{"cloudprovider":$cloudprovider,"ip":$ip,"initsecret":$initsecret}' > constellation-id.json ``` - - + + ## The *init* step diff --git a/docs/versioned_docs/version-2.7/workflows/recovery.md b/docs/versioned_docs/version-2.7/workflows/recovery.md index c26fb32eb..35596b8c9 100644 --- a/docs/versioned_docs/version-2.7/workflows/recovery.md +++ b/docs/versioned_docs/version-2.7/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.7/workflows/sbom.md b/docs/versioned_docs/version-2.7/workflows/sbom.md index 44b347a55..92550c182 100644 --- a/docs/versioned_docs/version-2.7/workflows/sbom.md +++ b/docs/versioned_docs/version-2.7/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -19,7 +19,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -40,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.7/workflows/scale.md b/docs/versioned_docs/version-2.7/workflows/scale.md index 3b7c0d479..bce045c66 100644 --- a/docs/versioned_docs/version-2.7/workflows/scale.md +++ b/docs/versioned_docs/version-2.7/workflows/scale.md @@ -48,23 +48,23 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + :::caution @@ -72,8 +72,8 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + ## Control-plane node scaling @@ -81,24 +81,24 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + :::caution @@ -106,7 +106,7 @@ Scaling isn't yet implemented for AWS. If you require this feature, [let us know ::: - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.7/workflows/storage.md b/docs/versioned_docs/version-2.7/workflows/storage.md index d0e5b188f..be9998676 100644 --- a/docs/versioned_docs/version-2.7/workflows/storage.md +++ b/docs/versioned_docs/version-2.7/workflows/storage.md @@ -21,14 +21,14 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as ReadWriteOnce, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. @@ -36,8 +36,8 @@ This includes support for [volume snapshots](https://cloud.google.com/kubernetes You can use them to bring a volume back to a prior state or provision new volumes. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for information about the configuration. - - + + :::caution @@ -47,8 +47,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction) or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -57,8 +57,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -86,8 +86,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -115,8 +115,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + :::caution @@ -126,8 +126,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) @@ -186,8 +186,8 @@ The default storage class is responsible for all persistent volume claims that d Constellation creates a storage class with encryption enabled and sets this as the default class. In case you wish to change it, follow the steps below: - - + + 1. List the storage classes in your cluster: @@ -233,8 +233,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) azuredisk.csi.confidential.cloud Delete Immediate false 1d ``` - - + + 1. List the storage classes in your cluster: @@ -280,8 +280,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) gcp.csi.confidential.cloud Delete Immediate false 1d ``` - - + + :::caution @@ -291,5 +291,5 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + diff --git a/docs/versioned_docs/version-2.7/workflows/terminate.md b/docs/versioned_docs/version-2.7/workflows/terminate.md index 647eadb42..f33489ca5 100644 --- a/docs/versioned_docs/version-2.7/workflows/terminate.md +++ b/docs/versioned_docs/version-2.7/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-id.json constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.7/workflows/troubleshooting.md b/docs/versioned_docs/version-2.7/workflows/troubleshooting.md index 2ddf3335d..cd095be28 100644 --- a/docs/versioned_docs/version-2.7/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.7/workflows/troubleshooting.md @@ -75,8 +75,8 @@ To provide information during early stages of a node's boot process, Constellati You can view this information in the following places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -86,8 +86,8 @@ You can view this information in the following places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -102,16 +102,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ### Node shell access diff --git a/docs/versioned_docs/version-2.7/workflows/trusted-launch.md b/docs/versioned_docs/version-2.7/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.7/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.7/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.7/workflows/verify-cli.md b/docs/versioned_docs/version-2.7/workflows/verify-cli.md index 1280c51b0..aa2df4be4 100644 --- a/docs/versioned_docs/version-2.7/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.7/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -33,7 +33,7 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.8/architecture/attestation.md b/docs/versioned_docs/version-2.8/architecture/attestation.md index 07ac3aa72..592063193 100644 --- a/docs/versioned_docs/version-2.8/architecture/attestation.md +++ b/docs/versioned_docs/version-2.8/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,16 +217,16 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ### CVM verification To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. For verification of the CVM technology, Constellation may expose additional options in its config file. - - + + On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. @@ -248,18 +248,18 @@ You may customize certain parameters for verification of the attestation stateme More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. - - + + There is no additional configuration available for GCP. - - + + There is no additional configuration available for AWS. - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.8/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.8/getting-started/first-steps-local.md index 707074bb9..81d8e141d 100644 --- a/docs/versioned_docs/version-2.8/getting-started/first-steps-local.md +++ b/docs/versioned_docs/version-2.8/getting-started/first-steps-local.md @@ -30,8 +30,8 @@ Both options use virtualization to create a local cluster with control-plane nod ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -59,8 +59,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -138,8 +138,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -192,8 +192,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -204,8 +204,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -233,8 +233,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/versioned_docs/version-2.8/getting-started/first-steps.md b/docs/versioned_docs/version-2.8/getting-started/first-steps.md index 4449e6d37..43ed0f923 100644 --- a/docs/versioned_docs/version-2.8/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.8/getting-started/first-steps.md @@ -17,9 +17,9 @@ If you encounter any problem with the following steps, make sure to use the [lat First, you need to create a [configuration file](../workflows/config.md) and an [IAM configuration](../workflows/config.md#creating-an-iam-configuration). The easiest way to do this is the following CLI command: - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --generate-config @@ -34,9 +34,9 @@ If you encounter any problem with the following steps, make sure to use the [lat * `westeurope` * `southeastasia` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --generate-config @@ -46,9 +46,9 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - + - + ```bash constellation iam create aws --zone=eu-central-1a --prefix=constellTest --generate-config @@ -67,8 +67,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.8/getting-started/install.md b/docs/versioned_docs/version-2.8/getting-started/install.md index 0575192af..2aa274b98 100644 --- a/docs/versioned_docs/version-2.8/getting-started/install.md +++ b/docs/versioned_docs/version-2.8/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,39 +105,42 @@ If you don't have a cloud subscription, you can also set up a [local Constellati ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] -* `Microsoft.Compute` -* `Microsoft.Insights` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` + +- `Microsoft.Attestation` +- `Microsoft.Compute` +- `Microsoft.Insights` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` By default, Constellation tries to register these automatically if they haven't been registered before. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `*/register/action` \[1] -* `Microsoft.Authorization/roleAssignments/*` -* `Microsoft.Authorization/roleDefinitions/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Resources/subscriptions/resourcegroups/*` + +- `*/register/action` \[1] +- `Microsoft.Authorization/roleAssignments/*` +- `Microsoft.Authorization/roleDefinitions/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Resources/subscriptions/resourcegroups/*` The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] -* `Microsoft.Compute/virtualMachineScaleSets/*` -* `Microsoft.Insights/components/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Network/loadBalancers/*` -* `Microsoft.Network/loadBalancers/backendAddressPools/*` -* `Microsoft.Network/networkSecurityGroups/*` -* `Microsoft.Network/publicIPAddresses/*` -* `Microsoft.Network/virtualNetworks/*` -* `Microsoft.Network/virtualNetworks/subnets/*` -* `Microsoft.Network/natGateways/*` + +- `Microsoft.Attestation/attestationProviders/*` +- `Microsoft.Compute/virtualMachineScaleSets/*` +- `Microsoft.Insights/components/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Network/loadBalancers/*` +- `Microsoft.Network/loadBalancers/backendAddressPools/*` +- `Microsoft.Network/networkSecurityGroups/*` +- `Microsoft.Network/publicIPAddresses/*` +- `Microsoft.Network/virtualNetworks/*` +- `Microsoft.Network/virtualNetworks/subnets/*` +- `Microsoft.Network/natGateways/*` The built-in `Contributor` role is a superset of these permissions. @@ -145,91 +148,91 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `iam.serviceAccountKeys.create` -* `iam.serviceAccountKeys.delete` -* `iam.serviceAccountKeys.get` -* `iam.serviceAccounts.create` -* `iam.serviceAccounts.delete` -* `iam.serviceAccounts.get` -* `resourcemanager.projects.getIamPolicy` -* `resourcemanager.projects.setIamPolicy` + +- `iam.serviceAccountKeys.create` +- `iam.serviceAccountKeys.delete` +- `iam.serviceAccountKeys.get` +- `iam.serviceAccounts.create` +- `iam.serviceAccounts.delete` +- `iam.serviceAccounts.get` +- `resourcemanager.projects.getIamPolicy` +- `resourcemanager.projects.setIamPolicy` Together, the built-in roles `roles/editor` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `compute.addresses.createInternal` -* `compute.addresses.deleteInternal` -* `compute.addresses.get` -* `compute.addresses.useInternal` -* `compute.backendServices.create` -* `compute.backendServices.delete` -* `compute.backendServices.get` -* `compute.backendServices.use` -* `compute.disks.create` -* `compute.firewalls.create` -* `compute.firewalls.delete` -* `compute.firewalls.get` -* `compute.globalAddresses.create` -* `compute.globalAddresses.delete` -* `compute.globalAddresses.get` -* `compute.globalAddresses.use` -* `compute.globalForwardingRules.create` -* `compute.globalForwardingRules.delete` -* `compute.globalForwardingRules.get` -* `compute.globalForwardingRules.setLabels` -* `compute.globalOperations.get` -* `compute.healthChecks.create` -* `compute.healthChecks.delete` -* `compute.healthChecks.get` -* `compute.healthChecks.useReadOnly` -* `compute.instanceGroupManagers.create` -* `compute.instanceGroupManagers.delete` -* `compute.instanceGroupManagers.get` -* `compute.instanceGroups.create` -* `compute.instanceGroups.delete` -* `compute.instanceGroups.get` -* `compute.instanceGroups.use` -* `compute.instances.create` -* `compute.instances.setLabels` -* `compute.instances.setMetadata` -* `compute.instances.setTags` -* `compute.instanceTemplates.create` -* `compute.instanceTemplates.delete` -* `compute.instanceTemplates.get` -* `compute.instanceTemplates.useReadOnly` -* `compute.networks.create` -* `compute.networks.delete` -* `compute.networks.get` -* `compute.networks.updatePolicy` -* `compute.routers.create` -* `compute.routers.delete` -* `compute.routers.get` -* `compute.routers.update` -* `compute.subnetworks.create` -* `compute.subnetworks.delete` -* `compute.subnetworks.get` -* `compute.subnetworks.use` -* `compute.targetTcpProxies.create` -* `compute.targetTcpProxies.delete` -* `compute.targetTcpProxies.get` -* `compute.targetTcpProxies.use` -* `iam.serviceAccounts.actAs` + +- `compute.addresses.createInternal` +- `compute.addresses.deleteInternal` +- `compute.addresses.get` +- `compute.addresses.useInternal` +- `compute.backendServices.create` +- `compute.backendServices.delete` +- `compute.backendServices.get` +- `compute.backendServices.use` +- `compute.disks.create` +- `compute.firewalls.create` +- `compute.firewalls.delete` +- `compute.firewalls.get` +- `compute.globalAddresses.create` +- `compute.globalAddresses.delete` +- `compute.globalAddresses.get` +- `compute.globalAddresses.use` +- `compute.globalForwardingRules.create` +- `compute.globalForwardingRules.delete` +- `compute.globalForwardingRules.get` +- `compute.globalForwardingRules.setLabels` +- `compute.globalOperations.get` +- `compute.healthChecks.create` +- `compute.healthChecks.delete` +- `compute.healthChecks.get` +- `compute.healthChecks.useReadOnly` +- `compute.instanceGroupManagers.create` +- `compute.instanceGroupManagers.delete` +- `compute.instanceGroupManagers.get` +- `compute.instanceGroups.create` +- `compute.instanceGroups.delete` +- `compute.instanceGroups.get` +- `compute.instanceGroups.use` +- `compute.instances.create` +- `compute.instances.setLabels` +- `compute.instances.setMetadata` +- `compute.instances.setTags` +- `compute.instanceTemplates.create` +- `compute.instanceTemplates.delete` +- `compute.instanceTemplates.get` +- `compute.instanceTemplates.useReadOnly` +- `compute.networks.create` +- `compute.networks.delete` +- `compute.networks.get` +- `compute.networks.updatePolicy` +- `compute.routers.create` +- `compute.routers.delete` +- `compute.routers.get` +- `compute.routers.update` +- `compute.subnetworks.create` +- `compute.subnetworks.delete` +- `compute.subnetworks.get` +- `compute.subnetworks.use` +- `compute.targetTcpProxies.create` +- `compute.targetTcpProxies.delete` +- `compute.targetTcpProxies.get` +- `compute.targetTcpProxies.use` +- `iam.serviceAccounts.actAs` Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -364,8 +367,8 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -375,8 +378,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -392,8 +395,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -416,8 +419,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -433,9 +436,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.8/overview/clouds.md b/docs/versioned_docs/version-2.8/overview/clouds.md index c56a623b1..dfc3d5307 100644 --- a/docs/versioned_docs/version-2.8/overview/clouds.md +++ b/docs/versioned_docs/version-2.8/overview/clouds.md @@ -31,7 +31,7 @@ This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -\* Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.8/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.8/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.8/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.8/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.8/overview/performance.md b/docs/versioned_docs/version-2.8/overview/performance.md index 8be5b7952..aef594c46 100644 --- a/docs/versioned_docs/version-2.8/overview/performance.md +++ b/docs/versioned_docs/version-2.8/overview/performance.md @@ -181,7 +181,7 @@ The following `fio` settings were used: - IOPS: 4 KB blocks and 128 iodepth - Bandwidth: 1024 KB blocks and 128 iodepth -For more details, see the [`fio` test configuration](../../../../.github/actions/e2e_benchmark/fio.ini). +For more details, see the [`fio` test configuration](https://github.com/edgelesssys/constellation/blob/main/.github/actions/e2e_benchmark/fio.ini). The results for IOPS on Azure are as follows: diff --git a/docs/versioned_docs/version-2.8/workflows/config.md b/docs/versioned_docs/version-2.8/workflows/config.md index 260c4e6ec..3330abe8a 100644 --- a/docs/versioned_docs/version-2.8/workflows/config.md +++ b/docs/versioned_docs/version-2.8/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,29 +14,29 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. @@ -47,25 +47,25 @@ You can also automatically generate a configuration file by adding the `--genera ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all nitroTPM-enabled machines with a minimum of 4 vCPUs (`xlarge` or larger). Refer to the [list of nitroTPM-enabled instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enable-nitrotpm-prerequisites.html) or run `constellation config instance-types` to get the list of all supported options. - - + + Fill the desired VM type into the **instanceType** field in the `constellation-conf.yml` file. @@ -79,8 +79,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you haven't generated a configuration file yet, you can do so by adding the `--generate-config` flag to the command. This creates a configuration file and populates it with the created IAM values. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -104,8 +104,8 @@ Paste the output into the corresponding fields of the `constellation-conf.yaml` Since `clientSecretValue` is a sensitive value, you can leave it empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -119,8 +119,8 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -144,16 +144,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -198,9 +198,9 @@ The following describes the configuration fields and how you obtain the required Since this is a sensitive value, alternatively you can leave `clientSecretValue` empty in the configuration file and pass it via an environment variable instead. To this end, create the environment variable `CONSTELL_AZURE_CLIENT_SECRET_VALUE` and set it to the secret value. ::: - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -224,9 +224,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -257,9 +257,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.8/workflows/create.md b/docs/versioned_docs/version-2.8/workflows/create.md index aff59bb6a..5c4dd2948 100644 --- a/docs/versioned_docs/version-2.8/workflows/create.md +++ b/docs/versioned_docs/version-2.8/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -26,8 +26,8 @@ Before you create the cluster, make sure to have a [valid configuration file](./ ### Create - - + + Choose the initial size of your cluster. The following command creates a cluster with one control-plane and two worker nodes: @@ -40,8 +40,8 @@ For details on the flags, consult the command help via `constellation create -h` *create* stores your cluster's state in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Terraform allows for an easier GitOps integration as well as meeting regulatory requirements. Since the Constellation CLI also uses Terraform under the hood, you can reuse the same Terraform files. @@ -80,8 +80,8 @@ CONSTELL_CSP=$(cat constellation-conf.yaml | yq ".provider | keys | .[0]") jq --null-input --arg cloudprovider "$CONSTELL_CSP" --arg ip "$CONSTELL_IP" --arg initsecret "$CONSTELL_INIT_SECRET" '{"cloudprovider":$cloudprovider,"ip":$ip,"initsecret":$initsecret}' > constellation-id.json ``` - - + + ## The *init* step diff --git a/docs/versioned_docs/version-2.8/workflows/recovery.md b/docs/versioned_docs/version-2.8/workflows/recovery.md index c26fb32eb..35596b8c9 100644 --- a/docs/versioned_docs/version-2.8/workflows/recovery.md +++ b/docs/versioned_docs/version-2.8/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.8/workflows/sbom.md b/docs/versioned_docs/version-2.8/workflows/sbom.md index c9dc0d5cc..6c1702dee 100644 --- a/docs/versioned_docs/version-2.8/workflows/sbom.md +++ b/docs/versioned_docs/version-2.8/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -19,7 +19,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -40,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.8/workflows/scale.md b/docs/versioned_docs/version-2.8/workflows/scale.md index 9531e90c9..46b048870 100644 --- a/docs/versioned_docs/version-2.8/workflows/scale.md +++ b/docs/versioned_docs/version-2.8/workflows/scale.md @@ -48,30 +48,30 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the worker ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + ## Control-plane node scaling @@ -79,30 +79,30 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.8/workflows/storage.md b/docs/versioned_docs/version-2.8/workflows/storage.md index d0e5b188f..be9998676 100644 --- a/docs/versioned_docs/version-2.8/workflows/storage.md +++ b/docs/versioned_docs/version-2.8/workflows/storage.md @@ -21,14 +21,14 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as ReadWriteOnce, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. @@ -36,8 +36,8 @@ This includes support for [volume snapshots](https://cloud.google.com/kubernetes You can use them to bring a volume back to a prior state or provision new volumes. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for information about the configuration. - - + + :::caution @@ -47,8 +47,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction) or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -57,8 +57,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -86,8 +86,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -115,8 +115,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + :::caution @@ -126,8 +126,8 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) @@ -186,8 +186,8 @@ The default storage class is responsible for all persistent volume claims that d Constellation creates a storage class with encryption enabled and sets this as the default class. In case you wish to change it, follow the steps below: - - + + 1. List the storage classes in your cluster: @@ -233,8 +233,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) azuredisk.csi.confidential.cloud Delete Immediate false 1d ``` - - + + 1. List the storage classes in your cluster: @@ -280,8 +280,8 @@ In case you wish to change it, follow the steps below: integrity-encrypted-rwo (default) gcp.csi.confidential.cloud Delete Immediate false 1d ``` - - + + :::caution @@ -291,5 +291,5 @@ You may use other (non-confidential) CSI drivers that are compatible with Kubern ::: - - + + diff --git a/docs/versioned_docs/version-2.8/workflows/terminate.md b/docs/versioned_docs/version-2.8/workflows/terminate.md index 647eadb42..f33489ca5 100644 --- a/docs/versioned_docs/version-2.8/workflows/terminate.md +++ b/docs/versioned_docs/version-2.8/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-id.json constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.8/workflows/troubleshooting.md b/docs/versioned_docs/version-2.8/workflows/troubleshooting.md index 2ddf3335d..cd095be28 100644 --- a/docs/versioned_docs/version-2.8/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.8/workflows/troubleshooting.md @@ -75,8 +75,8 @@ To provide information during early stages of a node's boot process, Constellati You can view this information in the following places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -86,8 +86,8 @@ You can view this information in the following places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -102,16 +102,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ### Node shell access diff --git a/docs/versioned_docs/version-2.8/workflows/trusted-launch.md b/docs/versioned_docs/version-2.8/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.8/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.8/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.8/workflows/verify-cli.md b/docs/versioned_docs/version-2.8/workflows/verify-cli.md index 1280c51b0..aa2df4be4 100644 --- a/docs/versioned_docs/version-2.8/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.8/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -33,7 +33,7 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_docs/version-2.9/architecture/attestation.md b/docs/versioned_docs/version-2.9/architecture/attestation.md index 07ac3aa72..592063193 100644 --- a/docs/versioned_docs/version-2.9/architecture/attestation.md +++ b/docs/versioned_docs/version-2.9/architecture/attestation.md @@ -121,8 +121,8 @@ Constellation allows to specify in the config which measurements should be enfor Enforcing non-reproducible measurements controlled by the cloud provider means that changes in these values require manual updates to the cluster's config. By default, Constellation only enforces measurements that are stable values produced by the infrastructure or by Constellation directly. - - + + Constellation uses the [vTPM](https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch#vtpm) feature of Azure CVMs for runtime measurements. This vTPM adheres to the [TPM 2.0](https://trustedcomputinggroup.org/resource/tpm-library-specification/) specification. @@ -152,8 +152,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) feature of CVMs on GCP for runtime measurements. Note that this vTPM doesn't run inside the hardware-protected CVM context, but is emulated by the hypervisor. @@ -185,8 +185,8 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + Constellation uses the [vTPM](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html) (NitroTPM) feature of the [AWS Nitro System](http://aws.amazon.com/ec2/nitro/) on AWS for runtime measurements. @@ -217,16 +217,16 @@ The latter means that the value can be generated offline and compared to the one | 15 | ClusterID | Constellation Bootstrapper | Yes | | 16–23 | Unused | - | - | - - + + ### CVM verification To verify the integrity of the received attestation statement, a chain of trust from the CVM technology to the interface providing the statement has to be established. For verification of the CVM technology, Constellation may expose additional options in its config file. - - + + On Azure, AMD SEV-SNP is used to provide runtime encryption to the VMs. An SEV-SNP attestation report is used to establish trust in the vTPM running inside the VM. @@ -248,18 +248,18 @@ You may customize certain parameters for verification of the attestation stateme More explicitly, it controls the verification of the `IDKeyDigest` value in the SEV-SNP attestation report. You can provide a list of accepted key digests and specify a policy on how this list is compared against the reported `IDKeyDigest`. - - + + There is no additional configuration available for GCP. - - + + There is no additional configuration available for AWS. - - + + ## Cluster attestation diff --git a/docs/versioned_docs/version-2.9/getting-started/first-steps-local.md b/docs/versioned_docs/version-2.9/getting-started/first-steps-local.md index 8fcd71811..f9cfa5cd3 100644 --- a/docs/versioned_docs/version-2.9/getting-started/first-steps-local.md +++ b/docs/versioned_docs/version-2.9/getting-started/first-steps-local.md @@ -45,8 +45,8 @@ sudo iptables -P FORWARD ACCEPT ## Create a cluster - - + + With the `constellation mini` command, you can deploy and test Constellation locally. This mode is called MiniConstellation. Conceptually, MiniConstellation is similar to [MicroK8s](https://microk8s.io/), [K3s](https://k3s.io/), and [minikube](https://minikube.sigs.k8s.io/docs/). @@ -74,8 +74,8 @@ constellation mini up This will configure your current directory as the [workspace](../architecture/orchestration.md#workspaces) for this cluster. All `constellation` commands concerning this cluster need to be issued from this directory. - - + + With the QEMU provider, you can create a local Constellation cluster as if it were in the cloud. The provider uses [QEMU](https://www.qemu.org/) to create multiple VMs for the cluster nodes, which interact with each other. @@ -153,8 +153,8 @@ attaching persistent storage, or autoscaling aren't available. export KUBECONFIG="$PWD/constellation-admin.conf" ``` - - + + ## Connect to the cluster @@ -207,8 +207,8 @@ worker-0 Ready 32s v1.24.6 ## Terminate your cluster - - + + Once you are done, you can clean up the created resources using the following command: @@ -219,8 +219,8 @@ constellation mini down This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + Once you are done, you can clean up the created resources using the following command: @@ -248,8 +248,8 @@ Your Constellation cluster was terminated successfully. This will destroy your cluster and clean up your workspace. The VM image and cluster configuration file (`constellation-conf.yaml`) will be kept and may be reused to create new clusters. - - + + ## Troubleshooting diff --git a/docs/versioned_docs/version-2.9/getting-started/first-steps.md b/docs/versioned_docs/version-2.9/getting-started/first-steps.md index 0329c5776..a29ff276c 100644 --- a/docs/versioned_docs/version-2.9/getting-started/first-steps.md +++ b/docs/versioned_docs/version-2.9/getting-started/first-steps.md @@ -15,39 +15,39 @@ If you encounter any problem with the following steps, make sure to use the [lat 1. Create the [configuration file](../workflows/config.md) for your cloud provider. - + - + ```bash constellation config generate azure ``` - + - + ```bash constellation config generate gcp ``` - + - + ```bash constellation config generate aws ``` - + - + 2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration). - + - + ```bash constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config @@ -62,9 +62,9 @@ If you encounter any problem with the following steps, make sure to use the [lat * `westeurope` * `southeastasia` - + - + ```bash constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config @@ -74,9 +74,9 @@ If you encounter any problem with the following steps, make sure to use the [lat Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. - + - + ```bash constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config @@ -103,8 +103,8 @@ If you encounter any problem with the following steps, make sure to use the [lat You can find a list of all [regions in AWS's documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). - - + + :::tip To learn about all options you have for managing IAM resources and Constellation configuration, see the [Configuration workflow](../workflows/config.md). diff --git a/docs/versioned_docs/version-2.9/getting-started/install.md b/docs/versioned_docs/version-2.9/getting-started/install.md index 0575192af..2aa274b98 100644 --- a/docs/versioned_docs/version-2.9/getting-started/install.md +++ b/docs/versioned_docs/version-2.9/getting-started/install.md @@ -18,8 +18,8 @@ Make sure the following requirements are met: The CLI executable is available at [GitHub](https://github.com/edgelesssys/constellation/releases). Install it with the following commands: - - + + 1. Download the CLI: @@ -35,8 +35,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-amd64 /usr/local/bin/constellation ``` - - + + 1. Download the CLI: @@ -52,9 +52,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-linux-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -70,9 +70,9 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-arm64 /usr/local/bin/constellation ``` - + - + 1. Download the CLI: @@ -88,8 +88,8 @@ curl -LO https://github.com/edgelesssys/constellation/releases/latest/download/c sudo install constellation-darwin-amd64 /usr/local/bin/constellation ``` - - + + :::tip The CLI supports autocompletion for various shells. To set it up, run `constellation completion` and follow the given steps. @@ -105,39 +105,42 @@ If you don't have a cloud subscription, you can also set up a [local Constellati ### Required permissions - - + + The following [resource providers need to be registered](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider) in your subscription: -* `Microsoft.Attestation` \[2] -* `Microsoft.Compute` -* `Microsoft.Insights` -* `Microsoft.ManagedIdentity` -* `Microsoft.Network` + +- `Microsoft.Attestation` +- `Microsoft.Compute` +- `Microsoft.Insights` +- `Microsoft.ManagedIdentity` +- `Microsoft.Network` By default, Constellation tries to register these automatically if they haven't been registered before. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `*/register/action` \[1] -* `Microsoft.Authorization/roleAssignments/*` -* `Microsoft.Authorization/roleDefinitions/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Resources/subscriptions/resourcegroups/*` + +- `*/register/action` \[1] +- `Microsoft.Authorization/roleAssignments/*` +- `Microsoft.Authorization/roleDefinitions/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Resources/subscriptions/resourcegroups/*` The built-in `Owner` role is a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `Microsoft.Attestation/attestationProviders/*` \[2] -* `Microsoft.Compute/virtualMachineScaleSets/*` -* `Microsoft.Insights/components/*` -* `Microsoft.ManagedIdentity/userAssignedIdentities/*` -* `Microsoft.Network/loadBalancers/*` -* `Microsoft.Network/loadBalancers/backendAddressPools/*` -* `Microsoft.Network/networkSecurityGroups/*` -* `Microsoft.Network/publicIPAddresses/*` -* `Microsoft.Network/virtualNetworks/*` -* `Microsoft.Network/virtualNetworks/subnets/*` -* `Microsoft.Network/natGateways/*` + +- `Microsoft.Attestation/attestationProviders/*` +- `Microsoft.Compute/virtualMachineScaleSets/*` +- `Microsoft.Insights/components/*` +- `Microsoft.ManagedIdentity/userAssignedIdentities/*` +- `Microsoft.Network/loadBalancers/*` +- `Microsoft.Network/loadBalancers/backendAddressPools/*` +- `Microsoft.Network/networkSecurityGroups/*` +- `Microsoft.Network/publicIPAddresses/*` +- `Microsoft.Network/virtualNetworks/*` +- `Microsoft.Network/virtualNetworks/subnets/*` +- `Microsoft.Network/natGateways/*` The built-in `Contributor` role is a superset of these permissions. @@ -145,91 +148,91 @@ Follow Microsoft's guide on [understanding](https://learn.microsoft.com/en-us/az 1: You can omit `*/register/Action` if the resource providers mentioned above are already registered and the `ARM_SKIP_PROVIDER_REGISTRATION` environment variable is set to `true` when creating the IAM configuration. -2: You can omit `Microsoft.Attestation/attestationProviders/*` and the registration of `Microsoft.Attestation` if `EnforceIDKeyDigest` isn't set to `MAAFallback` in the [config file](../workflows/config.md#configure-your-cluster). - - - + + Create a new project for Constellation or use an existing one. Enable the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com) on it. To [create the IAM configuration](../workflows/config.md#creating-an-iam-configuration) for Constellation, you need the following permissions: -* `iam.serviceAccountKeys.create` -* `iam.serviceAccountKeys.delete` -* `iam.serviceAccountKeys.get` -* `iam.serviceAccounts.create` -* `iam.serviceAccounts.delete` -* `iam.serviceAccounts.get` -* `resourcemanager.projects.getIamPolicy` -* `resourcemanager.projects.setIamPolicy` + +- `iam.serviceAccountKeys.create` +- `iam.serviceAccountKeys.delete` +- `iam.serviceAccountKeys.get` +- `iam.serviceAccounts.create` +- `iam.serviceAccounts.delete` +- `iam.serviceAccounts.get` +- `resourcemanager.projects.getIamPolicy` +- `resourcemanager.projects.setIamPolicy` Together, the built-in roles `roles/editor` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. To [create a Constellation cluster](../workflows/create.md#the-create-step), you need the following permissions: -* `compute.addresses.createInternal` -* `compute.addresses.deleteInternal` -* `compute.addresses.get` -* `compute.addresses.useInternal` -* `compute.backendServices.create` -* `compute.backendServices.delete` -* `compute.backendServices.get` -* `compute.backendServices.use` -* `compute.disks.create` -* `compute.firewalls.create` -* `compute.firewalls.delete` -* `compute.firewalls.get` -* `compute.globalAddresses.create` -* `compute.globalAddresses.delete` -* `compute.globalAddresses.get` -* `compute.globalAddresses.use` -* `compute.globalForwardingRules.create` -* `compute.globalForwardingRules.delete` -* `compute.globalForwardingRules.get` -* `compute.globalForwardingRules.setLabels` -* `compute.globalOperations.get` -* `compute.healthChecks.create` -* `compute.healthChecks.delete` -* `compute.healthChecks.get` -* `compute.healthChecks.useReadOnly` -* `compute.instanceGroupManagers.create` -* `compute.instanceGroupManagers.delete` -* `compute.instanceGroupManagers.get` -* `compute.instanceGroups.create` -* `compute.instanceGroups.delete` -* `compute.instanceGroups.get` -* `compute.instanceGroups.use` -* `compute.instances.create` -* `compute.instances.setLabels` -* `compute.instances.setMetadata` -* `compute.instances.setTags` -* `compute.instanceTemplates.create` -* `compute.instanceTemplates.delete` -* `compute.instanceTemplates.get` -* `compute.instanceTemplates.useReadOnly` -* `compute.networks.create` -* `compute.networks.delete` -* `compute.networks.get` -* `compute.networks.updatePolicy` -* `compute.routers.create` -* `compute.routers.delete` -* `compute.routers.get` -* `compute.routers.update` -* `compute.subnetworks.create` -* `compute.subnetworks.delete` -* `compute.subnetworks.get` -* `compute.subnetworks.use` -* `compute.targetTcpProxies.create` -* `compute.targetTcpProxies.delete` -* `compute.targetTcpProxies.get` -* `compute.targetTcpProxies.use` -* `iam.serviceAccounts.actAs` + +- `compute.addresses.createInternal` +- `compute.addresses.deleteInternal` +- `compute.addresses.get` +- `compute.addresses.useInternal` +- `compute.backendServices.create` +- `compute.backendServices.delete` +- `compute.backendServices.get` +- `compute.backendServices.use` +- `compute.disks.create` +- `compute.firewalls.create` +- `compute.firewalls.delete` +- `compute.firewalls.get` +- `compute.globalAddresses.create` +- `compute.globalAddresses.delete` +- `compute.globalAddresses.get` +- `compute.globalAddresses.use` +- `compute.globalForwardingRules.create` +- `compute.globalForwardingRules.delete` +- `compute.globalForwardingRules.get` +- `compute.globalForwardingRules.setLabels` +- `compute.globalOperations.get` +- `compute.healthChecks.create` +- `compute.healthChecks.delete` +- `compute.healthChecks.get` +- `compute.healthChecks.useReadOnly` +- `compute.instanceGroupManagers.create` +- `compute.instanceGroupManagers.delete` +- `compute.instanceGroupManagers.get` +- `compute.instanceGroups.create` +- `compute.instanceGroups.delete` +- `compute.instanceGroups.get` +- `compute.instanceGroups.use` +- `compute.instances.create` +- `compute.instances.setLabels` +- `compute.instances.setMetadata` +- `compute.instances.setTags` +- `compute.instanceTemplates.create` +- `compute.instanceTemplates.delete` +- `compute.instanceTemplates.get` +- `compute.instanceTemplates.useReadOnly` +- `compute.networks.create` +- `compute.networks.delete` +- `compute.networks.get` +- `compute.networks.updatePolicy` +- `compute.routers.create` +- `compute.routers.delete` +- `compute.routers.get` +- `compute.routers.update` +- `compute.subnetworks.create` +- `compute.subnetworks.delete` +- `compute.subnetworks.get` +- `compute.subnetworks.use` +- `compute.targetTcpProxies.create` +- `compute.targetTcpProxies.delete` +- `compute.targetTcpProxies.get` +- `compute.targetTcpProxies.use` +- `iam.serviceAccounts.actAs` Together, the built-in roles `roles/editor`, `roles/compute.instanceAdmin` and `roles/resourcemanager.projectIamAdmin` form a superset of these permissions. Follow Google's guide on [understanding](https://cloud.google.com/iam/docs/understanding-roles) and [assigning roles](https://cloud.google.com/iam/docs/granting-changing-revoking-access). - - + + To set up a Constellation cluster, you need to perform two tasks that require permissions: create the infrastructure and create roles for cluster nodes. Both of these actions can be performed by different users, e.g., an administrator to create roles and a DevOps engineer to create the infrastructure. @@ -364,8 +367,8 @@ The built-in `PowerUserAccess` policy is a superset of these permissions. Follow Amazon's guide on [understanding](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [managing policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html). - - + + ### Authentication @@ -375,8 +378,8 @@ You need to authenticate with your CSP. The following lists the required steps f The steps for a *testing* environment are simpler. However, they may expose secrets to the CSP. If in doubt, follow the *production* steps. ::: - - + + **Testing** @@ -392,8 +395,8 @@ az login Other options are described in Azure's [authentication guide](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). - - + + **Testing** @@ -416,8 +419,8 @@ Use one of the following options on a trusted machine: Follow [Google's guide](https://cloud.google.com/docs/authentication/production#manually) for setting up your credentials. - - + + **Testing** @@ -433,9 +436,9 @@ aws configure Options and first steps are described in the [AWS CLI documentation](https://docs.aws.amazon.com/cli/index.html). - + - + ## Next steps diff --git a/docs/versioned_docs/version-2.9/overview/clouds.md b/docs/versioned_docs/version-2.9/overview/clouds.md index c56a623b1..dfc3d5307 100644 --- a/docs/versioned_docs/version-2.9/overview/clouds.md +++ b/docs/versioned_docs/version-2.9/overview/clouds.md @@ -31,7 +31,7 @@ This firmware is signed by Azure. The signature is reflected in the remote-attestation statements of CVMs. Thus, the Azure closed-source firmware becomes part of Constellation's trusted computing base (TCB). -\* Recently, Azure [announced](https://techcommunity.microsoft.com/t5/azure-confidential-computing/azure-confidential-vms-using-sev-snp-dcasv5-ecasv5-are-now/ba-p/3573747) the *limited preview* of CVMs with customizable firmware. With this CVM type, (4) switches from *No* to *Yes*. Constellation will support customizable firmware on Azure in the future. +\* Recently, [Azure announced the open source paravisor OpenHCL](https://techcommunity.microsoft.com/blog/windowsosplatform/openhcl-the-new-open-source-paravisor/4273172). It's the foundation for fully open source and verifiable CVM firmware. Once Azure provides their CVM firmware with reproducible builds based on OpenHCL, (4) switches from *No* to *Yes*. Constellation will support OpenHCL based firmware on Azure in the future. ## Google Cloud Platform (GCP) diff --git a/docs/versioned_docs/version-2.9/overview/confidential-kubernetes.md b/docs/versioned_docs/version-2.9/overview/confidential-kubernetes.md index 2b6c6ed17..1441c833a 100644 --- a/docs/versioned_docs/version-2.9/overview/confidential-kubernetes.md +++ b/docs/versioned_docs/version-2.9/overview/confidential-kubernetes.md @@ -23,9 +23,9 @@ With the above, Constellation wraps an entire cluster into one coherent and veri ![Confidential Kubernetes](../_media/concept-constellation.svg) -## Contrast: Managed Kubernetes with CVMs +## Comparison: Managed Kubernetes with CVMs -In contrast, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. +In comparison, managed Kubernetes with CVMs, as it's for example offered in [AKS](https://azure.microsoft.com/en-us/services/kubernetes-service/) and [GKE](https://cloud.google.com/kubernetes-engine), only provides runtime encryption for certain worker nodes. Here, each worker node is a separate (and typically unverified) confidential context. This only provides limited security benefits as it only prevents direct access to a worker node's memory. The large majority of potential attacks through the infrastructure remain unaffected. This includes attacks through the control plane, access to external key management, and the corruption of worker node images. This leaves many problems unsolved. For instance, *Node A* has no means to verify if *Node B* is "good" and if it's OK to share data with it. Consequently, this approach leaves a large attack surface, as is depicted in the following. ![Concept: Managed Kubernetes plus CVMs](../_media/concept-managed.svg) diff --git a/docs/versioned_docs/version-2.9/workflows/config.md b/docs/versioned_docs/version-2.9/workflows/config.md index f276f3f63..43313d88e 100644 --- a/docs/versioned_docs/version-2.9/workflows/config.md +++ b/docs/versioned_docs/version-2.9/workflows/config.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -14,49 +14,49 @@ Before you can create your cluster, you need to configure the identity and acces You can generate a configuration file for your CSP by using the following CLI command: - - + + ```bash constellation config generate azure ``` - - + + ```bash constellation config generate gcp ``` - - + + ```bash constellation config generate aws ``` - - + + This creates the file `constellation-conf.yaml` in the current directory. ## Choosing a VM type Constellation supports the following VM types: - - + + By default, Constellation uses `Standard_DC4as_v5` CVMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. For CVMs, any VM type with a minimum of 4 vCPUs from the [DCasv5 & DCadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/dcasv5-dcadsv5-series) or [ECasv5 & ECadsv5](https://docs.microsoft.com/en-us/azure/virtual-machines/ecasv5-ecadsv5-series) families is supported. You can also run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `n2d-standard-4` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. Supported are all machines with a minimum of 4 vCPUs from the [C2D](https://cloud.google.com/compute/docs/compute-optimized-machines#c2d_machine_types) or [N2D](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machines) family. You can run `constellation config instance-types` to get the list of all supported options. - - + + By default, Constellation uses `m6a.xlarge` VMs (4 vCPUs, 16 GB RAM) to create your cluster. Optionally, you can switch to a different VM type by modifying **instanceType** in the configuration file. @@ -75,8 +75,8 @@ AWS is currently investigating the issue. SNP-based attestation will be enabled as soon as a fix is verified. ::: - - + + Fill the desired VM type into the **instanceType** field in the `constellation-conf.yml` file. @@ -90,8 +90,8 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. If you already have a Constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration. Furthermore, the flag updates the zone/region of the configuration if it hasn't been set yet. - - + + You must be authenticated with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -111,8 +111,8 @@ Note that CVMs are currently only supported in a few regions, check [Azure's pro Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [GCP CLI](https://cloud.google.com/sdk/gcloud) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -126,8 +126,8 @@ Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + + You must be authenticated with the [AWS CLI](https://aws.amazon.com/en/cli/) in the shell session with a user that has the [required permissions for IAM creation](../getting-started/install.md#set-up-cloud-credentials). @@ -151,16 +151,16 @@ You can find a list of all [regions in AWS's documentation](https://docs.aws.ama Paste the output into the corresponding fields of the `constellation-conf.yaml` file. - - + +
Alternatively, you can manually create the IAM configuration on your CSP. The following describes the configuration fields and how you obtain the required information or create the required resources. - - + + * **subscription**: The UUID of your Azure subscription, e.g., `8b8bd01f-efd9-4113-9bd1-c82137c32da7`. @@ -189,9 +189,9 @@ The following describes the configuration fields and how you obtain the required The user-assigned identity is used by instances of the cluster to access other cloud resources. For more information about managed identities refer to [Azure's documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities). - + - + * **project**: The ID of your GCP project, e.g., `constellation-129857`. @@ -215,9 +215,9 @@ The following describes the configuration fields and how you obtain the required Afterward, create and download a new JSON key for this service account. Place the downloaded file in your Constellation workspace, and set the config parameter to the filename, e.g., `constellation-129857-15343dba46cb.json`. - + - + * **region**: The name of your chosen AWS data center region, e.g., `us-east-2`. @@ -248,9 +248,9 @@ The following describes the configuration fields and how you obtain the required Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. - + - +
Now that you've configured your CSP, you can [create your cluster](./create.md). diff --git a/docs/versioned_docs/version-2.9/workflows/create.md b/docs/versioned_docs/version-2.9/workflows/create.md index aff59bb6a..5c4dd2948 100644 --- a/docs/versioned_docs/version-2.9/workflows/create.md +++ b/docs/versioned_docs/version-2.9/workflows/create.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -26,8 +26,8 @@ Before you create the cluster, make sure to have a [valid configuration file](./ ### Create - - + + Choose the initial size of your cluster. The following command creates a cluster with one control-plane and two worker nodes: @@ -40,8 +40,8 @@ For details on the flags, consult the command help via `constellation create -h` *create* stores your cluster's state in a [`constellation-terraform`](../architecture/orchestration.md#cluster-creation-process) directory in your workspace. - - + + Terraform allows for an easier GitOps integration as well as meeting regulatory requirements. Since the Constellation CLI also uses Terraform under the hood, you can reuse the same Terraform files. @@ -80,8 +80,8 @@ CONSTELL_CSP=$(cat constellation-conf.yaml | yq ".provider | keys | .[0]") jq --null-input --arg cloudprovider "$CONSTELL_CSP" --arg ip "$CONSTELL_IP" --arg initsecret "$CONSTELL_INIT_SECRET" '{"cloudprovider":$cloudprovider,"ip":$ip,"initsecret":$initsecret}' > constellation-id.json ``` - - + + ## The *init* step diff --git a/docs/versioned_docs/version-2.9/workflows/recovery.md b/docs/versioned_docs/version-2.9/workflows/recovery.md index c26fb32eb..35596b8c9 100644 --- a/docs/versioned_docs/version-2.9/workflows/recovery.md +++ b/docs/versioned_docs/version-2.9/workflows/recovery.md @@ -16,8 +16,8 @@ You can check the health status of the nodes via the cloud service provider (CSP Constellation provides logging information on the boot process and status via [cloud logging](troubleshooting.md#cloud-logging). In the following, you'll find detailed descriptions for identifying clusters stuck in recovery for each CSP. - - + + In the Azure portal, find the cluster's resource group. Inside the resource group, open the control plane *Virtual machine scale set* `constellation-scale-set-controlplanes-`. @@ -51,8 +51,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, check that the control plane *Instance Group* has enough members in a *Ready* state. In the GCP Console, go to **Instance Groups** and check the group for the cluster's control plane `-control-plane-`. @@ -87,8 +87,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + First, open the AWS console to view all Auto Scaling Groups (ASGs) in the region of your cluster. Select the ASG of the control plane `--control-plane` and check that enough members are in a *Running* state. @@ -118,8 +118,8 @@ If this fails due to an unhealthy control plane, you will see log messages simil This means that you have to recover the node manually. - - + + ## Recover a cluster diff --git a/docs/versioned_docs/version-2.9/workflows/sbom.md b/docs/versioned_docs/version-2.9/workflows/sbom.md index c9dc0d5cc..6c1702dee 100644 --- a/docs/versioned_docs/version-2.9/workflows/sbom.md +++ b/docs/versioned_docs/version-2.9/workflows/sbom.md @@ -1,6 +1,6 @@ # Consume software bill of materials (SBOMs) - + --- @@ -19,7 +19,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). Make sure the key is available in a file named `cosign.pub` to execute the following examples. ::: @@ -40,7 +40,7 @@ cosign verify-blob --key cosign.pub --signature constellation.spdx.sbom.sig cons ### Container Images -SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/signing/other_types#sboms-software-bill-of-materials) and uploaded to the same registry. +SBOMs for container images are [attached to the image using Cosign](https://docs.sigstore.dev/cosign/signing/other_types/#sboms-software-bill-of-materials) and uploaded to the same registry. As a consumer, use cosign to download and verify the SBOM: diff --git a/docs/versioned_docs/version-2.9/workflows/scale.md b/docs/versioned_docs/version-2.9/workflows/scale.md index 06898ad0c..63b727c7d 100644 --- a/docs/versioned_docs/version-2.9/workflows/scale.md +++ b/docs/versioned_docs/version-2.9/workflows/scale.md @@ -51,30 +51,30 @@ kubectl -n kube-system get nodes Alternatively, you can manually scale your cluster up or down: - - + + 1. Find your Constellation resource group. 2. Select the `scale-set-workers`. 3. Go to **settings** and **scaling**. 4. Set the new **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **worker** instance group. 3. Set the new **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the worker ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + ## Control-plane node scaling @@ -82,30 +82,30 @@ Control-plane nodes can **only be scaled manually and only scaled up**! To increase the number of control-plane nodes, follow these steps: - + - + 1. Find your Constellation resource group. 2. Select the `scale-set-controlplanes`. 3. Go to **settings** and **scaling**. 4. Set the new (increased) **instance count** and **save**. - - + + 1. In Compute Engine go to [Instance Groups](https://console.cloud.google.com/compute/instanceGroups/). 2. **Edit** the **control-plane** instance group. 3. Set the new (increased) **number of instances** and **save**. - - + + 1. Go to Auto Scaling Groups and select the control-plane ASG to scale up. 2. Click **Edit** 3. Set the new (increased) **Desired capacity** and **Update**. - - + + If you scale down the number of control-planes nodes, the removed nodes won't be able to exit the `etcd` cluster correctly. This will endanger the quorum that's required to run a stable Kubernetes control plane. diff --git a/docs/versioned_docs/version-2.9/workflows/storage.md b/docs/versioned_docs/version-2.9/workflows/storage.md index 9e3d96346..06fbc4de6 100644 --- a/docs/versioned_docs/version-2.9/workflows/storage.md +++ b/docs/versioned_docs/version-2.9/workflows/storage.md @@ -21,30 +21,30 @@ For more details see [encrypted persistent storage](../architecture/encrypted-st Constellation supports the following drivers, which offer node-level encryption and optional integrity protection. - - + + **Constellation CSI driver for Azure Disk**: Mount Azure [Disk Storage](https://azure.microsoft.com/en-us/services/storage/disks/#overview) into your Constellation cluster. See the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-azuredisk-csi-driver) for more information. Since Azure Disks are mounted as `ReadWriteOnce`, they're only available to a single pod. - - + + **Constellation CSI driver for GCP Persistent Disk**: Mount [Persistent Disk](https://cloud.google.com/persistent-disk) block storage into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver) for more information. - - + + **Constellation CSI driver for AWS Elastic Block Store** Mount [Elastic Block Store](https://aws.amazon.com/ebs/) storage volumes into your Constellation cluster. Follow the instructions on how to [install the Constellation CSI driver](#installation) or check out the [repository](https://github.com/edgelesssys/constellation-aws-ebs-csi-driver) for more information. - - + + Note that in case the options above aren't a suitable solution for you, Constellation is compatible with all other CSI-based storage options. For example, you can use [AWS EFS](https://docs.aws.amazon.com/en_en/eks/latest/userguide/efs-csi.html), [Azure Files](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction), or [GCP Filestore](https://cloud.google.com/filestore) with Constellation out of the box. Constellation is just not providing transparent encryption on the node level for these storage types yet. @@ -53,8 +53,8 @@ Note that in case the options above aren't a suitable solution for you, Constell The Constellation CLI automatically installs Constellation's CSI driver for the selected CSP in your cluster. If you don't need a CSI driver or wish to deploy your own, you can disable the automatic installation by setting `deployCSIDriver` to `false` in your Constellation config file. - - + + Azure comes with two storage classes by default. @@ -82,8 +82,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + GCP comes with two storage classes by default. @@ -111,8 +111,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + AWS comes with two storage classes by default. @@ -140,8 +140,8 @@ Note that volume expansion isn't supported for integrity-protected disks. ::: - - + + 1. Create a [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) diff --git a/docs/versioned_docs/version-2.9/workflows/terminate.md b/docs/versioned_docs/version-2.9/workflows/terminate.md index 647eadb42..f33489ca5 100644 --- a/docs/versioned_docs/version-2.9/workflows/terminate.md +++ b/docs/versioned_docs/version-2.9/workflows/terminate.md @@ -4,7 +4,7 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- @@ -16,8 +16,8 @@ All ephemeral storage and state of your cluster will be lost. Make sure any data ::: - - + + Terminate the cluster by running: ```bash @@ -40,8 +40,8 @@ resources manually. Just run the `terminate` command again afterward to continue ::: - - + + Terminate the cluster by running: ```bash @@ -56,5 +56,5 @@ rm constellation-id.json constellation-admin.conf Only the `constellation-mastersecret.json` and the configuration file remain. - - + + diff --git a/docs/versioned_docs/version-2.9/workflows/troubleshooting.md b/docs/versioned_docs/version-2.9/workflows/troubleshooting.md index 2ddf3335d..cd095be28 100644 --- a/docs/versioned_docs/version-2.9/workflows/troubleshooting.md +++ b/docs/versioned_docs/version-2.9/workflows/troubleshooting.md @@ -75,8 +75,8 @@ To provide information during early stages of a node's boot process, Constellati You can view this information in the following places: - - + + 1. In your Azure subscription find the Constellation resource group. 2. Inside the resource group find the Application Insights resource called `constellation-insights-*`. @@ -86,8 +86,8 @@ You can view this information in the following places: To **find the disk UUIDs** use the following query: `traces | where message contains "Disk UUID"` - - + + 1. Select the project that hosts Constellation. 2. Go to the `Compute Engine` service. @@ -102,16 +102,16 @@ Constellation uses the default bucket to store logs. Its [default retention peri ::: - - + + 1. Open [AWS CloudWatch](https://console.aws.amazon.com/cloudwatch/home) 2. Select [Log Groups](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) 3. Select the log group that matches the name of your cluster. 4. Select the log stream for control or worker type nodes. - - + + ### Node shell access diff --git a/docs/versioned_docs/version-2.9/workflows/trusted-launch.md b/docs/versioned_docs/version-2.9/workflows/trusted-launch.md index 13bd63ba6..11d0a096c 100644 --- a/docs/versioned_docs/version-2.9/workflows/trusted-launch.md +++ b/docs/versioned_docs/version-2.9/workflows/trusted-launch.md @@ -14,7 +14,7 @@ Constellation supports trusted launch VMs with instance types `Standard_D*_v4` a Azure currently doesn't support [community galleries for trusted launch VMs](https://docs.microsoft.com/en-us/azure/virtual-machines/share-gallery-community). Thus, you need to manually import the Constellation node image into your cloud subscription. -The latest image is available at . Simply adjust the version number to download a newer version. +The latest image is available at `https://cdn.confidential.cloud/constellation/images/azure/trusted-launch/v2.2.0/constellation.img`. Simply adjust the version number to download a newer version. After you've downloaded the image, create a resource group `constellation-images` in your Azure subscription and import the image. You can use a script to do this: @@ -26,6 +26,7 @@ AZURE_IMAGE_VERSION=2.2.0 AZURE_RESOURCE_GROUP_NAME=constellation-images AZURE_I ``` The script creates the following resources: + 1. A new image gallery with the default name `constellation-import` 2. A new image definition with the default name `constellation` 3. The actual image with the provided version. In this case `2.2.0` diff --git a/docs/versioned_docs/version-2.9/workflows/verify-cli.md b/docs/versioned_docs/version-2.9/workflows/verify-cli.md index 1280c51b0..aa2df4be4 100644 --- a/docs/versioned_docs/version-2.9/workflows/verify-cli.md +++ b/docs/versioned_docs/version-2.9/workflows/verify-cli.md @@ -4,11 +4,11 @@ This recording presents the essence of this page. It's recommended to read it in full for the motivation and all details. ::: - + --- -Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/signing/quickstart), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at . +Edgeless Systems uses [sigstore](https://www.sigstore.dev/) and [SLSA](https://slsa.dev) to ensure supply-chain security for the Constellation CLI and node images ("artifacts"). sigstore consists of three components: [Cosign](https://docs.sigstore.dev/cosign/signing/overview/), [Rekor](https://docs.sigstore.dev/logging/overview), and Fulcio. Edgeless Systems uses Cosign to sign artifacts. All signatures are uploaded to the public Rekor transparency log, which resides at `https://rekor.sigstore.dev`. :::note The public key for Edgeless Systems' long-term code-signing key is: @@ -20,7 +20,7 @@ JmEe5iSLvG1SyQSAew7WdMKF6o9t8e2TFuCkzlOhhlws2OHWbiFZnFWCFw== -----END PUBLIC KEY----- ``` -The public key is also available for download at and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). +The public key is also available for download at [https://edgeless.systems/es.pub](https://edgeless.systems/es.pub) and in the Twitter profile [@EdgelessSystems](https://twitter.com/EdgelessSystems). ::: The Rekor transparency log is a public append-only ledger that verifies and records signatures and associated metadata. The Rekor transparency log enables everyone to observe the sequence of (software) signatures issued by Edgeless Systems and many other parties. The transparency log allows for the public identification of dubious or malicious signatures. @@ -33,7 +33,7 @@ You don't need to verify the Constellation node images. This is done automatical ## Verify the signature -First, [install the Cosign CLI](https://docs.sigstore.dev/system_config/installation). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: +First, [install the Cosign CLI](https://docs.sigstore.dev/cosign/system_config/installation/). Next, [download](https://github.com/edgelesssys/constellation/releases) and verify the signature that accompanies your CLI executable, for example: ```shell-session $ cosign verify-blob --key https://edgeless.systems/es.pub --signature constellation-linux-amd64.sig constellation-linux-amd64 diff --git a/docs/versioned_sidebars/version-2.10-sidebars.json b/docs/versioned_sidebars/version-2.10-sidebars.json index 02898994d..9d47f4b26 100644 --- a/docs/versioned_sidebars/version-2.10-sidebars.json +++ b/docs/versioned_sidebars/version-2.10-sidebars.json @@ -40,6 +40,11 @@ "id": "overview/performance/performance" }, "items": [ + { + "type": "doc", + "label": "Compute benchmarks", + "id": "overview/performance/compute" + }, { "type": "doc", "label": "I/O benchmarks", diff --git a/docs/versioned_sidebars/version-2.11-sidebars.json b/docs/versioned_sidebars/version-2.11-sidebars.json index 17740bcca..8e0ad0ffb 100644 --- a/docs/versioned_sidebars/version-2.11-sidebars.json +++ b/docs/versioned_sidebars/version-2.11-sidebars.json @@ -40,6 +40,11 @@ "id": "overview/performance/performance" }, "items": [ + { + "type": "doc", + "label": "Compute benchmarks", + "id": "overview/performance/compute" + }, { "type": "doc", "label": "I/O benchmarks", diff --git a/docs/versioned_sidebars/version-2.12-sidebars.json b/docs/versioned_sidebars/version-2.12-sidebars.json index 81aaba77d..e4c845754 100644 --- a/docs/versioned_sidebars/version-2.12-sidebars.json +++ b/docs/versioned_sidebars/version-2.12-sidebars.json @@ -40,6 +40,11 @@ "id": "overview/performance/performance" }, "items": [ + { + "type": "doc", + "label": "Compute benchmarks", + "id": "overview/performance/compute" + }, { "type": "doc", "label": "I/O benchmarks", diff --git a/docs/versioned_sidebars/version-2.13-sidebars.json b/docs/versioned_sidebars/version-2.13-sidebars.json index 38caa4ac8..6317fc3f0 100644 --- a/docs/versioned_sidebars/version-2.13-sidebars.json +++ b/docs/versioned_sidebars/version-2.13-sidebars.json @@ -40,6 +40,11 @@ "id": "overview/performance/performance" }, "items": [ + { + "type": "doc", + "label": "Compute benchmarks", + "id": "overview/performance/compute" + }, { "type": "doc", "label": "I/O benchmarks", diff --git a/docs/versioned_sidebars/version-2.14-sidebars.json b/docs/versioned_sidebars/version-2.14-sidebars.json index 80e7edbea..ed97049b8 100644 --- a/docs/versioned_sidebars/version-2.14-sidebars.json +++ b/docs/versioned_sidebars/version-2.14-sidebars.json @@ -40,6 +40,11 @@ "id": "overview/performance/performance" }, "items": [ + { + "type": "doc", + "label": "Compute benchmarks", + "id": "overview/performance/compute" + }, { "type": "doc", "label": "I/O benchmarks", diff --git a/docs/versioned_sidebars/version-2.15-sidebars.json b/docs/versioned_sidebars/version-2.15-sidebars.json index b137f339c..09b5ec04e 100644 --- a/docs/versioned_sidebars/version-2.15-sidebars.json +++ b/docs/versioned_sidebars/version-2.15-sidebars.json @@ -40,6 +40,11 @@ "id": "overview/performance/performance" }, "items": [ + { + "type": "doc", + "label": "Compute benchmarks", + "id": "overview/performance/compute" + }, { "type": "doc", "label": "I/O benchmarks", diff --git a/docs/versioned_sidebars/version-2.16-sidebars.json b/docs/versioned_sidebars/version-2.16-sidebars.json index b137f339c..09b5ec04e 100644 --- a/docs/versioned_sidebars/version-2.16-sidebars.json +++ b/docs/versioned_sidebars/version-2.16-sidebars.json @@ -40,6 +40,11 @@ "id": "overview/performance/performance" }, "items": [ + { + "type": "doc", + "label": "Compute benchmarks", + "id": "overview/performance/compute" + }, { "type": "doc", "label": "I/O benchmarks", diff --git a/docs/versioned_sidebars/version-2.17-sidebars.json b/docs/versioned_sidebars/version-2.17-sidebars.json new file mode 100644 index 000000000..09b5ec04e --- /dev/null +++ b/docs/versioned_sidebars/version-2.17-sidebars.json @@ -0,0 +1,299 @@ +{ + "docs": [ + { + "type": "doc", + "label": "Introduction", + "id": "intro" + }, + { + "type": "category", + "label": "Basics", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Confidential Kubernetes", + "id": "overview/confidential-kubernetes" + }, + { + "type": "doc", + "label": "Security benefits", + "id": "overview/security-benefits" + }, + { + "type": "doc", + "label": "Product features", + "id": "overview/product" + }, + { + "type": "doc", + "label": "Feature status of clouds", + "id": "overview/clouds" + }, + { + "type": "category", + "label": "Performance", + "link": { + "type": "doc", + "id": "overview/performance/performance" + }, + "items": [ + { + "type": "doc", + "label": "Compute benchmarks", + "id": "overview/performance/compute" + }, + { + "type": "doc", + "label": "I/O benchmarks", + "id": "overview/performance/io" + }, + { + "type": "doc", + "label": "Application benchmarks", + "id": "overview/performance/application" + } + ] + }, + { + "type": "doc", + "label": "License", + "id": "overview/license" + } + ] + }, + { + "type": "category", + "label": "Getting started", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Installation", + "id": "getting-started/install" + }, + { + "type": "doc", + "label": "First steps (cloud)", + "id": "getting-started/first-steps" + }, + { + "type": "doc", + "label": "First steps (local)", + "id": "getting-started/first-steps-local" + }, + { + "type": "doc", + "label": "Cloud Marketplaces", + "id": "getting-started/marketplaces" + }, + { + "type": "category", + "label": "Examples", + "link": { + "type": "doc", + "id": "getting-started/examples" + }, + "items": [ + { + "type": "doc", + "label": "Emojivoto", + "id": "getting-started/examples/emojivoto" + }, + { + "type": "doc", + "label": "Online Boutique", + "id": "getting-started/examples/online-boutique" + }, + { + "type": "doc", + "label": "Horizontal Pod Autoscaling", + "id": "getting-started/examples/horizontal-scaling" + }, + { + "type": "doc", + "label": "Filestash with s3proxy", + "id": "getting-started/examples/filestash-s3proxy" + } + ] + } + ] + }, + { + "type": "category", + "label": "Workflows", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Verify the CLI", + "id": "workflows/verify-cli" + }, + { + "type": "doc", + "label": "Configure your cluster", + "id": "workflows/config" + }, + { + "type": "doc", + "label": "Create your cluster", + "id": "workflows/create" + }, + { + "type": "doc", + "label": "Scale your cluster", + "id": "workflows/scale" + }, + { + "type": "doc", + "label": "Upgrade your cluster", + "id": "workflows/upgrade" + }, + { + "type": "doc", + "label": "Expose a service", + "id": "workflows/lb" + }, + { + "type": "doc", + "label": "Install cert-manager", + "id": "workflows/cert-manager" + }, + { + "type": "doc", + "label": "Install s3proxy", + "id": "workflows/s3proxy" + }, + { + "type": "doc", + "label": "Terminate your cluster", + "id": "workflows/terminate" + }, + { + "type": "doc", + "label": "Recover your cluster", + "id": "workflows/recovery" + }, + { + "type": "doc", + "label": "Verify your cluster", + "id": "workflows/verify-cluster" + }, + { + "type": "doc", + "label": "Use persistent storage", + "id": "workflows/storage" + }, + { + "type": "doc", + "label": "Use the Terraform provider", + "id": "workflows/terraform-provider" + }, + { + "type": "doc", + "label": "Consume SBOMs", + "id": "workflows/sbom" + }, + { + "type": "doc", + "label": "Troubleshooting", + "id": "workflows/troubleshooting" + } + ] + }, + { + "type": "category", + "label": "Architecture", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Overview", + "id": "architecture/overview" + }, + { + "type": "doc", + "label": "Cluster orchestration", + "id": "architecture/orchestration" + }, + { + "type": "doc", + "label": "Versions and support", + "id": "architecture/versions" + }, + { + "type": "doc", + "label": "Microservices", + "id": "architecture/microservices" + }, + { + "type": "doc", + "label": "Attestation", + "id": "architecture/attestation" + }, + { + "type": "doc", + "label": "Images", + "id": "architecture/images" + }, + { + "type": "doc", + "label": "Keys and cryptographic primitives", + "id": "architecture/keys" + }, + { + "type": "doc", + "label": "Encrypted persistent storage", + "id": "architecture/encrypted-storage" + }, + { + "type": "doc", + "label": "Networking", + "id": "architecture/networking" + }, + { + "type": "doc", + "label": "Observability", + "id": "architecture/observability" + } + ] + }, + { + "type": "category", + "label": "Reference", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "CLI", + "id": "reference/cli" + }, + { + "type": "doc", + "label": "Configuration migrations", + "id": "reference/migration" + }, + { + "type": "doc", + "label": "Terraform usage", + "id": "reference/terraform" + }, + { + "type": "doc", + "label": "SLSA adoption", + "id": "reference/slsa" + } + ] + } + ] +} diff --git a/docs/versioned_sidebars/version-2.18-sidebars.json b/docs/versioned_sidebars/version-2.18-sidebars.json new file mode 100644 index 000000000..09b5ec04e --- /dev/null +++ b/docs/versioned_sidebars/version-2.18-sidebars.json @@ -0,0 +1,299 @@ +{ + "docs": [ + { + "type": "doc", + "label": "Introduction", + "id": "intro" + }, + { + "type": "category", + "label": "Basics", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Confidential Kubernetes", + "id": "overview/confidential-kubernetes" + }, + { + "type": "doc", + "label": "Security benefits", + "id": "overview/security-benefits" + }, + { + "type": "doc", + "label": "Product features", + "id": "overview/product" + }, + { + "type": "doc", + "label": "Feature status of clouds", + "id": "overview/clouds" + }, + { + "type": "category", + "label": "Performance", + "link": { + "type": "doc", + "id": "overview/performance/performance" + }, + "items": [ + { + "type": "doc", + "label": "Compute benchmarks", + "id": "overview/performance/compute" + }, + { + "type": "doc", + "label": "I/O benchmarks", + "id": "overview/performance/io" + }, + { + "type": "doc", + "label": "Application benchmarks", + "id": "overview/performance/application" + } + ] + }, + { + "type": "doc", + "label": "License", + "id": "overview/license" + } + ] + }, + { + "type": "category", + "label": "Getting started", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Installation", + "id": "getting-started/install" + }, + { + "type": "doc", + "label": "First steps (cloud)", + "id": "getting-started/first-steps" + }, + { + "type": "doc", + "label": "First steps (local)", + "id": "getting-started/first-steps-local" + }, + { + "type": "doc", + "label": "Cloud Marketplaces", + "id": "getting-started/marketplaces" + }, + { + "type": "category", + "label": "Examples", + "link": { + "type": "doc", + "id": "getting-started/examples" + }, + "items": [ + { + "type": "doc", + "label": "Emojivoto", + "id": "getting-started/examples/emojivoto" + }, + { + "type": "doc", + "label": "Online Boutique", + "id": "getting-started/examples/online-boutique" + }, + { + "type": "doc", + "label": "Horizontal Pod Autoscaling", + "id": "getting-started/examples/horizontal-scaling" + }, + { + "type": "doc", + "label": "Filestash with s3proxy", + "id": "getting-started/examples/filestash-s3proxy" + } + ] + } + ] + }, + { + "type": "category", + "label": "Workflows", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Verify the CLI", + "id": "workflows/verify-cli" + }, + { + "type": "doc", + "label": "Configure your cluster", + "id": "workflows/config" + }, + { + "type": "doc", + "label": "Create your cluster", + "id": "workflows/create" + }, + { + "type": "doc", + "label": "Scale your cluster", + "id": "workflows/scale" + }, + { + "type": "doc", + "label": "Upgrade your cluster", + "id": "workflows/upgrade" + }, + { + "type": "doc", + "label": "Expose a service", + "id": "workflows/lb" + }, + { + "type": "doc", + "label": "Install cert-manager", + "id": "workflows/cert-manager" + }, + { + "type": "doc", + "label": "Install s3proxy", + "id": "workflows/s3proxy" + }, + { + "type": "doc", + "label": "Terminate your cluster", + "id": "workflows/terminate" + }, + { + "type": "doc", + "label": "Recover your cluster", + "id": "workflows/recovery" + }, + { + "type": "doc", + "label": "Verify your cluster", + "id": "workflows/verify-cluster" + }, + { + "type": "doc", + "label": "Use persistent storage", + "id": "workflows/storage" + }, + { + "type": "doc", + "label": "Use the Terraform provider", + "id": "workflows/terraform-provider" + }, + { + "type": "doc", + "label": "Consume SBOMs", + "id": "workflows/sbom" + }, + { + "type": "doc", + "label": "Troubleshooting", + "id": "workflows/troubleshooting" + } + ] + }, + { + "type": "category", + "label": "Architecture", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Overview", + "id": "architecture/overview" + }, + { + "type": "doc", + "label": "Cluster orchestration", + "id": "architecture/orchestration" + }, + { + "type": "doc", + "label": "Versions and support", + "id": "architecture/versions" + }, + { + "type": "doc", + "label": "Microservices", + "id": "architecture/microservices" + }, + { + "type": "doc", + "label": "Attestation", + "id": "architecture/attestation" + }, + { + "type": "doc", + "label": "Images", + "id": "architecture/images" + }, + { + "type": "doc", + "label": "Keys and cryptographic primitives", + "id": "architecture/keys" + }, + { + "type": "doc", + "label": "Encrypted persistent storage", + "id": "architecture/encrypted-storage" + }, + { + "type": "doc", + "label": "Networking", + "id": "architecture/networking" + }, + { + "type": "doc", + "label": "Observability", + "id": "architecture/observability" + } + ] + }, + { + "type": "category", + "label": "Reference", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "CLI", + "id": "reference/cli" + }, + { + "type": "doc", + "label": "Configuration migrations", + "id": "reference/migration" + }, + { + "type": "doc", + "label": "Terraform usage", + "id": "reference/terraform" + }, + { + "type": "doc", + "label": "SLSA adoption", + "id": "reference/slsa" + } + ] + } + ] +} diff --git a/docs/versioned_sidebars/version-2.19-sidebars.json b/docs/versioned_sidebars/version-2.19-sidebars.json new file mode 100644 index 000000000..09b5ec04e --- /dev/null +++ b/docs/versioned_sidebars/version-2.19-sidebars.json @@ -0,0 +1,299 @@ +{ + "docs": [ + { + "type": "doc", + "label": "Introduction", + "id": "intro" + }, + { + "type": "category", + "label": "Basics", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Confidential Kubernetes", + "id": "overview/confidential-kubernetes" + }, + { + "type": "doc", + "label": "Security benefits", + "id": "overview/security-benefits" + }, + { + "type": "doc", + "label": "Product features", + "id": "overview/product" + }, + { + "type": "doc", + "label": "Feature status of clouds", + "id": "overview/clouds" + }, + { + "type": "category", + "label": "Performance", + "link": { + "type": "doc", + "id": "overview/performance/performance" + }, + "items": [ + { + "type": "doc", + "label": "Compute benchmarks", + "id": "overview/performance/compute" + }, + { + "type": "doc", + "label": "I/O benchmarks", + "id": "overview/performance/io" + }, + { + "type": "doc", + "label": "Application benchmarks", + "id": "overview/performance/application" + } + ] + }, + { + "type": "doc", + "label": "License", + "id": "overview/license" + } + ] + }, + { + "type": "category", + "label": "Getting started", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Installation", + "id": "getting-started/install" + }, + { + "type": "doc", + "label": "First steps (cloud)", + "id": "getting-started/first-steps" + }, + { + "type": "doc", + "label": "First steps (local)", + "id": "getting-started/first-steps-local" + }, + { + "type": "doc", + "label": "Cloud Marketplaces", + "id": "getting-started/marketplaces" + }, + { + "type": "category", + "label": "Examples", + "link": { + "type": "doc", + "id": "getting-started/examples" + }, + "items": [ + { + "type": "doc", + "label": "Emojivoto", + "id": "getting-started/examples/emojivoto" + }, + { + "type": "doc", + "label": "Online Boutique", + "id": "getting-started/examples/online-boutique" + }, + { + "type": "doc", + "label": "Horizontal Pod Autoscaling", + "id": "getting-started/examples/horizontal-scaling" + }, + { + "type": "doc", + "label": "Filestash with s3proxy", + "id": "getting-started/examples/filestash-s3proxy" + } + ] + } + ] + }, + { + "type": "category", + "label": "Workflows", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Verify the CLI", + "id": "workflows/verify-cli" + }, + { + "type": "doc", + "label": "Configure your cluster", + "id": "workflows/config" + }, + { + "type": "doc", + "label": "Create your cluster", + "id": "workflows/create" + }, + { + "type": "doc", + "label": "Scale your cluster", + "id": "workflows/scale" + }, + { + "type": "doc", + "label": "Upgrade your cluster", + "id": "workflows/upgrade" + }, + { + "type": "doc", + "label": "Expose a service", + "id": "workflows/lb" + }, + { + "type": "doc", + "label": "Install cert-manager", + "id": "workflows/cert-manager" + }, + { + "type": "doc", + "label": "Install s3proxy", + "id": "workflows/s3proxy" + }, + { + "type": "doc", + "label": "Terminate your cluster", + "id": "workflows/terminate" + }, + { + "type": "doc", + "label": "Recover your cluster", + "id": "workflows/recovery" + }, + { + "type": "doc", + "label": "Verify your cluster", + "id": "workflows/verify-cluster" + }, + { + "type": "doc", + "label": "Use persistent storage", + "id": "workflows/storage" + }, + { + "type": "doc", + "label": "Use the Terraform provider", + "id": "workflows/terraform-provider" + }, + { + "type": "doc", + "label": "Consume SBOMs", + "id": "workflows/sbom" + }, + { + "type": "doc", + "label": "Troubleshooting", + "id": "workflows/troubleshooting" + } + ] + }, + { + "type": "category", + "label": "Architecture", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "Overview", + "id": "architecture/overview" + }, + { + "type": "doc", + "label": "Cluster orchestration", + "id": "architecture/orchestration" + }, + { + "type": "doc", + "label": "Versions and support", + "id": "architecture/versions" + }, + { + "type": "doc", + "label": "Microservices", + "id": "architecture/microservices" + }, + { + "type": "doc", + "label": "Attestation", + "id": "architecture/attestation" + }, + { + "type": "doc", + "label": "Images", + "id": "architecture/images" + }, + { + "type": "doc", + "label": "Keys and cryptographic primitives", + "id": "architecture/keys" + }, + { + "type": "doc", + "label": "Encrypted persistent storage", + "id": "architecture/encrypted-storage" + }, + { + "type": "doc", + "label": "Networking", + "id": "architecture/networking" + }, + { + "type": "doc", + "label": "Observability", + "id": "architecture/observability" + } + ] + }, + { + "type": "category", + "label": "Reference", + "link": { + "type": "generated-index" + }, + "items": [ + { + "type": "doc", + "label": "CLI", + "id": "reference/cli" + }, + { + "type": "doc", + "label": "Configuration migrations", + "id": "reference/migration" + }, + { + "type": "doc", + "label": "Terraform usage", + "id": "reference/terraform" + }, + { + "type": "doc", + "label": "SLSA adoption", + "id": "reference/slsa" + } + ] + } + ] +} diff --git a/docs/versions.json b/docs/versions.json index 2d1f36c9c..89f88399a 100644 --- a/docs/versions.json +++ b/docs/versions.json @@ -1,4 +1,7 @@ [ + "2.19", + "2.18", + "2.17", "2.16", "2.15", "2.14", diff --git a/e2e/internal/upgrade/BUILD.bazel b/e2e/internal/upgrade/BUILD.bazel index 6e368e94f..8acfc7e94 100644 --- a/e2e/internal/upgrade/BUILD.bazel +++ b/e2e/internal/upgrade/BUILD.bazel @@ -47,6 +47,7 @@ go_test( "//e2e/internal/kubectl", "//internal/constants", "//internal/versions", + "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", "@io_k8s_api//core/v1:core", "@io_k8s_apimachinery//pkg/apis/meta/v1:meta", diff --git a/e2e/internal/upgrade/upgrade.go b/e2e/internal/upgrade/upgrade.go index 14eb2227a..fd2483259 100644 --- a/e2e/internal/upgrade/upgrade.go +++ b/e2e/internal/upgrade/upgrade.go @@ -142,7 +142,6 @@ func testNodesEventuallyHaveVersion(t *testing.T, k *kubernetes.Clientset, targe if key == "constellation.edgeless.systems/node-image" { if !strings.EqualFold(value, targetVersions.ImageRef) { log.Printf("\t%s: Image %s, want %s\n", node.Name, value, targetVersions.ImageRef) - fmt.Printf("\tP: %s: Image %s, want %s\n", node.Name, value, targetVersions.ImageRef) allUpdated = false } } @@ -154,11 +153,6 @@ func testNodesEventuallyHaveVersion(t *testing.T, k *kubernetes.Clientset, targe log.Printf("\t%s: K8s (Kubelet) %s, want %s\n", node.Name, kubeletVersion, targetVersions.Kubernetes) allUpdated = false } - kubeProxyVersion := node.Status.NodeInfo.KubeProxyVersion - if kubeProxyVersion != string(targetVersions.Kubernetes) { - log.Printf("\t%s: K8s (Proxy) %s, want %s\n", node.Name, kubeProxyVersion, targetVersions.Kubernetes) - allUpdated = false - } } } return allUpdated @@ -188,7 +182,8 @@ func runCommandWithSeparateOutputs(cmd *exec.Cmd) (stdout, stderr []byte, err er return } - continuouslyPrintOutput := func(r io.Reader, prefix string) { + continuouslyPrintOutput := func(r io.Reader, prefix string, wg *sync.WaitGroup) { + defer wg.Done() scanner := bufio.NewScanner(r) for scanner.Scan() { output := scanner.Text() @@ -202,12 +197,15 @@ func runCommandWithSeparateOutputs(cmd *exec.Cmd) (stdout, stderr []byte, err er } } - go continuouslyPrintOutput(stdoutIn, "stdout") - go continuouslyPrintOutput(stderrIn, "stderr") + wg := &sync.WaitGroup{} + wg.Add(2) + go continuouslyPrintOutput(stdoutIn, "stdout", wg) + go continuouslyPrintOutput(stderrIn, "stderr", wg) if err = cmd.Wait(); err != nil { err = fmt.Errorf("wait for command to finish: %w", err) } + wg.Wait() return stdout, stderr, err } @@ -303,10 +301,10 @@ func getCLIPath(cliPathFlag string) (string, error) { pathCLI := os.Getenv("PATH_CLI") var relCLIPath string switch { - case pathCLI != "": - relCLIPath = pathCLI case cliPathFlag != "": relCLIPath = cliPathFlag + case pathCLI != "": + relCLIPath = pathCLI default: return "", errors.New("neither 'PATH_CLI' nor 'cli' flag set") } diff --git a/e2e/internal/upgrade/upgrade_test.go b/e2e/internal/upgrade/upgrade_test.go index 4206348f2..be47bb197 100644 --- a/e2e/internal/upgrade/upgrade_test.go +++ b/e2e/internal/upgrade/upgrade_test.go @@ -23,6 +23,7 @@ import ( "github.com/edgelesssys/constellation/v2/e2e/internal/kubectl" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/versions" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" coreV1 "k8s.io/api/core/v1" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -81,7 +82,8 @@ func TestUpgrade(t *testing.T) { log.Println(string(data)) log.Println("Checking upgrade.") - runUpgradeCheck(require, cli, *targetKubernetes) + assert := assert.New(t) // use assert because this part is more brittle and should not fail the entire test + runUpgradeCheck(assert, cli, *targetKubernetes) log.Println("Triggering upgrade.") runUpgradeApply(require, cli) @@ -170,25 +172,25 @@ func testNodesEventuallyAvailable(t *testing.T, k *kubernetes.Clientset, wantCon // runUpgradeCheck executes 'upgrade check' and does basic checks on the output. // We can not check images upgrades because we might use unpublished images. CLI uses public CDN to check for available images. -func runUpgradeCheck(require *require.Assertions, cli, targetKubernetes string) { +func runUpgradeCheck(assert *assert.Assertions, cli, targetKubernetes string) { cmd := exec.CommandContext(context.Background(), cli, "upgrade", "check", "--debug") stdout, stderr, err := runCommandWithSeparateOutputs(cmd) - require.NoError(err, "Stdout: %s\nStderr: %s", string(stdout), string(stderr)) + assert.NoError(err, "Stdout: %s\nStderr: %s", string(stdout), string(stderr)) - require.Contains(string(stdout), "The following updates are available with this CLI:") - require.Contains(string(stdout), "Kubernetes:") + assert.Contains(string(stdout), "The following updates are available with this CLI:") + assert.Contains(string(stdout), "Kubernetes:") log.Printf("targetKubernetes: %s\n", targetKubernetes) if targetKubernetes == "" { log.Printf("true\n") - require.True(containsAny(string(stdout), versions.SupportedK8sVersions())) + assert.True(containsAny(string(stdout), versions.SupportedK8sVersions())) } else { log.Printf("false. targetKubernetes: %s\n", targetKubernetes) - require.Contains(string(stdout), targetKubernetes, fmt.Sprintf("Expected Kubernetes version %s in output.", targetKubernetes)) + assert.Contains(string(stdout), targetKubernetes, fmt.Sprintf("Expected Kubernetes version %s in output.", targetKubernetes)) } - require.Contains(string(stdout), "Services:") - require.Contains(string(stdout), fmt.Sprintf("--> %s", constants.BinaryVersion().String())) + assert.Contains(string(stdout), "Services:") + assert.Contains(string(stdout), fmt.Sprintf("--> %s", constants.BinaryVersion().String())) log.Println(string(stdout)) } diff --git a/e2e/malicious-join/malicious-join.go b/e2e/malicious-join/malicious-join.go index 2ef649771..7e416242a 100644 --- a/e2e/malicious-join/malicious-join.go +++ b/e2e/malicious-join/malicious-join.go @@ -156,7 +156,7 @@ type maliciousJoiner struct { // join issues a join request to the join service endpoint. func (j *maliciousJoiner) join(ctx context.Context) (*joinproto.IssueJoinTicketResponse, error) { j.logger.Debug(fmt.Sprintf("Dialing join service endpoint %q", j.endpoint)) - conn, err := j.dialer.Dial(ctx, j.endpoint) + conn, err := j.dialer.Dial(j.endpoint) if err != nil { return nil, fmt.Errorf("dialing join service endpoint: %w", err) } @@ -172,10 +172,10 @@ func (j *maliciousJoiner) join(ctx context.Context) (*joinproto.IssueJoinTicketR IsControlPlane: false, } res, err := protoClient.IssueJoinTicket(ctx, req) - j.logger.Debug("Got join ticket response", "apiServerEndpoint", res.ApiServerEndpoint, "kubernetesVersion", res.KubernetesVersion) if err != nil { return nil, fmt.Errorf("issuing join ticket: %w", err) } + j.logger.Debug("Got join ticket response", "apiServerEndpoint", res.ApiServerEndpoint, "kubernetesVersion", res.KubernetesVersion) return res, nil } diff --git a/e2e/miniconstellation/.terraform.lock.hcl b/e2e/miniconstellation/.terraform.lock.hcl index b29acb322..2e5970afe 100644 --- a/e2e/miniconstellation/.terraform.lock.hcl +++ b/e2e/miniconstellation/.terraform.lock.hcl @@ -2,74 +2,56 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "3.92.0" - constraints = "3.92.0" + version = "4.1.0" + constraints = "4.1.0" hashes = [ - "h1:+bZPRgjpUA6LivvMIS1UdwRWUgzoYBp/nhEpbL4aXHM=", - "h1:D5lngW1uKlPM2EUCdNG1f2FvPGHYRklDFN8b2jPCIpM=", - "h1:nTP2ZYfuEpMP+PkkgRdhQphNmWWJuKdE9Z4TzeC7ydo=", - "h1:sqVZftg9rJGDiiPiY9l1V/a+5CWkxNcj22sBu8HsJBY=", - "h1:swoRk2drVrD8v7GrW/2OJSk06v2I2zGk3XPAgBDbw9A=", - "zh:04292e149676ba956d738e85faeb6d6ebd3759e8310f1c4155e67402eb5ae0f7", - "zh:0963b4528f25d01d5c733e17de31e2c0b94790fd02931b2a47cd051b20dd0d96", - "zh:133563e16e8a4a7139ac11d94e68de8d1d5e3a62a532e64ac936735d7b1e04db", - "zh:2b219f1b40881d3bdd89257c916f255a7e36904ddc65dbbafee80763661b4636", - "zh:4b4e11a4e3716b290b3b173dfd15b06814b2f6f148f663e3c67a677c95526339", - "zh:5607c7bff3019c3b31488be1a8a9d77a96d27b199a1d8b789e4c2d4c90805674", - "zh:6469aef7728947dacb47785e6082d2d95ebd336a8798f3be6cece5a13145108c", - "zh:69e563f4e6397e1ebaef6f554d296238ec1d9dadc4b865c36743bd8366a888da", - "zh:887a223b7a9ec4e66634dbb65d9dcc53f0be06d058d9a209927ad49702ae790c", - "zh:b03c273367885c5489a24c31859af81ea58cb169431c0da97a175945ec968f53", - "zh:dd7b704ceaf98ce591e111a9c5085465c946f4f8f357089c0e27e990a669ba39", + "h1:K2OLOYxwF/onOegr+Y6Sfu/DjEjDLobQBBrLBF3i9TI=", + "h1:cwtEEnEESVOgcxtXGz0A2wXCiNZIzm3dC2xHmYuxg9M=", + "h1:dKXFrVrjv579ax6iX4wc6lmEAVFsr3iTDjErnPHIjH4=", + "h1:iqN6KxIOGYv0N1p5xfNTgsjvDHpE3bZM8s5vIAEgfnQ=", + "h1:qDmSr5+vMVdWmfBEaIwqSLo5ZLyYk7KYoJo5flny6lk=", + "zh:3f332bca3a8b7dc982e428e09c73862d1afda34c2ad7803e70d8ba7b9e2445fd", + "zh:66b7e4a7a4fd06e0a5a3a22b4f76bda48e50ed3dd26c388738d9cc882b801bce", + "zh:6a271175d6e079241f24129f5026e0b16f04e7a548807f115600003d615e0ec3", + "zh:7a6abc7e2ae8d1041d0446bbe87156e0436639676ee1fad40321e8ee6759a454", + "zh:903f6e7f03e5952347ce6ee589d58c829179f2f22220f25cf52ae4efecd7053c", + "zh:a572b9834cf3b51799c82c5009705c59309d947a6ecdb7e17729868c55e7d0e0", + "zh:a7fca14338f0cfb82b17ce085400c210cbc986a87086702e3a11efcb4e53d6e4", + "zh:af36c7004702b0a273794914a17a77af1eb972caaad64e0068739e55c1488845", + "zh:b36f308db1cdc02dee659e3e518186d7dec970d88b6149be3f6b3f8d544e4282", + "zh:bedf6d13cf4bccc128d8cbb0703a3a8b547629674439ffda5e73563ab775d0f7", + "zh:d1df286a2e5d4a5f6a7f4d29700a25588167ccffa31c686550ef617503df3254", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/cloudinit" { - version = "2.3.3" - constraints = "2.3.3" + version = "2.3.4" + constraints = "2.3.4" hashes = [ - "h1:6utKe3l0lf4+hw+uVK8XJVNdOmp7tOTcycyFvv1pGAA=", - "h1:GmJ8PxLjjPr+lh02Bw3u7RYqA3UtpE2hQ1T43Vt7PTQ=", - "h1:TCZQjXesJ9qbOZaHjJse/WyOxYQwp7wUX3VNxL/qo1c=", - "h1:U6EC4/cJJ6Df3LztUQ/I4YuljGQQeQ+LdLndAwSSiTs=", - "h1:ZmQ97fIcPW7hj/vynRB4zbtObK0Z/LVJPvCwlNd78zA=", - "zh:0bd6ee14ca5cf0f0c83d3bb965346b1225ccd06a6247e80774aaaf54c729daa7", - "zh:3055ad0dcc98de1d4e45b72c5889ae91b62f4ae4e54dbc56c4821be0fdfbed91", - "zh:32764cfcff0d7379ca8b7dde376ac5551854d454c5881945f1952b785a312fa2", - "zh:55c2a4dc3ebdeaa1dec3a36db96dab253c7fa10b9fe1209862e1ee77a01e0aa1", - "zh:5c71f260ba5674d656d12f67cde3bb494498e6b6b6e66945ef85688f185dcf63", + "h1:+J2rgfJH5B0vyFR0Wfcoyt4SHWfZLDe+WtUMtmZLDeY=", + "h1:/Ty/HXg0Bti5T+Zk6XvhwEHyKGiOV5LzCrbLiekjuLU=", + "h1:S3j8poSaLbaftlKq2STBkQEkZH253ZLaHhBHBifdpBQ=", + "h1:TSeGg71hzb+ahU16viRNFxDVgpC3krXqK9Lm4dg9v3Y=", + "h1:ZJGY2ywdCKnbMMAlyAv0n5cwVpHaicKVheNYbdCkZTw=", + "h1:cVIIhnXweOHavu1uV2bdKScTjLbM1WnKM/25wqYBJWo=", + "h1:iDq03pOzp/UsXya2h+32VOOrvGdJgI9L2/EZJoN9t4A=", + "h1:jTcgflH266LJFwqejIEHndaLn+TwrrYqim3rQmw15qI=", + "h1:mPi6Snl6LCYgO2tMxEs+YMuKw+YQ1MJ3E+uf+f/74yA=", + "h1:pb1C8Lrfp4VnPRm6Uo+jEWbKvqsGunHxDO7pWtc/yRI=", + "h1:qsx0lvgUWVL7D2EvWAuO+WyOO/fVneGD8FG2REcNVhI=", + "zh:09f1f1e1d232da96fbf9513b0fb5263bc2fe9bee85697aa15d40bb93835efbeb", + "zh:381e74b90d7a038c3a8dcdcc2ce8c72d6b86da9f208a27f4b98cabe1a1032773", + "zh:398eb321949e28c4c5f7c52e9b1f922a10d0b2b073b7db04cb69318d24ffc5a9", + "zh:4a425679614a8f0fe440845828794e609b35af17db59134c4f9e56d61e979813", + "zh:4d955d8608ece4984c9f1dacda2a59fdb4ea6b0243872f049b388181aab8c80a", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:9617280a853ec7caedb8beb7864e4b29faf9c850a453283980c28fccef2c493d", - "zh:ac8bda21950f8dddade3e9bc15f7bcfdee743738483be5724169943cafa611f5", - "zh:ba9ab567bbe63dee9197a763b3104ea9217ba27449ed54d3afa6657f412e3496", - "zh:effd1a7e34bae3879c02f03ed3afa979433a518e11de1f8afd35a8710231ac14", - "zh:f021538c86d0ac250d75e59efde6d869bbfff711eb744c8bddce79d2475bf46d", - "zh:f1e3984597948a2103391a26600e177b19f16a5a4c66acee27a4343fb141571f", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "3.6.0" - constraints = "3.6.0" - hashes = [ - "h1:5KeoKSVKVHJW308uiTgslxFbjQAdWzBGUFK68vgMRWY=", - "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", - "h1:R5Ucn26riKIEijcsiOMBR3uOAjuOMfI1x7XvH4P6B1w=", - "h1:p6WG1IPHnqx1fnJVKNjv733FBaArIugqy58HRZnpPCk=", - "h1:t0mRdJzegohRKhfdoQEJnv3JRISSezJRblN0HIe67vo=", - "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", - "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", - "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", - "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", - "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", - "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", - "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", - "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", - "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", - "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", + "zh:a48fbee1d58d55a1f4c92c2f38c83a37c8b2f2701ed1a3c926cefb0801fa446a", + "zh:b748fe6631b16a1dafd35a09377c3bffa89552af584cf95f47568b6cd31fc241", + "zh:d4b931f7a54603fa4692a2ec6e498b95464babd2be072bed5c7c2e140a280d99", + "zh:f1c9337fcfe3a7be39d179eb7986c22a979cfb2c587c05f1b3b83064f41785c5", + "zh:f58fc57edd1ee3250a28943cd84de3e4b744cdb52df0356a53403fc240240636", + "zh:f5f50de0923ff530b03e1bca0ac697534d61bb3e5fc7f60e13becb62229097a9", ] } diff --git a/e2e/miniconstellation/BUILD.bazel b/e2e/miniconstellation/BUILD.bazel index 836b2d075..e8df73984 100644 --- a/e2e/miniconstellation/BUILD.bazel +++ b/e2e/miniconstellation/BUILD.bazel @@ -9,6 +9,7 @@ filegroup( "main.tf", "output.tf", "test-remote.sh", + "variables.tf", ], ) diff --git a/e2e/miniconstellation/main.sh.in b/e2e/miniconstellation/main.sh.in index 694f17bb3..f25975554 100755 --- a/e2e/miniconstellation/main.sh.in +++ b/e2e/miniconstellation/main.sh.in @@ -23,6 +23,11 @@ cd e2e/miniconstellation echo "::group::Terraform" +random_string=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 6) +rg_name="e2e-mini-${random_string}" +echo "rgname=${rg_name}" >> "${GITHUB_OUTPUT:-/dev/null}" +echo "resource_name = \"${rg_name}\"" > terraform.tfvars + terraform init terraform apply -auto-approve terraform output -raw ssh_private_key > id_rsa diff --git a/e2e/miniconstellation/main.tf b/e2e/miniconstellation/main.tf index 094a217e2..601f0a3fb 100644 --- a/e2e/miniconstellation/main.tf +++ b/e2e/miniconstellation/main.tf @@ -2,11 +2,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.92.0" - } - random = { - source = "hashicorp/random" - version = "3.6.0" + version = "4.1.0" } tls = { source = "hashicorp/tls" @@ -14,7 +10,7 @@ terraform { } cloudinit = { source = "hashicorp/cloudinit" - version = "2.3.3" + version = "2.3.4" } } } @@ -22,15 +18,13 @@ terraform { provider "azurerm" { use_oidc = true features {} + # This enables all resource providers. + # In the future, we might want to use `resource_providers_to_register` to registers just the ones we need. + resource_provider_registrations = "all" } provider "tls" {} -resource "random_string" "suffix" { - length = 6 - special = false -} - resource "tls_private_key" "ssh_key" { algorithm = "RSA" rsa_bits = 2048 @@ -47,26 +41,26 @@ data "cloudinit_config" "cloud_init" { } resource "azurerm_resource_group" "main" { - name = "e2e-mini-${random_string.suffix.result}" - location = "North Europe" + name = var.resource_name + location = "West Europe" } resource "azurerm_virtual_network" "main" { - name = "e2e-mini-${random_string.suffix.result}" + name = var.resource_name address_space = ["10.0.0.0/16"] location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name } resource "azurerm_subnet" "main" { - name = "e2e-mini-${random_string.suffix.result}" + name = var.resource_name resource_group_name = azurerm_resource_group.main.name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.0.2.0/24"] } resource "azurerm_public_ip" "main" { - name = "e2e-mini-${random_string.suffix.result}" + name = var.resource_name location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name allocation_method = "Static" @@ -74,7 +68,7 @@ resource "azurerm_public_ip" "main" { } resource "azurerm_network_interface" "main" { - name = "e2e-mini-${random_string.suffix.result}" + name = var.resource_name resource_group_name = azurerm_resource_group.main.name location = azurerm_resource_group.main.location @@ -87,7 +81,7 @@ resource "azurerm_network_interface" "main" { } resource "azurerm_network_security_group" "ssh" { - name = "e2e-mini-${random_string.suffix.result}" + name = var.resource_name resource_group_name = azurerm_resource_group.main.name location = azurerm_resource_group.main.location @@ -110,7 +104,7 @@ resource "azurerm_subnet_network_security_group_association" "ssh" { } resource "azurerm_linux_virtual_machine" "main" { - name = "e2e-mini-${random_string.suffix.result}" + name = var.resource_name resource_group_name = azurerm_resource_group.main.name location = azurerm_resource_group.main.location diff --git a/e2e/miniconstellation/variables.tf b/e2e/miniconstellation/variables.tf new file mode 100644 index 000000000..eb2034c7f --- /dev/null +++ b/e2e/miniconstellation/variables.tf @@ -0,0 +1,4 @@ +variable "resource_name" { + type = string + description = "name for resources to create" +} diff --git a/flake.lock b/flake.lock index d53c97aa4..a633bfa33 100644 --- a/flake.lock +++ b/flake.lock @@ -18,13 +18,29 @@ "type": "github" } }, - "nixpkgsUnstable": { + "nixpkgsBazel": { "locked": { - "lastModified": 1715161350, - "narHash": "sha256-5ZU8DVwHO0gjw2sKoKkToYOXMJFRBpRsa17Ebm8fgj0=", + "lastModified": 1717414489, + "narHash": "sha256-fhvJv8hkJwotkqxhoSQfvh6UfKG+sTYIQ3hchariEDk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c4200cb341ee794775185ecd4105fbbfb5ca73a0", + "rev": "c429fa2ffa21229eeadbe37c11a47aff35f53ce0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c429fa2ffa21229eeadbe37c11a47aff35f53ce0", + "type": "github" + } + }, + "nixpkgsUnstable": { + "locked": { + "lastModified": 1725816686, + "narHash": "sha256-0Kq2MkQ/sQX1rhWJ/ySBBQlBJBUK8mPMDcuDhhdBkSU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "add0443ee587a0c44f22793b8c8649a0dbc3bb00", "type": "github" }, "original": { @@ -37,6 +53,7 @@ "root": { "inputs": { "flake-utils": "flake-utils", + "nixpkgsBazel": "nixpkgsBazel", "nixpkgsUnstable": "nixpkgsUnstable", "uplosi": "uplosi" } @@ -66,11 +83,11 @@ ] }, "locked": { - "lastModified": 1714468720, - "narHash": "sha256-i/RVCoeQLeOaPaEtJS/l+42CVohMucA6cBBt0mdJ4uE=", + "lastModified": 1725522308, + "narHash": "sha256-AtsFZ92WkVkH8fd0Xa0D6/PR84/dtOH6gpM4mtn32Hk=", "owner": "edgelesssys", "repo": "uplosi", - "rev": "7c881351a2f7c664d04c4e235562e5b427b167f2", + "rev": "c8a482de299b5442f558d7381f0cbf898e0de0e1", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index ff88be0b5..ddd1521c7 100644 --- a/flake.nix +++ b/flake.nix @@ -5,6 +5,11 @@ nixpkgsUnstable = { url = "github:NixOS/nixpkgs/nixpkgs-unstable"; }; + # TODO(msanft): Remove once https://github.com/NixOS/nixpkgs/commit/c429fa2ffa21229eeadbe37c11a47aff35f53ce0 + # lands in nixpkgs-unstable. + nixpkgsBazel = { + url = "github:NixOS/nixpkgs/c429fa2ffa21229eeadbe37c11a47aff35f53ce0"; + }; flake-utils = { url = "github:numtide/flake-utils"; }; @@ -16,73 +21,98 @@ }; outputs = - { self - , nixpkgsUnstable - , flake-utils - , uplosi - }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgsUnstable = import nixpkgsUnstable { inherit system; }; - - callPackage = pkgsUnstable.callPackage; - - mkosiDev = (pkgsUnstable.mkosi.overrideAttrs (oldAttrs: rec { - propagatedBuildInputs = oldAttrs.propagatedBuildInputs ++ (with pkgsUnstable; [ - # package management - dnf5 - rpm - createrepo_c - - # filesystem tools - squashfsTools # mksquashfs - dosfstools # mkfs.vfat - mtools # mcopy - cryptsetup # dm-verity - util-linux # flock - kmod # depmod - cpio # cpio - zstd # zstd - xz # xz - - # utils - gnused # sed - gnugrep # grep - ]); - })); - - uplosiDev = uplosi.outputs.packages."${system}".uplosi; - - openssl-static = pkgsUnstable.openssl.override { static = true; }; - - bazel_7 = callPackage ./nix/packages/bazel.nix { pkgs = pkgsUnstable; nixpkgs = nixpkgsUnstable; }; - - in { - packages.mkosi = mkosiDev; + self, + nixpkgsUnstable, + nixpkgsBazel, + flake-utils, + uplosi, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgsUnstable = import nixpkgsUnstable { inherit system; }; - packages.uplosi = uplosiDev; + bazelPkgsUnstable = import nixpkgsBazel { inherit system; }; - packages.openssl = callPackage ./nix/cc/openssl.nix { pkgs = pkgsUnstable; }; + callPackage = pkgsUnstable.callPackage; - packages.cryptsetup = callPackage ./nix/cc/cryptsetup.nix { pkgs = pkgsUnstable; pkgsLinux = import nixpkgsUnstable { system = "x86_64-linux"; }; }; + mkosiDev = ( + pkgsUnstable.mkosi.overrideAttrs (oldAttrs: rec { + propagatedBuildInputs = + oldAttrs.propagatedBuildInputs + ++ (with pkgsUnstable; [ + # package management + dnf5 + rpm + createrepo_c - packages.libvirt = callPackage ./nix/cc/libvirt.nix { pkgs = pkgsUnstable; pkgsLinux = import nixpkgsUnstable { system = "x86_64-linux"; }; }; + # filesystem tools + squashfsTools # mksquashfs + dosfstools # mkfs.vfat + mtools # mcopy + cryptsetup # dm-verity + util-linux # flock + kmod # depmod + cpio # cpio + zstd # zstd + xz # xz - packages.libvirtd_base = callPackage ./nix/container/libvirtd_base.nix { pkgs = pkgsUnstable; pkgsLinux = import nixpkgsUnstable { system = "x86_64-linux"; }; }; + # utils + gnused # sed + gnugrep # grep + ]); + }) + ); - packages.vpn = callPackage ./nix/container/vpn/vpn.nix { pkgs = pkgsUnstable; pkgsLinux = import nixpkgsUnstable { system = "x86_64-linux"; }; }; + uplosiDev = uplosi.outputs.packages."${system}".uplosi; - packages.awscli2 = pkgsUnstable.awscli2; + openssl-static = pkgsUnstable.openssl.override { static = true; }; - packages.bazel_7 = bazel_7; + bazel_7 = bazelPkgsUnstable.callPackage ./nix/packages/bazel.nix { + pkgs = bazelPkgsUnstable; + nixpkgs = nixpkgsBazel; + }; - packages.createrepo_c = pkgsUnstable.createrepo_c; + in + { + packages.mkosi = mkosiDev; - packages.dnf5 = pkgsUnstable.dnf5; + packages.uplosi = uplosiDev; - devShells.default = callPackage ./nix/shells/default.nix { inherit bazel_7; }; + packages.openssl = callPackage ./nix/cc/openssl.nix { pkgs = pkgsUnstable; }; - formatter = nixpkgsUnstable.legacyPackages.${system}.nixpkgs-fmt; - }); + packages.cryptsetup = callPackage ./nix/cc/cryptsetup.nix { + pkgs = pkgsUnstable; + pkgsLinux = import nixpkgsUnstable { system = "x86_64-linux"; }; + }; + + packages.libvirt = callPackage ./nix/cc/libvirt.nix { + pkgs = pkgsUnstable; + pkgsLinux = import nixpkgsUnstable { system = "x86_64-linux"; }; + }; + + packages.libvirtd_base = callPackage ./nix/container/libvirtd_base.nix { + pkgs = pkgsUnstable; + pkgsLinux = import nixpkgsUnstable { system = "x86_64-linux"; }; + }; + + packages.vpn = callPackage ./nix/container/vpn/vpn.nix { + pkgs = pkgsUnstable; + pkgsLinux = import nixpkgsUnstable { system = "x86_64-linux"; }; + }; + + packages.awscli2 = pkgsUnstable.awscli2; + + packages.bazel_7 = bazel_7; + + packages.createrepo_c = pkgsUnstable.createrepo_c; + + packages.dnf5 = pkgsUnstable.dnf5; + + devShells.default = callPackage ./nix/shells/default.nix { inherit bazel_7; }; + + formatter = nixpkgsUnstable.legacyPackages.${system}.nixpkgs-fmt; + } + ); } diff --git a/go.mod b/go.mod index 22a04cf78..d9a8d61a2 100644 --- a/go.mod +++ b/go.mod @@ -1,167 +1,156 @@ module github.com/edgelesssys/constellation/v2 -go 1.22.3 +go 1.23.2 -replace ( - k8s.io/api v0.0.0 => k8s.io/api v0.29.0 - k8s.io/apiextensions-apiserver v0.0.0 => k8s.io/apiextensions-apiserver v0.29.0 - k8s.io/apimachinery v0.0.0 => k8s.io/apimachinery v0.29.0 - k8s.io/apiserver v0.0.0 => k8s.io/apiserver v0.29.0 - k8s.io/cli-runtime v0.0.0 => k8s.io/cli-runtime v0.29.0 - k8s.io/client-go v0.0.0 => k8s.io/client-go v0.29.0 - k8s.io/cloud-provider v0.0.0 => k8s.io/cloud-provider v0.29.0 - k8s.io/cluster-bootstrap v0.0.0 => k8s.io/cluster-bootstrap v0.29.0 - k8s.io/code-generator v0.0.0 => k8s.io/code-generator v0.29.0 - k8s.io/component-base v0.0.0 => k8s.io/component-base v0.29.0 - k8s.io/component-helpers v0.0.0 => k8s.io/component-helpers v0.29.0 - k8s.io/controller-manager v0.0.0 => k8s.io/controller-manager v0.29.0 - k8s.io/cri-api v0.0.0 => k8s.io/cri-api v0.29.0 - k8s.io/csi-translation-lib v0.0.0 => k8s.io/csi-translation-lib v0.29.0 - k8s.io/dynamic-resource-allocation v0.0.0 => k8s.io/dynamic-resource-allocation v0.29.0 - k8s.io/endpointslice v0.0.0 => k8s.io/endpointslice v0.29.0 - k8s.io/kube-aggregator v0.0.0 => k8s.io/kube-aggregator v0.29.0 - k8s.io/kube-controller-manager v0.0.0 => k8s.io/kube-controller-manager v0.29.0 - k8s.io/kube-proxy v0.0.0 => k8s.io/kube-proxy v0.29.0 - k8s.io/kube-scheduler v0.0.0 => k8s.io/kube-scheduler v0.29.0 - k8s.io/kubectl v0.0.0 => k8s.io/kubectl v0.29.0 - k8s.io/kubelet v0.0.0 => k8s.io/kubelet v0.29.0 - k8s.io/kubernetes v0.0.0 => k8s.io/kubernetes v1.29.0 - k8s.io/legacy-cloud-providers v0.0.0 => k8s.io/legacy-cloud-providers v0.29.0 - k8s.io/metrics v0.0.0 => k8s.io/metrics v0.29.0 - k8s.io/mount-utils v0.0.0 => k8s.io/mount-utils v0.29.0 - k8s.io/pod-security-admission v0.0.0 => k8s.io/pod-security-admission v0.29.0 - k8s.io/sample-apiserver v0.0.0 => k8s.io/sample-apiserver v0.29.0 -) +// TODO(daniel-weisse): revert after merging https://github.com/martinjungblut/go-cryptsetup/pull/16. +replace github.com/martinjungblut/go-cryptsetup => github.com/daniel-weisse/go-cryptsetup v0.0.0-20230705150314-d8c07bd1723c +// Kubernetes replace directives are required because we depend on k8s.io/kubernetes/cmd/kubeadm +// k8s discourages usage of k8s.io/kubernetes as a dependency, but no external staging repositories for kubeadm exist. +// Our code does not actually depend on these packages, but `go mod download` breaks without this replace directive. +// See this issue: https://github.com/kubernetes/kubernetes/issues/79384 +// And this README: https://github.com/kubernetes/kubernetes/blob/master/staging/README.md replace ( - github.com/martinjungblut/go-cryptsetup => github.com/daniel-weisse/go-cryptsetup v0.0.0-20230705150314-d8c07bd1723c - github.com/tink-crypto/tink-go/v2 v2.0.0 => github.com/derpsteb/tink-go/v2 v2.0.0-20231002051717-a808e454eed6 + k8s.io/cloud-provider => k8s.io/cloud-provider v0.31.1 + k8s.io/controller-manager => k8s.io/controller-manager v0.31.1 + k8s.io/cri-client => k8s.io/cri-client v0.31.1 + k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.31.1 + k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.31.1 + k8s.io/endpointslice => k8s.io/endpointslice v0.31.1 + k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.31.1 + k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.31.1 + k8s.io/kube-proxy => k8s.io/kube-proxy v0.31.1 + k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.31.1 + k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.5 + k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.31.1 + k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.31.1 ) require ( - cloud.google.com/go/compute v1.26.0 - cloud.google.com/go/compute/metadata v0.3.0 - cloud.google.com/go/kms v1.16.0 - cloud.google.com/go/secretmanager v1.13.0 - cloud.google.com/go/storage v1.40.0 - dario.cat/mergo v1.0.0 + cloud.google.com/go/compute v1.28.1 + cloud.google.com/go/compute/metadata v0.5.2 + cloud.google.com/go/kms v1.20.0 + cloud.google.com/go/secretmanager v1.14.1 + cloud.google.com/go/storage v1.44.0 + dario.cat/mergo v1.0.1 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.1.1 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.15.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6 v6.1.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.1.0 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.1.0 - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 - github.com/BurntSushi/toml v1.3.2 - github.com/aws/aws-sdk-go v1.53.0 - github.com/aws/aws-sdk-go-v2 v1.26.1 - github.com/aws/aws-sdk-go-v2/config v1.27.13 - github.com/aws/aws-sdk-go-v2/credentials v1.17.13 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.17 - github.com/aws/aws-sdk-go-v2/service/autoscaling v1.40.6 - github.com/aws/aws-sdk-go-v2/service/cloudfront v1.36.1 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.1 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.30.6 - github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.21.5 - github.com/aws/aws-sdk-go-v2/service/s3 v1.53.2 - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.7 - github.com/aws/smithy-go v1.20.2 - github.com/bazelbuild/buildtools v0.0.0-20240422193413-1429e15ae755 - github.com/bazelbuild/rules_go v0.47.1 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1 + github.com/BurntSushi/toml v1.4.0 + github.com/aws/aws-sdk-go v1.55.5 + github.com/aws/aws-sdk-go-v2 v1.32.2 + github.com/aws/aws-sdk-go-v2/config v1.27.43 + github.com/aws/aws-sdk-go-v2/credentials v1.17.41 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.32 + github.com/aws/aws-sdk-go-v2/service/autoscaling v1.45.2 + github.com/aws/aws-sdk-go-v2/service/cloudfront v1.40.2 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.182.0 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.40.0 + github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.25.2 + github.com/aws/aws-sdk-go-v2/service/s3 v1.65.3 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 + github.com/aws/smithy-go v1.22.0 + github.com/bazelbuild/buildtools v0.0.0-20240918101019-be1c24cc9a44 + github.com/bazelbuild/rules_go v0.50.1 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/docker/docker v26.1.2+incompatible + github.com/docker/docker v27.3.1+incompatible github.com/edgelesssys/go-azguestattestation v0.0.0-20240513062303-05f8770a633d github.com/edgelesssys/go-tdx-qpl v0.0.0-20240123150912-dcad3c41ec5f - github.com/foxboron/go-uefi v0.0.0-20240128152106-48be911532c2 + github.com/foxboron/go-uefi v0.0.0-20240805124652-e2076f0e58ca github.com/fsnotify/fsnotify v1.7.0 github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 - github.com/go-playground/validator/v10 v10.20.0 + github.com/go-playground/validator/v10 v10.22.1 github.com/golang-jwt/jwt/v5 v5.2.1 - github.com/google/go-sev-guest v0.11.1 + github.com/google/go-sev-guest v0.11.2-0.20241122022416-97a55186df28 github.com/google/go-tdx-guest v0.3.1 - github.com/google/go-tpm v0.9.1-0.20240510201744-5c2f0887e003 + github.com/google/go-tpm v0.9.1 github.com/google/go-tpm-tools v0.4.4 github.com/google/uuid v1.6.0 - github.com/googleapis/gax-go/v2 v2.12.4 - github.com/gophercloud/gophercloud v1.11.0 - github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 + github.com/googleapis/gax-go/v2 v2.13.0 + github.com/gophercloud/gophercloud/v2 v2.1.1 + github.com/gophercloud/utils/v2 v2.0.0-20241008104625-7cbb8fd76bb7 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 github.com/hashicorp/go-kms-wrapping/v2 v2.0.16 github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2 v2.0.9 github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2 v2.0.11 github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2 v2.0.12 - github.com/hashicorp/go-version v1.6.0 - github.com/hashicorp/hc-install v0.6.4 - github.com/hashicorp/hcl/v2 v2.20.1 - github.com/hashicorp/terraform-exec v0.20.0 - github.com/hashicorp/terraform-json v0.21.0 - github.com/hashicorp/terraform-plugin-framework v1.8.0 - github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 - github.com/hashicorp/terraform-plugin-go v0.23.0 + github.com/hashicorp/go-version v1.7.0 + github.com/hashicorp/hc-install v0.9.0 + github.com/hashicorp/hcl/v2 v2.22.0 + github.com/hashicorp/terraform-exec v0.21.0 + github.com/hashicorp/terraform-json v0.22.1 + github.com/hashicorp/terraform-plugin-framework v1.12.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 + github.com/hashicorp/terraform-plugin-go v0.24.0 github.com/hashicorp/terraform-plugin-log v0.9.0 - github.com/hashicorp/terraform-plugin-testing v1.7.0 + github.com/hashicorp/terraform-plugin-testing v1.10.0 github.com/hexops/gotextdiff v1.0.3 github.com/martinjungblut/go-cryptsetup v0.0.0-20220520180014-fd0874fd07a6 github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/go-homedir v1.1.0 - github.com/onsi/ginkgo/v2 v2.17.3 - github.com/onsi/gomega v1.33.1 + github.com/onsi/ginkgo/v2 v2.20.2 + github.com/onsi/gomega v1.34.2 github.com/pkg/errors v0.9.1 - github.com/regclient/regclient v0.6.0 - github.com/rogpeppe/go-internal v1.12.0 - github.com/samber/slog-multi v1.0.2 - github.com/schollz/progressbar/v3 v3.14.2 + github.com/regclient/regclient v0.7.1 + github.com/rogpeppe/go-internal v1.13.1 + github.com/samber/slog-multi v1.2.3 + github.com/schollz/progressbar/v3 v3.16.1 github.com/secure-systems-lab/go-securesystemslib v0.8.0 - github.com/siderolabs/talos/pkg/machinery v1.7.1 + github.com/siderolabs/talos/pkg/machinery v1.8.1 github.com/sigstore/rekor v1.3.6 - github.com/sigstore/sigstore v1.8.3 + github.com/sigstore/sigstore v1.8.10 github.com/spf13/afero v1.11.0 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 - github.com/tink-crypto/tink-go/v2 v2.1.0 + github.com/tink-crypto/tink-go/v2 v2.2.0 github.com/vincent-petithory/dataurl v1.0.0 - go.etcd.io/etcd/api/v3 v3.5.13 - go.etcd.io/etcd/client/pkg/v3 v3.5.13 - go.etcd.io/etcd/client/v3 v3.5.13 + go.etcd.io/etcd/api/v3 v3.5.16 + go.etcd.io/etcd/client/pkg/v3 v3.5.16 + go.etcd.io/etcd/client/v3 v3.5.16 go.uber.org/goleak v1.3.0 - golang.org/x/crypto v0.23.0 - golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 - golang.org/x/mod v0.17.0 - golang.org/x/sys v0.20.0 - golang.org/x/text v0.15.0 - golang.org/x/tools v0.21.0 - google.golang.org/api v0.180.0 - google.golang.org/grpc v1.63.2 - google.golang.org/protobuf v1.34.1 + golang.org/x/crypto v0.28.0 + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c + golang.org/x/mod v0.21.0 + golang.org/x/sys v0.26.0 + golang.org/x/text v0.19.0 + golang.org/x/tools v0.26.0 + google.golang.org/api v0.200.0 + google.golang.org/grpc v1.67.1 + google.golang.org/protobuf v1.35.1 gopkg.in/yaml.v3 v3.0.1 - helm.sh/helm v2.17.0+incompatible - helm.sh/helm/v3 v3.14.4 - k8s.io/api v0.30.0 - k8s.io/apiextensions-apiserver v0.30.0 - k8s.io/apimachinery v0.30.0 - k8s.io/apiserver v0.30.0 - k8s.io/client-go v0.30.0 - k8s.io/cluster-bootstrap v0.30.0 - k8s.io/kubelet v0.30.0 - k8s.io/kubernetes v1.30.0 - k8s.io/mount-utils v0.30.0 - k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 - libvirt.org/go/libvirt v1.10003.0 - sigs.k8s.io/controller-runtime v0.18.2 + helm.sh/helm/v3 v3.16.2 + k8s.io/api v0.31.1 + k8s.io/apiextensions-apiserver v0.31.1 + k8s.io/apimachinery v0.31.1 + k8s.io/apiserver v0.31.1 + k8s.io/client-go v0.31.1 + k8s.io/cluster-bootstrap v0.31.1 + k8s.io/kubelet v0.31.1 + k8s.io/kubernetes v1.31.1 + k8s.io/mount-utils v0.31.1 + k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 + libvirt.org/go/libvirt v1.10008.0 + sigs.k8s.io/controller-runtime v0.19.0 sigs.k8s.io/yaml v1.4.0 ) require ( - cloud.google.com/go v0.112.2 // indirect - cloud.google.com/go/auth v0.4.1 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/iam v1.1.8 // indirect - cloud.google.com/go/longrunning v0.5.7 // indirect + cel.dev/expr v0.16.2 // indirect + cloud.google.com/go v0.115.1 // indirect + cloud.google.com/go/auth v0.9.8 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go/iam v1.2.1 // indirect + cloud.google.com/go/longrunning v0.6.1 // indirect + cloud.google.com/go/monitoring v1.21.1 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.6.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 // indirect @@ -175,44 +164,51 @@ require ( github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.1 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.2.1 // indirect - github.com/Masterminds/sprig/v3 v3.2.3 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect - github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect + github.com/ProtonMail/go-crypto v1.1.0-alpha.5.0.20240827111422-b5837fa4476e // indirect github.com/agext/levenshtein v1.2.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.20.6 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.28.7 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.21 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/cloudflare/circl v1.3.7 // indirect + github.com/cloudflare/circl v1.3.9 // indirect + github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/log v0.1.0 // indirect + github.com/coredns/caddy v1.1.1 // indirect + github.com/coredns/corefile-migration v1.0.23 // indirect github.com/coreos/go-semver v0.3.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 // indirect - github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/cyphar/filepath-securejoin v0.3.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.5.0 // indirect - github.com/docker/cli v25.0.1+incompatible // indirect + github.com/docker/cli v27.1.1+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -220,17 +216,21 @@ require ( github.com/docker/go-units v0.5.0 // indirect github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/envoyproxy/go-control-plane v0.13.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect github.com/evanphx/json-patch v5.9.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-chi/chi v4.1.2+incompatible // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-jose/go-jose/v3 v3.0.3 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-jose/go-jose/v4 v4.0.2 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/analysis v0.23.0 // indirect @@ -246,6 +246,7 @@ require ( github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/gofrs/uuid/v5 v5.3.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -256,14 +257,14 @@ require ( github.com/google/go-attestation v0.5.1 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-configfs-tsm v0.2.2 // indirect - github.com/google/go-containerregistry v0.19.0 // indirect + github.com/google/go-containerregistry v0.20.2 // indirect github.com/google/go-tspi v0.3.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/logger v1.1.1 // indirect - github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect - github.com/google/s2a-go v0.1.7 // indirect + github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect + github.com/google/s2a-go v0.1.8 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect @@ -272,36 +273,36 @@ require ( github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect - github.com/hashicorp/go-hclog v1.6.2 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.6.0 // indirect - github.com/hashicorp/go-retryablehttp v0.7.5 // indirect + github.com/hashicorp/go-plugin v1.6.1 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 // indirect + github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect - github.com/huandu/xstrings v1.4.0 // indirect - github.com/imdario/mergo v0.3.15 // indirect + github.com/huandu/xstrings v1.5.0 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/jmoiron/sqlx v1.3.5 // indirect + github.com/jmoiron/sqlx v1.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.4 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/kylelemons/godebug v1.1.0 // 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/letsencrypt/boulder v0.0.0-20230907030200-6d76a0f91e1e // indirect + github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect github.com/lib/pq v1.10.9 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -310,8 +311,8 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/locker v1.0.1 // indirect - github.com/moby/spdystream v0.2.0 // indirect - github.com/moby/sys/mountinfo v0.6.2 // indirect + github.com/moby/spdystream v0.4.0 // indirect + github.com/moby/sys/mountinfo v0.7.1 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -321,69 +322,76 @@ require ( github.com/oklog/run v1.0.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc6 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/opencontainers/runc v1.1.13 // indirect + github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/pborman/uuid v1.2.1 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.19.0 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.48.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rubenv/sql-migrate v1.5.2 // indirect + github.com/rubenv/sql-migrate v1.7.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/samber/lo v1.38.1 // indirect + github.com/samber/lo v1.47.0 // indirect github.com/sassoftware/relic v7.2.1+incompatible // indirect - github.com/shopspring/decimal v1.3.1 // indirect + github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/cast v1.7.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/theupdateframework/go-tuf v0.7.0 // indirect github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect github.com/transparency-dev/merkle v0.0.2 // indirect - github.com/ulikunitz/xz v0.5.11 // indirect + github.com/ulikunitz/xz v0.5.12 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/vtolstov/go-ioctl v0.0.0-20151206205506-6be9cced4810 // indirect + github.com/x448/float16 v0.8.4 // 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/xlab/treeprint v1.2.0 // indirect - github.com/zclconf/go-cty v1.14.3 // indirect + github.com/zclconf/go-cty v1.15.0 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.29.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/sdk v1.29.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/oauth2 v0.20.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/term v0.20.0 // indirect - golang.org/x/time v0.5.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/time v0.7.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 // indirect - gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect + google.golang.org/genproto v0.0.0-20241007155032-5fefd90f89a9 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect + google.golang.org/grpc/stats/opentelemetry v0.0.0-20240907200651-3ffb98b2c93a // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/cli-runtime v0.29.0 // indirect - k8s.io/component-base v0.30.0 // indirect - k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/cli-runtime v0.31.1 // indirect + k8s.io/component-base v0.31.1 // indirect + k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/kubectl v0.29.0 // indirect + k8s.io/kubectl v0.31.1 // indirect oras.land/oras-go v1.2.5 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect - sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/kustomize/api v0.17.2 // indirect + sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) diff --git a/go.sum b/go.sum index 4807f7721..366de64dc 100644 --- a/go.sum +++ b/go.sum @@ -1,26 +1,34 @@ +cel.dev/expr v0.16.2 h1:RwRhoH17VhAu9U5CMvMhH1PDVgf0tuz9FT+24AfMLfU= +cel.dev/expr v0.16.2/go.mod h1:gXngZQMkWJoSbE8mOzehJlXQyubn/Vg0vR9/F3W7iw8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.112.2 h1:ZaGT6LiG7dBzi6zNOvVZwacaXlmf3lRqnC4DQzqyRQw= -cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= -cloud.google.com/go/auth v0.4.1 h1:Z7YNIhlWRtrnKlZke7z3GMqzvuYzdc2z98F9D1NV5Hg= -cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro= -cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= -cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= -cloud.google.com/go/compute v1.26.0 h1:uHf0NN2nvxl1Gh4QO83yRCOdMK4zivtMS5gv0dEX0hg= -cloud.google.com/go/compute v1.26.0/go.mod h1:T9RIRap4pVHCGUkVFRJ9hygT3KCXjip41X1GgWtBBII= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/iam v1.1.8 h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0= -cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE= -cloud.google.com/go/kms v1.16.0 h1:1yZsRPhmargZOmY+fVAh8IKiR9HzCb0U1zsxb5g2nRY= -cloud.google.com/go/kms v1.16.0/go.mod h1:olQUXy2Xud+1GzYfiBO9N0RhjsJk5IJLU6n/ethLXVc= -cloud.google.com/go/longrunning v0.5.7 h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU= -cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= -cloud.google.com/go/secretmanager v1.13.0 h1:nQ/Ca2Gzm/OEP8tr1hiFdHRi5wAnAmsm9qTjwkivyrQ= -cloud.google.com/go/secretmanager v1.13.0/go.mod h1:yWdfNmM2sLIiyv6RM6VqWKeBV7CdS0SO3ybxJJRhBEs= -cloud.google.com/go/storage v1.40.0 h1:VEpDQV5CJxFmJ6ueWNsKxcr1QAYOXEgxDa+sBbJahPw= -cloud.google.com/go/storage v1.40.0/go.mod h1:Rrj7/hKlG87BLqDJYtwR0fbPld8uJPbQ2ucUMY7Ir0g= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ= +cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc= +cloud.google.com/go/auth v0.9.8 h1:+CSJ0Gw9iVeSENVCKJoLHhdUykDgXSc4Qn+gu2BRtR8= +cloud.google.com/go/auth v0.9.8/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= +cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= +cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go/compute v1.28.1 h1:XwPcZjgMCnU2tkwY10VleUjSAfpTj9RDn+kGrbYsi8o= +cloud.google.com/go/compute v1.28.1/go.mod h1:b72iXMY4FucVry3NR3Li4kVyyTvbMDE7x5WsqvxjsYk= +cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= +cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= +cloud.google.com/go/iam v1.2.1 h1:QFct02HRb7H12J/3utj0qf5tobFh9V4vR6h9eX5EBRU= +cloud.google.com/go/iam v1.2.1/go.mod h1:3VUIJDPpwT6p/amXRC5GY8fCCh70lxPygguVtI0Z4/g= +cloud.google.com/go/kms v1.20.0 h1:uKUvjGqbBlI96xGE669hcVnEMw1Px/Mvfa62dhM5UrY= +cloud.google.com/go/kms v1.20.0/go.mod h1:/dMbFF1tLLFnQV44AoI2GlotbjowyUfgVwezxW291fM= +cloud.google.com/go/logging v1.11.0 h1:v3ktVzXMV7CwHq1MBF65wcqLMA7i+z3YxbUsoK7mOKs= +cloud.google.com/go/logging v1.11.0/go.mod h1:5LDiJC/RxTt+fHc1LAt20R9TKiUTReDg6RuuFOZ67+A= +cloud.google.com/go/longrunning v0.6.1 h1:lOLTFxYpr8hcRtcwWir5ITh1PAKUD/sG2lKrTSYjyMc= +cloud.google.com/go/longrunning v0.6.1/go.mod h1:nHISoOZpBcmlwbJmiVk5oDRz0qG/ZxPynEGs1iZ79s0= +cloud.google.com/go/monitoring v1.21.1 h1:zWtbIoBMnU5LP9A/fz8LmWMGHpk4skdfeiaa66QdFGc= +cloud.google.com/go/monitoring v1.21.1/go.mod h1:Rj++LKrlht9uBi8+Eb530dIrzG/cU/lB8mt+lbeFK1c= +cloud.google.com/go/secretmanager v1.14.1 h1:xlWSIg8rtBn5qCr2f3XtQP19+5COyf/ll49SEvi/0vM= +cloud.google.com/go/secretmanager v1.14.1/go.mod h1:L+gO+u2JA9CCyXpSR8gDH0o8EV7i/f0jdBOrUXcIV0U= +cloud.google.com/go/storage v1.44.0 h1:abBzXf4UJKMmQ04xxJf9dYM/fNl24KHoTuBjyJDX2AI= +cloud.google.com/go/storage v1.44.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= +cloud.google.com/go/trace v1.11.1 h1:UNqdP+HYYtnm6lb91aNA5JQ0X14GnxkABGlfz2PzPew= +cloud.google.com/go/trace v1.11.1/go.mod h1:IQKNQuBzH72EGaXEodKlNJrWykGZxet2zgjtS60OtjA= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= @@ -29,32 +37,34 @@ github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d h1:zjq github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d/go.mod h1:XNqJ7hv2kY++g8XEHREpi+JqZo3+0l+CH2egBVN4yqM= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.6.0 h1:sUFnFjzDUie80h24I7mrKtwCKgLY9L8h5Tp2x9+TWqk= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.6.0/go.mod h1:52JbnQTp15qg5mRkMBHwp0j0ZFwHJ42Sx3zVV5RE9p0= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.15.0 h1:eXzkOEXbSTOa7cJ7EqeCVi/OFi/ppDrUtQuttCWy74c= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.15.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvULkDNfdXOgrjtg6UYJPFBJyuEcRCAw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE= github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw= github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.1.1 h1:QZY6o3E/KX0QhgQpvat4UxAsXuBIb4efrFtZcqCUTbs= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.1.1/go.mod h1:8gv2PVzO0a+f4aWpe940Ouz0r4ifLj8H+/jxRXgwPxg= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0/go.mod h1:T5RfihdXtBDxt1Ch2wobif3TvzTdumDy29kahv6AV9A= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6 v6.1.0 h1:zDeQI/PaWztI2tcrGO/9RIMey9NvqYbnyttf/0P3QWM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6 v6.1.0/go.mod h1:zflC9v4VfViJrSvcvplqws/yGXVbUEMZi/iHpZdSPWA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0/go.mod h1:AW8VEadnhw9xox+VaVd9sP7NjzOAnaZBLRH6Tq3cJ38= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.1.0 h1:Fd+iaEa+JBwzYo6OTWYSNqyvlPSLciMGsmsnYCKcXM0= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.1.0/go.mod h1:ulHyBFJOI0ONiRL4vcJTmS7rx18jQQlEPmAgo80cRdM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.1.0 h1:h4Zxgmi9oyZL2l8jeg1iRTqPloHktywWcu0nlJmo1tA= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.1.0/go.mod h1:LgLGXawqSreJz135Elog0ywTJDsm0Hz2k+N+6ZK35u8= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 h1:YUUxeiOWgdAQE3pXt2H7QXzZs0q8UBjgRbl56qo8GYM= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2/go.mod h1:dmXQgZuiSubAecswZE+Sm8jkvEa7kQgTPVRvwL/nd0E= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1 h1:cf+OIKbkmMHBaC3u78AXomweqM0oxQSgBXRZf3WH4yM= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1/go.mod h1:ap1dmS6vQKJxSMNiGJcq4QuUQkOynyD93gLw6MDF7ek= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -77,30 +87,39 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.1 h1:pB2F2JKCj1Znmp2rwxxt1J0Fg0wezTMgWYk5Mpbi1kg= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.1/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1/go.mod h1:0wEl7vrAD8mehJyohS9HZy+WyEOaQO2mJx86Cvh93kM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= -github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= 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.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= -github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg= -github.com/ProtonMail/go-crypto v1.1.0-alpha.2/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.1.0-alpha.5.0.20240827111422-b5837fa4476e h1:O1cSHAcGcbGEO66Qi2AIJeYmXO8iP4L/PNrbdN+RjJA= +github.com/ProtonMail/go-crypto v1.1.0-alpha.5.0.20240827111422-b5837fa4476e/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= @@ -117,62 +136,62 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo= -github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= -github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg= -github.com/aws/aws-sdk-go-v2/config v1.27.13 h1:WbKW8hOzrWoOA/+35S5okqO/2Ap8hkkFUzoW8Hzq24A= -github.com/aws/aws-sdk-go-v2/config v1.27.13/go.mod h1:XLiyiTMnguytjRER7u5RIkhIqS8Nyz41SwAWb4xEjxs= -github.com/aws/aws-sdk-go-v2/credentials v1.17.13 h1:XDCJDzk/u5cN7Aple7D/MiAhx1Rjo/0nueJ0La8mRuE= -github.com/aws/aws-sdk-go-v2/credentials v1.17.13/go.mod h1:FMNcjQrmuBYvOTZDtOLCIu0esmxjF7RuA/89iSXWzQI= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.17 h1:9b1Os1s11mF5qTIKLgSsyPG810di2+ySSLIIt9bwe9I= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.17/go.mod h1:9Wp7tDOMhv0+sb/FTRAkbHNQ7abYDnoJRzm5AAtCnTc= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5 h1:81KE7vaZzrl7yHBYHVEzYB8sypz11NMOZ40YlWvPxsU= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5/go.mod h1:LIt2rg7Mcgn09Ygbdh/RdIm0rQ+3BNkbP1gyVMFtRK0= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.40.6 h1:IDoEdCkKRy7iPlRVSuDATGE57xUjrk5i1M9eWPYwr/Y= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.40.6/go.mod h1:ZErgk/bPaaZIpj+lUWGlwI1A0UFhSIscgnCPzTLnb2s= -github.com/aws/aws-sdk-go-v2/service/cloudfront v1.36.1 h1://GRw/PrpnUyWBJh6KvUvR9AgkDBhclzaj3HKGxRoCw= -github.com/aws/aws-sdk-go-v2/service/cloudfront v1.36.1/go.mod h1:Pphkts8iBnexoEpcMti5fUvN3/yoGRLtl2heOeppF70= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.1 h1:NbjXshriDs5bGeqKvrOF70L41X0aCMC60ImN2vkcQAc= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.1/go.mod h1:xejKuuRDjz6z5OqyeLsz01MlOqqW7CqpAB4PabNvpu8= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.30.6 h1:P5kMcIzrz4Y7GIkvmkosgv/0cs1Crk/VLo5pBhrTWGI= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.30.6/go.mod h1:e1McVqsud0JOERidvppLEHnuCdh/X6MRyL5L0LseAUk= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7 h1:ZMeFZ5yk+Ek+jNr1+uwCd2tG89t6oTS5yVWpa6yy2es= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7/go.mod h1:mxV05U+4JiHqIpGqqYXOHLPKUC6bDXC44bsUhNjOEwY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5 h1:f9RyWNtS8oH7cZlbn+/JNPpjUk5+5fLd5lM9M0i49Ys= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5/go.mod h1:h5CoMZV2VF297/VLhRhO1WF+XYWOzXo+4HsObA4HjBQ= -github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.21.5 h1:GR0vFRc5TpN36ppQJjd+gjRRC9vMAHN5C2W53oMWCJU= -github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.21.5/go.mod h1:FWw+Jnx+SlpsrU/NQ/f7f+1RdixTApZiU2o9FOubiDQ= -github.com/aws/aws-sdk-go-v2/service/s3 v1.53.2 h1:rq2hglTQM3yHZvOPVMtNvLS5x6hijx7JvRDgKiTNDGQ= -github.com/aws/aws-sdk-go-v2/service/s3 v1.53.2/go.mod h1:qmdkIIAC+GCLASF7R2whgNrJADz0QZPX+Seiw/i4S3o= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.7 h1:4cziOtpDwtgcb+wTYRzz8C+GoH1XySy0p7j4oBbqPQE= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.7/go.mod h1:3Ba++UwWd154xtP4FRX5pUK3Gt4up5sDHCve6kVfE+g= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.6 h1:o5cTaeunSpfXiLTIBx5xo2enQmiChtu1IBbzXnfU9Hs= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.6/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0 h1:Qe0r0lVURDDeBQJ4yP+BOrJkvkiCo/3FH/t+wY11dmw= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.7 h1:et3Ta53gotFR4ERLXXHIHl/Uuk1qYpP5uU7cvNql8ns= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.7/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw= -github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= -github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= -github.com/bazelbuild/buildtools v0.0.0-20240422193413-1429e15ae755 h1:hqhMmuZiSNwCWVHqnpr4DZfIeZ2/aJF7fs207eg7HZo= -github.com/bazelbuild/buildtools v0.0.0-20240422193413-1429e15ae755/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo= -github.com/bazelbuild/rules_go v0.47.1 h1:9s9FA2l8IAxCbwV97E1WLu5ai21muLNrjZRV0+agTRs= -github.com/bazelbuild/rules_go v0.47.1/go.mod h1:Dhcz716Kqg1RHNWos+N6MlXNkjNP2EwZQ0LukRKJfMs= +github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= +github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI= +github.com/aws/aws-sdk-go-v2 v1.32.2/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6 h1:pT3hpW0cOHRJx8Y0DfJUEQuqPild8jRGmSFmBgvydr0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6/go.mod h1:j/I2++U0xX+cr44QjHay4Cvxj6FUbnxrgmqN3H1jTZA= +github.com/aws/aws-sdk-go-v2/config v1.27.43 h1:p33fDDihFC390dhhuv8nOmX419wjOSDQRb+USt20RrU= +github.com/aws/aws-sdk-go-v2/config v1.27.43/go.mod h1:pYhbtvg1siOOg8h5an77rXle9tVG8T+BWLWAo7cOukc= +github.com/aws/aws-sdk-go-v2/credentials v1.17.41 h1:7gXo+Axmp+R4Z+AK8YFQO0ZV3L0gizGINCOWxSLY9W8= +github.com/aws/aws-sdk-go-v2/credentials v1.17.41/go.mod h1:u4Eb8d3394YLubphT4jLEwN1rLNq2wFOlT6OuxFwPzU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 h1:TMH3f/SCAWdNtXXVPPu5D6wrr4G5hI1rAxbcocKfC7Q= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17/go.mod h1:1ZRXLdTpzdJb9fwTMXiLipENRxkGMTn1sfKexGllQCw= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.32 h1:C2hE+gJ40Cb4vzhFJ+tTzjvBpPloUq7XP6PD3A2Fk7g= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.32/go.mod h1:0OmMtVNp+10JFBTfmA2AIeqBDm0YthDXmE+N7poaptk= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 h1:UAsR3xA31QGf79WzpG/ixT9FZvQlh5HY1NRqSHBNOCk= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21/go.mod h1:JNr43NFf5L9YaG3eKTm7HQzls9J+A9YYcGI5Quh1r2Y= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 h1:6jZVETqmYCadGFvrYEQfC5fAQmlo80CeL5psbno6r0s= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21/go.mod h1:1SR0GbLlnN3QUmYaflZNiH1ql+1qrSiB2vwcJ+4UM60= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.21 h1:7edmS3VOBDhK00b/MwGtGglCm7hhwNYnjJs/PgFdMQE= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.21/go.mod h1:Q9o5h4HoIWG8XfzxqiuK/CGUbepCJ8uTlaE3bAbxytQ= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.45.2 h1:NurelK9YO5OB0HlIUj1ycEZJIFNvkuG5iJjo7/r6AJ4= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.45.2/go.mod h1:YmWinWbpoVdOgnBZQFeZJ2l4kT97lvnRlTvX2zyyBfc= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.40.2 h1:d2VzVozwvcImzmlPTvIV5xHh3tsm5PSnHIlOpbZFZMY= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.40.2/go.mod h1:f3osu1mATeVxhF5MufhYckvB9WZNqv29c0wNR7egU9Q= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.182.0 h1:LaeziEhHZ/SJZYBK223QVzl3ucHvA9IP4tQMcxGrc9I= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.182.0/go.mod h1:kYXaB4FzyhEJjvrJ84oPnMElLiEAjGxxUunVW2tBSng= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.40.0 h1:ZQONu+vfYQ8LJ7G10RK9vXp/6G3B3PZ2KzwWWm4MRxE= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.40.0/go.mod h1:EF4KS26lCJdihrMJR9Rd4X4Q+rHLXa8Scx6S6tqg4WM= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.2 h1:4FMHqLfk0efmTqhXVRL5xYRqlEBNBiRI7N6w4jsEdd4= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.2/go.mod h1:LWoqeWlK9OZeJxsROW2RqrSPvQHKTpp69r/iDjwsSaw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 h1:s7NA1SOw8q/5c0wr8477yOPp0z+uBaXBnLE0XYb0POA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2/go.mod h1:fnjjWyAW/Pj5HYOxl9LJqWtEwS7W2qgcRLWP+uWbss0= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.2 h1:t7iUP9+4wdc5lt3E41huP+GvQZJD38WLsgVp4iOtAjg= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.2/go.mod h1:/niFCtmuQNxqx9v8WAPq5qh7EH25U4BF6tjoyq9bObM= +github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.25.2 h1:GsOyDDu3svGW4UHi/wM7xHKUmMrbcy7iCGPDIfPiH2c= +github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.25.2/go.mod h1:fh2trEdv/AGvQ8Fi+5Kv+CJJ5pVlXqSKJUQJRLaSlhc= +github.com/aws/aws-sdk-go-v2/service/s3 v1.65.3 h1:xxHGZ+wUgZNACQmxtdvP5tgzfsxGS3vPpTP5Hy3iToE= +github.com/aws/aws-sdk-go-v2/service/s3 v1.65.3/go.mod h1:cB6oAuus7YXRZhWCc1wIwPywwZ1XwweNp2TVAEGYeB8= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 h1:Rrqru2wYkKQCS2IM5/JrgKUQIoNTqA6y/iuxkjzxC6M= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2/go.mod h1:QuCURO98Sqee2AXmqDNxKXYFm2OEDAVAPApMqO0Vqnc= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 h1:bSYXVyUzoTHoKalBmwaZxs97HU9DWWI3ehHSAMa7xOk= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.2/go.mod h1:skMqY7JElusiOUjMJMOv1jJsP7YUg7DrhgqZZWuzu1U= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 h1:AhmO1fHINP9vFYUE0LHzCWg/LfUWUF+zFPEcY9QXb7o= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2/go.mod h1:o8aQygT2+MVP0NaV6kbdE1YnnIM8RRVQzoeUH45GOdI= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 h1:CiS7i0+FUe+/YY1GvIBLLrR/XNGZ4CtM1Ll0XavNuVo= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.2/go.mod h1:HtaiBI8CjYoNVde8arShXb94UbQQi9L4EMr6D+xGBwo= +github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= +github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/bazelbuild/buildtools v0.0.0-20240918101019-be1c24cc9a44 h1:FGzENZi+SX9I7h9xvMtRA3rel8hCEfyzSixteBgn7MU= +github.com/bazelbuild/buildtools v0.0.0-20240918101019-be1c24cc9a44/go.mod h1:PLNUetjLa77TCCziPsz0EI8a6CUxgC+1jgmWv0H25tg= +github.com/bazelbuild/rules_go v0.50.1 h1:/BUvuaB8MEiUA2oLPPCGtuw5V+doAYyiGTFyoSWlkrw= +github.com/bazelbuild/rules_go v0.50.1/go.mod h1:Dhcz716Kqg1RHNWos+N6MlXNkjNP2EwZQ0LukRKJfMs= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -191,20 +210,26 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembj github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +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/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM= +github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= -github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE= +github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI= +github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= @@ -213,19 +238,24 @@ github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0= +github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= +github.com/coredns/corefile-migration v1.0.23 h1:Fp4FETmk8sT/IRgnKX2xstC2dL7+QdcU+BL5AYIN3Jw= +github.com/coredns/corefile-migration v1.0.23/go.mod h1:8HyMhuyzx9RLZp8cRc9Uf3ECpEAafHOFxQWUPqktMQI= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 h1:vU+EP9ZuFUCYE0NYLwTSob+3LNEJATzNfP/DC7SWGWI= github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.3.1 h1:1V7cHiaW+C+39wEfpH6XlLBQo3j/PciWFrgfCLS8XrE= +github.com/cyphar/filepath-securejoin v0.3.1/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= github.com/daniel-weisse/go-cryptsetup v0.0.0-20230705150314-d8c07bd1723c h1:ToajP6trZoiqlZ3Z4uoG1P02/wtqSw1AcowOXOYjATk= github.com/daniel-weisse/go-cryptsetup v0.0.0-20230705150314-d8c07bd1723c/go.mod h1:gZoZ0+POlM1ge/VUxWpMmZVNPzzMJ7l436CgkQ5+qzU= github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE= @@ -234,18 +264,18 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/cli v25.0.1+incompatible h1:mFpqnrS6Hsm3v1k7Wa/BO23oz0k121MTbTO1lpcGSkU= -github.com/docker/cli v25.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= +github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v26.1.2+incompatible h1:UVX5ZOrrfTGZZYEP+ZDq3Xn9PdHNXaSYMFPDumMqG2k= -github.com/docker/docker v26.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -269,7 +299,11 @@ github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FM github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= +github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM= +github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= @@ -278,18 +312,21 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwC github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -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/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/foxboron/go-uefi v0.0.0-20240128152106-48be911532c2 h1:qGlg/7H49H30Eu7nkCBA7YxNmW30ephqBf7xIxlAGuQ= -github.com/foxboron/go-uefi v0.0.0-20240128152106-48be911532c2/go.mod h1:ffg/fkDeOYicEQLoO2yFFGt00KUTYVXI+rfnc8il6vQ= -github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI= -github.com/foxcpp/go-mockdns v1.0.0/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/foxboron/go-uefi v0.0.0-20240805124652-e2076f0e58ca h1:ErxkaWK5AIt8gQf3KpAuQQBdZI4ps72HzEe123kh+So= +github.com/foxboron/go-uefi v0.0.0-20240805124652-e2076f0e58ca/go.mod h1:ffg/fkDeOYicEQLoO2yFFGt00KUTYVXI+rfnc8il6vQ= +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.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= 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/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= @@ -306,12 +343,14 @@ github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= +github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= +github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/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-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= @@ -342,28 +381,23 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o 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.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= -github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= +github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= -github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= -github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= -github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= -github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= -github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= -github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= 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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk= +github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -416,14 +450,14 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-configfs-tsm v0.2.2 h1:YnJ9rXIOj5BYD7/0DNnzs8AOp7UcvjfTvt215EWcs98= github.com/google/go-configfs-tsm v0.2.2/go.mod h1:EL1GTDFMb5PZQWDviGfZV9n87WeGTR/JUg13RfwkgRo= -github.com/google/go-containerregistry v0.19.0 h1:uIsMRBV7m/HDkDxE/nXMnv1q+lOOSPlQ/ywc5JbB8Ic= -github.com/google/go-containerregistry v0.19.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ= -github.com/google/go-sev-guest v0.11.1 h1:gnww4U8fHV5DCPz4gykr1s8SEX1fFNcxCBy+vvXN24k= -github.com/google/go-sev-guest v0.11.1/go.mod h1:qBOfb+JmgsUI3aUyzQoGC13Kpp9zwLeWvuyXmA9q77w= +github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= +github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= +github.com/google/go-sev-guest v0.11.2-0.20241122022416-97a55186df28 h1:dFOaRoS7lz9+t6aJeWjyBsuIMSZFQEmxGEoTW54sxP0= +github.com/google/go-sev-guest v0.11.2-0.20241122022416-97a55186df28/go.mod h1:SK9vW+uyfuzYdVN0m8BShL3OQCtXZe/JPF7ZkpD3760= github.com/google/go-tdx-guest v0.3.1 h1:gl0KvjdsD4RrJzyLefDOvFOUH3NAJri/3qvaL5m83Iw= github.com/google/go-tdx-guest v0.3.1/go.mod h1:/rc3d7rnPykOPuY8U9saMyEps0PZDThLk/RygXm04nE= -github.com/google/go-tpm v0.9.1-0.20240510201744-5c2f0887e003 h1:gfGQAIxsEEAuYuFvjCGpDnTwisMJOz+rUfJMkk4yTmc= -github.com/google/go-tpm v0.9.1-0.20240510201744-5c2f0887e003/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= +github.com/google/go-tpm v0.9.1 h1:0pGc4X//bAlmZzMKf8iz6IsDo1nYTbYJ6FZN/rg4zdM= +github.com/google/go-tpm v0.9.1/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= github.com/google/go-tpm-tools v0.4.4 h1:oiQfAIkc6xTy9Fl5NKTeTJkBTlXdHsxAofmQyxBKY98= github.com/google/go-tpm-tools v0.4.4/go.mod h1:T8jXkp2s+eltnCDIsXR84/MTcVU9Ja7bh3Mit0pa4AY= github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus= @@ -433,33 +467,30 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/logger v1.1.1 h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ= github.com/google/logger v1.1.1/go.mod h1:BkeJZ+1FhQ+/d087r4dzojEg1u2ZX+ZqG1jTUrLM+zQ= -github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= 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.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= -github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= -github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= -github.com/gophercloud/gophercloud v1.11.0 h1:ls0O747DIq1D8SUHc7r2vI8BFbMLeLFuENaAIfEx7OM= -github.com/gophercloud/gophercloud v1.11.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= -github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE= -github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/gophercloud/gophercloud/v2 v2.1.1 h1:KUeVTUoq6um/CijR+hl1JRZ35SXRY62LiYUbgp4qqKw= +github.com/gophercloud/gophercloud/v2 v2.1.1/go.mod h1:f2hMRC7Kakbv5vM7wSGHrIPZh6JZR60GVHryJlF/K44= +github.com/gophercloud/utils/v2 v2.0.0-20241008104625-7cbb8fd76bb7 h1:RDFC3+cVfeCQ8zi/PgaKrPzJyUbwzg3Mi2xCWnAW+g4= +github.com/gophercloud/utils/v2 v2.0.0-20241008104625-7cbb8fd76bb7/go.mod h1:hLzf9Ts2fhebZrZAtq6BpbwXQLEZmUqa7ABJMkg/il8= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= @@ -469,8 +500,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= 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= @@ -481,10 +512,9 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I= -github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +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-kms-wrapping/v2 v2.0.16 h1:WZeXfD26QMWYC35at25KgE021SF9L3u9UMHK8fJAdV0= github.com/hashicorp/go-kms-wrapping/v2 v2.0.16/go.mod h1:ZiKZctjRTLEppuRwrttWkp71VYMbTTCkazK4xT7U/NQ= github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2 v2.0.9 h1:qdxeZvDMRGZ3YSE4Oz0Pp7WUSUn5S6cWZguEOkEVL50= @@ -495,41 +525,41 @@ github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2 v2.0.12 h1:PCqWzT/Hii0K github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2 v2.0.12/go.mod h1:HSaOaX/lv3ShCdilUYbOTPnSvmoZ9xtQhgw+8hYcZkg= 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-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= -github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= -github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= -github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= +github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= +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-secure-stdlib/awsutil v0.1.6 h1:W9WN8p6moV1fjKLkeqEgkAMu5rauy9QeYDAmIaPuuiA= github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6/go.mod h1:MpCPSPGLDILGb4JMm94/mMi3YysIqsXzGCzkEZjcjXg= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hc-install v0.6.4 h1:QLqlM56/+SIIGvGcfFiwMY3z5WGXT066suo/v9Km8e0= -github.com/hashicorp/hc-install v0.6.4/go.mod h1:05LWLy8TD842OtgcfBbOT0WMoInBMUSHjmDx10zuBIA= -github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc= -github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4= +github.com/hashicorp/hc-install v0.9.0 h1:2dIk8LcvANwtv3QZLckxcjyF5w8KVtiMxu6G6eLhghE= +github.com/hashicorp/hc-install v0.9.0/go.mod h1:+6vOP+mf3tuGgMApVYtmsnDoKWMDcFXeTxCACYZ8SFg= +github.com/hashicorp/hcl/v2 v2.22.0 h1:hkZ3nCtqeJsDhPRFz5EA9iwcG1hNWGePOTw6oyul12M= +github.com/hashicorp/hcl/v2 v2.22.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/terraform-exec v0.20.0 h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8JyYF3vpnuEo= -github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw= -github.com/hashicorp/terraform-json v0.21.0 h1:9NQxbLNqPbEMze+S6+YluEdXgJmhQykRyRNd+zTI05U= -github.com/hashicorp/terraform-json v0.21.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= -github.com/hashicorp/terraform-plugin-framework v1.8.0 h1:P07qy8RKLcoBkCrY2RHJer5AEvJnDuXomBgou6fD8kI= -github.com/hashicorp/terraform-plugin-framework v1.8.0/go.mod h1:/CpTukO88PcL/62noU7cuyaSJ4Rsim+A/pa+3rUVufY= -github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc= -github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg= -github.com/hashicorp/terraform-plugin-go v0.23.0 h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co= -github.com/hashicorp/terraform-plugin-go v0.23.0/go.mod h1:1E3Cr9h2vMlahWMbsSEcNrOCxovCZhOOIXjFHbjc/lQ= +github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ= +github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= +github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec= +github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= +github.com/hashicorp/terraform-plugin-framework v1.12.0 h1:7HKaueHPaikX5/7cbC1r9d1m12iYHY+FlNZEGxQ42CQ= +github.com/hashicorp/terraform-plugin-framework v1.12.0/go.mod h1:N/IOQ2uYjW60Jp39Cp3mw7I/OpC/GfZ0385R0YibmkE= +github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 h1:bxZfGo9DIUoLLtHMElsu+zwqI4IsMZQBRRy4iLzZJ8E= +github.com/hashicorp/terraform-plugin-framework-validators v0.13.0/go.mod h1:wGeI02gEhj9nPANU62F2jCaHjXulejm/X+af4PdZaNo= +github.com/hashicorp/terraform-plugin-go v0.24.0 h1:2WpHhginCdVhFIrWHxDEg6RBn3YaWzR2o6qUeIEat2U= +github.com/hashicorp/terraform-plugin-go v0.24.0/go.mod h1:tUQ53lAsOyYSckFGEefGC5C8BAaO0ENqzFd3bQeuYQg= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 h1:qHprzXy/As0rxedphECBEQAh3R4yp6pKksKHcqZx5G8= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0/go.mod h1:H+8tjs9TjV2w57QFVSMBQacf8k/E1XwLXGCARgViC6A= -github.com/hashicorp/terraform-plugin-testing v1.7.0 h1:I6aeCyZ30z4NiI3tzyDoO6fS7YxP5xSL1ceOon3gTe8= -github.com/hashicorp/terraform-plugin-testing v1.7.0/go.mod h1:sbAreCleJNOCz+y5vVHV8EJkIWZKi/t4ndKiUjM9vao= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 h1:kJiWGx2kiQVo97Y5IOGR4EMcZ8DtMswHhUuFibsCQQE= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0/go.mod h1:sl/UoabMc37HA6ICVMmGO+/0wofkVIRxf+BMb/dnoIg= +github.com/hashicorp/terraform-plugin-testing v1.10.0 h1:2+tmRNhvnfE4Bs8rB6v58S/VpqzGC6RCh9Y8ujdn+aw= +github.com/hashicorp/terraform-plugin-testing v1.10.0/go.mod h1:iWRW3+loP33WMch2P/TEyCxxct/ZEcCGMquSLSCVsrc= github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM= github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= @@ -540,12 +570,10 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM= github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= -github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= -github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +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/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= @@ -561,8 +589,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/clock v1.2.0 h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs= github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI= -github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= -github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -570,15 +598,14 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= -github.com/karrick/godirwalk v1.17.0 h1:b4kY7nqDdioR/6qnbHQyDvmA17u5G1cZ6J+CZXwSWoI= -github.com/karrick/godirwalk v1.17.0/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -597,9 +624,8 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhR 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/letsencrypt/boulder v0.0.0-20230907030200-6d76a0f91e1e h1:RLTpX495BXToqxpM90Ws4hXEo4Wfh81jr9DX1n/4WOo= -github.com/letsencrypt/boulder v0.0.0-20230907030200-6d76a0f91e1e/go.mod h1:EAuqr9VFWxBi9nD5jc/EA2MT1RFty9288TF6zdtYoCU= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec h1:2tTW6cDth2TSgRbAhD7yjZzTQmcN25sDRPEeinR51yQ= +github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec/go.mod h1:TmwEoGCwIti7BCeJ9hescZgRtatxRE+A72pCoPfmcfk= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= @@ -608,12 +634,6 @@ github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffkt github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= -github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= -github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= -github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= -github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -627,17 +647,15 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= -github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= +github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -648,17 +666,16 @@ github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQ github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= 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/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 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/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= -github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= +github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= +github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -681,20 +698,22 @@ github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olareg/olareg v0.0.0-20240323210534-20ec9e4f6dd4 h1:1I7mTStFqh+DqPG9rRjEhEallPi2MQg2uACGImFGS1Q= -github.com/olareg/olareg v0.0.0-20240323210534-20ec9e4f6dd4/go.mod h1:RBuU7JW7SoIIxZKzLRhq8sVtQeAHzCAtRrXEBx2KlM4= -github.com/onsi/ginkgo/v2 v2.17.3 h1:oJcvKpIb7/8uLpDDtnQuf18xVnwKp8DTD7DQ6gTd/MU= -github.com/onsi/ginkgo/v2 v2.17.3/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/olareg/olareg v0.1.0 h1:1dXBOgPrig5N7zoXyIZVQqU0QBo6sD9pbL6UYjY75CA= +github.com/olareg/olareg v0.1.0/go.mod h1:RBuU7JW7SoIIxZKzLRhq8sVtQeAHzCAtRrXEBx2KlM4= +github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= +github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= +github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= +github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= 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.0-rc6 h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU= -github.com/opencontainers/image-spec v1.1.0-rc6/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runc v1.1.13 h1:98S2srgG9vw0zWcDpFMn5TRrh8kLxa/5OFUstuUhmRs= +github.com/opencontainers/runc v1.1.13/go.mod h1:R016aXacfp/gwQBYw2FDGa9m+n6atbLWrYY8hNMT/sA= +github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= +github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= 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/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= -github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= @@ -706,64 +725,68 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= 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/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +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.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/regclient/regclient v0.6.0 h1:P+8L9fdOTCo6S6O0/vE/C47csVY5UW5CMEzVwENVbWA= -github.com/regclient/regclient v0.6.0/go.mod h1:ofqAoAhp8T8us4pXT2acvmpUnqjfEdXt3y3b9YunqGo= +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/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= +github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= +github.com/regclient/regclient v0.7.1 h1:qEsJrTmZd98fZKjueAbrZCSNGU+ifnr6xjlSAs3WOPs= +github.com/regclient/regclient v0.7.1/go.mod h1:+w/BFtJuw0h0nzIw/z2+1FuA2/dVXBzDq4rYmziJpMc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -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/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0= -github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= +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/rubenv/sql-migrate v1.7.0 h1:HtQq1xyTN2ISmQDggnh0c9U3JlP8apWh8YO2jzlXpTI= +github.com/rubenv/sql-migrate v1.7.0/go.mod h1:S4wtDEG1CKn+0ShpTtzWhFpHHI5PvCUtiGI+C+Z2THE= 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/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= -github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/samber/slog-multi v1.0.2 h1:6BVH9uHGAsiGkbbtQgAOQJMpKgV8unMrHhhJaw+X1EQ= -github.com/samber/slog-multi v1.0.2/go.mod h1:uLAvHpGqbYgX4FSL0p1ZwoLuveIAJvBECtE07XmYvFo= +github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= +github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= +github.com/samber/slog-multi v1.2.3 h1:np8YoAZbGP699xA92SYZxs7zzKpL1/yBYk6q8/caXpc= +github.com/samber/slog-multi v1.2.3/go.mod h1:ACuZ5B6heK57TfMVkVknN2UZHoFfjCwRxR0Q2OXKHlo= github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGqpgjJU3DYAZeI05A= github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk= github.com/sassoftware/relic/v7 v7.6.2 h1:rS44Lbv9G9eXsukknS4mSjIAuuX+lMq/FnStgmZlUv4= github.com/sassoftware/relic/v7 v7.6.2/go.mod h1:kjmP0IBVkJZ6gXeAu35/KCEfca//+PKM6vTAsyDPY+k= -github.com/schollz/progressbar/v3 v3.14.2 h1:EducH6uNLIWsr560zSV1KrTeUb/wZGAHqyMFIEa99ks= -github.com/schollz/progressbar/v3 v3.14.2/go.mod h1:aQAZQnhF4JGFtRJiw/eobaXpsqpVQAftEQ+hLGXaRc4= +github.com/schollz/progressbar/v3 v3.16.1 h1:RnF1neWZFzLCoGx8yp1yF7SDl4AzNDI5y4I0aUJRrZQ= +github.com/schollz/progressbar/v3 v3.16.1/go.mod h1:I2ILR76gz5VXqYMIY/LdLecvMHDPVcQm3W/MSKi1TME= github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA= github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -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/siderolabs/talos/pkg/machinery v1.7.1 h1:sVFQ0lNE6+kOomSZA8iuktzG1A4zSW9KTsB2TLaTPsU= -github.com/siderolabs/talos/pkg/machinery v1.7.1/go.mod h1:YBl9KDCD45Uc7N0rXBY1JqovUn1n46ekUPSNbEVZzQU= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/siderolabs/talos/pkg/machinery v1.8.1 h1:oeJQmkLNjEG5jxrzPiC2XMQS5dcg1qZ17p5LKcaCbRM= +github.com/siderolabs/talos/pkg/machinery v1.8.1/go.mod h1:mWTmuUk8G6CdkhUfDmsrIkgPo0G6J5hC/zGazgnyzBg= github.com/sigstore/rekor v1.3.6 h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8= github.com/sigstore/rekor v1.3.6/go.mod h1:JDTSNNMdQ/PxdsS49DJkJ+pRJCO/83nbR5p3aZQteXc= -github.com/sigstore/sigstore v1.8.3 h1:G7LVXqL+ekgYtYdksBks9B38dPoIsbscjQJX/MGWkA4= -github.com/sigstore/sigstore v1.8.3/go.mod h1:mqbTEariiGA94cn6G3xnDiV6BD8eSLdL/eA7bvJ0fVs= +github.com/sigstore/sigstore v1.8.10 h1:r4t+TYzJlG9JdFxMy+um9GZhZ2N1hBTyTex0AHEZxFs= +github.com/sigstore/sigstore v1.8.10/go.mod h1:BekjqxS5ZtHNJC4u3Q3Stvfx2eyisbW/lUZzmPU2u4A= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -771,11 +794,11 @@ github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= -github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -797,14 +820,14 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI= github.com/theupdateframework/go-tuf v0.7.0/go.mod h1:uEB7WSY+7ZIugK6R1hiBMBjQftaFzn7ZCDJcp1tCUug= -github.com/tink-crypto/tink-go/v2 v2.1.0 h1:QXFBguwMwTIaU17EgZpEJWsUSc60b1BAGTzBIoMdmok= -github.com/tink-crypto/tink-go/v2 v2.1.0/go.mod h1:y1TnYFt1i2eZVfx4OGc+C+EMp4CoKWAw2VSEuoicHHI= +github.com/tink-crypto/tink-go/v2 v2.2.0 h1:L2Da0F2Udh2agtKztdr69mV/KpnY3/lGTkMgLTVIXlA= +github.com/tink-crypto/tink-go/v2 v2.2.0/go.mod h1:JJ6PomeNPF3cJpfWC0lgyTES6zpJILkAX0cJNwlS3xU= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs= github.com/transparency-dev/merkle v0.0.2 h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4= github.com/transparency-dev/merkle v0.0.2/go.mod h1:pqSy+OXefQ1EDUVmAJ8MUhHB9TXGuzVAT58PqBoHz1A= -github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= -github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= +github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= @@ -816,6 +839,8 @@ github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAh github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/vtolstov/go-ioctl v0.0.0-20151206205506-6be9cced4810 h1:X6ps8XHfpQjw8dUStzlMi2ybiKQ2Fmdw7UM+TinwvyM= github.com/vtolstov/go-ioctl v0.0.0-20151206205506-6be9cced4810/go.mod h1:dF0BBJ2YrV1+2eAIyEI+KeSidgA6HqoIP1u5XTlMq/o= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -838,41 +863,44 @@ github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1 github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms= github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= -github.com/zclconf/go-cty v1.14.3 h1:1JXy1XroaGrzZuG6X9dt7HL6s9AwbY+l4UNL8o5B6ho= -github.com/zclconf/go-cty v1.14.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= -go.etcd.io/etcd/api/v3 v3.5.13 h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4= -go.etcd.io/etcd/api/v3 v3.5.13/go.mod h1:gBqlqkcMMZMVTMm4NDZloEVJzxQOQIls8splbqBDa0c= -go.etcd.io/etcd/client/pkg/v3 v3.5.13 h1:RVZSAnWWWiI5IrYAXjQorajncORbS0zI48LQlE2kQWg= -go.etcd.io/etcd/client/pkg/v3 v3.5.13/go.mod h1:XxHT4u1qU12E2+po+UVPrEeL94Um6zL58ppuJWXSAB8= -go.etcd.io/etcd/client/v3 v3.5.13 h1:o0fHTNJLeO0MyVbc7I3fsCf6nrOqn5d+diSarKnB2js= -go.etcd.io/etcd/client/v3 v3.5.13/go.mod h1:cqiAeY8b5DEEcpxvgWKsbLIWNM/8Wy2xJSDMtioMcoI= +github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= +github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= +go.etcd.io/etcd/api/v3 v3.5.16 h1:WvmyJVbjWqK4R1E+B12RRHz3bRGy9XVfh++MgbN+6n0= +go.etcd.io/etcd/api/v3 v3.5.16/go.mod h1:1P4SlIP/VwkDmGo3OlOD7faPeP8KDIFhqvciH5EfN28= +go.etcd.io/etcd/client/pkg/v3 v3.5.16 h1:ZgY48uH6UvB+/7R9Yf4x574uCO3jIx0TRDyetSfId3Q= +go.etcd.io/etcd/client/pkg/v3 v3.5.16/go.mod h1:V8acl8pcEK0Y2g19YlOV9m9ssUe6MgiDSobSoaBAM0E= +go.etcd.io/etcd/client/v3 v3.5.16 h1:sSmVYOAHeC9doqi0gv7v86oY/BTld0SEFGaxsU9eRhE= +go.etcd.io/etcd/client/v3 v3.5.16/go.mod h1:X+rExSGkyqxvu276cr2OwPLBaeqFu1cIl4vmRjAD/50= go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0/go.mod h1:GijYcYmNpX1KazD5JmWGsi4P7dDTTTnfv1UbGn84MnU= +go.opentelemetry.io/contrib/detectors/gcp v1.29.0 h1:TiaiXB4DpGD3sdzNlYQxruQngn5Apwzi1X0DRhuGvDQ= +go.opentelemetry.io/contrib/detectors/gcp v1.29.0/go.mod h1:GW2aWZNwR2ZxDLdv8OyC2G8zkRoQBuURgV7RPQgcPoU= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= -go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.starlark.net v0.0.0-20210223155950-e043a3d3c984/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= +go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= +go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -887,15 +915,13 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -903,8 +929,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -920,14 +946,13 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -936,8 +961,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -963,36 +988,33 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1003,18 +1025,16 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= -golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/api v0.180.0 h1:M2D87Yo0rGBPWpo1orwfCLehUUL6E7/TYe5gvMQWDh4= -google.golang.org/api v0.180.0/go.mod h1:51AiyoEg1MJPSZ9zvklA8VnRILPXxn1iVen9v25XHAE= +google.golang.org/api v0.200.0 h1:0ytfNWn101is6e9VBoct2wrGDjOi5vn7jw5KtaQgDrU= +google.golang.org/api v0.200.0/go.mod h1:Tc5u9kcbjO7A8SwGlYj4IiVifJU01UqXtEgDMYmBmV8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= @@ -1022,19 +1042,21 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda h1:wu/KJm9KJwpfHWhkkZGohVC6KRrc1oJNr4jwtQMOQXw= -google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= -google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae h1:AH34z6WAGVNkllnKs5raNq3yRq93VnjBG6rpfub/jYk= -google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae/go.mod h1:FfiGhwUm6CJviekPrc0oJ+7h29e+DmWU6UtjX0ZvI7Y= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 h1:DujSIu+2tC9Ht0aPNA7jgj23Iq8Ewi5sgkQ++wdvonE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto v0.0.0-20241007155032-5fefd90f89a9 h1:nFS3IivktIU5Mk6KQa+v6RKkHUpdQpphqGNLxqNnbEk= +google.golang.org/genproto v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:tEzYTYZxbmVNOu0OAFH9HzdJtLn6h4Aj89zzlBCdHms= +google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f h1:jTm13A2itBi3La6yTGqn8bVSrc3ZZ1r8ENHlIXBfnRA= +google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f/go.mod h1:CLGoBuH1VHxAUXVPP8FfPwPEVJB6lz3URE5mY2SuayE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc/stats/opentelemetry v0.0.0-20240907200651-3ffb98b2c93a h1:UIpYSuWdWHSzjwcAFRLjKcPXFZVVLXGEM23W+NWqipw= +google.golang.org/grpc/stats/opentelemetry v0.0.0-20240907200651-3ffb98b2c93a/go.mod h1:9i1T9n4ZinTUZGgzENMi8MDDgbGC5mqTS75JAv6xN3A= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1046,16 +1068,16 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= -gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= @@ -1063,7 +1085,6 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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= @@ -1071,54 +1092,52 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= -helm.sh/helm v2.17.0+incompatible h1:cSe3FaQOpRWLDXvTObQNj0P7WI98IG5yloU6tQVls2k= -helm.sh/helm v2.17.0+incompatible/go.mod h1:0Xbc6ErzwWH9qC55X1+hE3ZwhM3atbhCm/NbFZw5i+4= -helm.sh/helm/v3 v3.14.4 h1:6FSpEfqyDalHq3kUr4gOMThhgY55kXUEjdQoyODYnrM= -helm.sh/helm/v3 v3.14.4/go.mod h1:Tje7LL4gprZpuBNTbG34d1Xn5NmRT3OWfBRwpOSer9I= +helm.sh/helm/v3 v3.16.2 h1:Y9v7ry+ubQmi+cb5zw1Llx8OKHU9Hk9NQ/+P+LGBe2o= +helm.sh/helm/v3 v3.16.2/go.mod h1:SyTXgKBjNqi2NPsHCW5dDAsHqvGIu0kdNYNH9gQaw70= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA= -k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE= -k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs= -k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y= -k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA= -k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= -k8s.io/apiserver v0.30.0 h1:QCec+U72tMQ+9tR6A0sMBB5Vh6ImCEkoKkTDRABWq6M= -k8s.io/apiserver v0.30.0/go.mod h1:smOIBq8t0MbKZi7O7SyIpjPsiKJ8qa+llcFCluKyqiY= -k8s.io/cli-runtime v0.29.0 h1:q2kC3cex4rOBLfPOnMSzV2BIrrQlx97gxHJs21KxKS4= -k8s.io/cli-runtime v0.29.0/go.mod h1:VKudXp3X7wR45L+nER85YUzOQIru28HQpXr0mTdeCrk= -k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ= -k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY= -k8s.io/cluster-bootstrap v0.30.0 h1:vaIjA1eMFpcLYz+p6NMj75aqiauDahFx9EkuTxc0GMI= -k8s.io/cluster-bootstrap v0.30.0/go.mod h1:/ceTq+EC/aOrQk27mfmFW/iOeQDqzKg6vYWIBFNHSAE= -k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o= -k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ= -k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= +k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= +k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40= +k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ= +k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= +k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/apiserver v0.31.1 h1:Sars5ejQDCRBY5f7R3QFHdqN3s61nhkpaX8/k1iEw1c= +k8s.io/apiserver v0.31.1/go.mod h1:lzDhpeToamVZJmmFlaLwdYZwd7zB+WYRYIboqA1kGxM= +k8s.io/cli-runtime v0.31.1 h1:/ZmKhmZ6hNqDM+yf9s3Y4KEYakNXUn5sod2LWGGwCuk= +k8s.io/cli-runtime v0.31.1/go.mod h1:pKv1cDIaq7ehWGuXQ+A//1OIF+7DI+xudXtExMCbe9U= +k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= +k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= +k8s.io/cluster-bootstrap v0.31.1 h1:lS5aJi2r6WEKnjO5UhbYsz8e3xmEfoF4Hiob/gnB/Nk= +k8s.io/cluster-bootstrap v0.31.1/go.mod h1:dxroRr4eQ0ekxis/kzGa1qODprQXAxQZrgDLfTk8Pug= +k8s.io/component-base v0.31.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8= +k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/kubectl v0.29.0 h1:Oqi48gXjikDhrBF67AYuZRTcJV4lg2l42GmvsP7FmYI= -k8s.io/kubectl v0.29.0/go.mod h1:0jMjGWIcMIQzmUaMgAzhSELv5WtHo2a8pq67DtviAJs= -k8s.io/kubelet v0.30.0 h1:/pqHVR2Rn8ExCpn211wL3pMtqRFpcBcJPl4+1INbIMk= -k8s.io/kubelet v0.30.0/go.mod h1:WukdKqbQxnj+csn3K8XOKeX7Sh60J/da25IILjvvB5s= -k8s.io/kubernetes v1.30.0 h1:u3Yw8rNlo2NDSGaDpoxoHXLPQnEu1tfqHATKOJe94HY= -k8s.io/kubernetes v1.30.0/go.mod h1:yPbIk3MhmhGigX62FLJm+CphNtjxqCvAIFQXup6RKS0= -k8s.io/mount-utils v0.30.0 h1:EceYTNYVabfpdtIAHC4KgMzoZkm1B8ovZ1J666mYZQI= -k8s.io/mount-utils v0.30.0/go.mod h1:9sCVmwGLcV1MPvbZ+rToMDnl1QcGozy+jBPd0MsQLIo= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -libvirt.org/go/libvirt v1.10003.0 h1:LEoawzuggD6IL5R/XtnBE8wWJx49i7UZ1HcB7p9glwE= -libvirt.org/go/libvirt v1.10003.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ= +k8s.io/kubectl v0.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24= +k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM= +k8s.io/kubelet v0.31.1 h1:aAxwVxGzbbMKKk/FnSjvkN52K3LdHhjhzmYcyGBuE0c= +k8s.io/kubelet v0.31.1/go.mod h1:8ZbexYHqUO946gXEfFmnMZiK2UKRGhk7LlGvJ71p2Ig= +k8s.io/kubernetes v1.31.1 h1:1fcYJe8SAhtannpChbmnzHLwAV9Je99PrGaFtBvCxms= +k8s.io/kubernetes v1.31.1/go.mod h1:/YGPL//Fb9mdv5vukvAQ7Xon+Bqwry52bmjTdORAw+Q= +k8s.io/mount-utils v0.31.1 h1:f8UrH9kRynljmdNGM6BaCvFUON5ZPKDgE+ltmYqI4wA= +k8s.io/mount-utils v0.31.1/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU= +k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY9mD9fNT47QO6HI= +k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +libvirt.org/go/libvirt v1.10008.0 h1:j+hybvOmBQFC2BiivOVCPE3ozpQWtxWXp9p1cGk0x1Y= +libvirt.org/go/libvirt v1.10008.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= -sigs.k8s.io/controller-runtime v0.18.2 h1:RqVW6Kpeaji67CY5nPEfRz6ZfFMk0lWQlNrLqlNpx+Q= -sigs.k8s.io/controller-runtime v0.18.2/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw= +sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= +sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= +sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g= +sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0= +sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= +sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/go.work b/go.work index 260ad61e4..0cf42a018 100644 --- a/go.work +++ b/go.work @@ -1,6 +1,6 @@ -go 1.22.3 +go 1.23.2 -toolchain go1.22.3 +toolchain go1.23.2 use ( . diff --git a/hack/bazel-deps-mirror/README.md b/hack/bazel-deps-mirror/README.md index 9aa5fb21e..354e506ab 100644 --- a/hack/bazel-deps-mirror/README.md +++ b/hack/bazel-deps-mirror/README.md @@ -2,7 +2,7 @@ This directory contains tooling to automatically mirror the dependencies of a Bazel project into the Constellation CDN at `https://cdn.confidential.cloud/`. -The tool searches for various rules in the WORKSPACE.bazel file and all loaded .bzl files. +The tool searches for various rules in the WORKSPACE.bzlmod file and all loaded .bzl files. It has the following commands: - check: checks if the dependencies all have a mirror URL and optionally checks if the mirror really returns the expected file diff --git a/hack/bazel-deps-mirror/internal/bazelfiles/files.go b/hack/bazel-deps-mirror/internal/bazelfiles/files.go index 468ff24ac..d1c32135d 100644 --- a/hack/bazel-deps-mirror/internal/bazelfiles/files.go +++ b/hack/bazel-deps-mirror/internal/bazelfiles/files.go @@ -53,12 +53,12 @@ func (h *Helper) FindFiles() ([]BazelFile, error) { return append(bzlFiles, workspaceFile), nil } -// findWorkspaceFile returns the path to the Bazel WORKSPACE.bazel file (or WORKSPACE if the former doesn't exist). +// findWorkspaceFile returns the path to the Bazel WORKSPACE.bzlmod file (or WORKSPACE if the former doesn't exist). func (h *Helper) findWorkspaceFile() (BazelFile, error) { - if _, err := h.fs.Stat("WORKSPACE.bazel"); err == nil { + if _, err := h.fs.Stat("WORKSPACE.bzlmod"); err == nil { return BazelFile{ - RelPath: "WORKSPACE.bazel", - AbsPath: filepath.Join(h.workspaceRoot, "WORKSPACE.bazel"), + RelPath: "WORKSPACE.bzlmod", + AbsPath: filepath.Join(h.workspaceRoot, "WORKSPACE.bzlmod"), Type: BazelFileTypeWorkspace, }, nil } @@ -151,7 +151,7 @@ type BazelFileType int const ( BazelFileTypeBzl = iota // BazelFileTypeBzl is a .bzl file - BazelFileTypeWorkspace // BazelFileTypeWorkspace is a WORKSPACE or WORKSPACE.bazel file + BazelFileTypeWorkspace // BazelFileTypeWorkspace is a WORKSPACE or WORKSPACE.bzlmod file ) // LookupEnv can be the real os.LookupEnv or a mock for testing. diff --git a/hack/bazel-deps-mirror/internal/bazelfiles/files_test.go b/hack/bazel-deps-mirror/internal/bazelfiles/files_test.go index c7d37770b..92cb1a0ae 100644 --- a/hack/bazel-deps-mirror/internal/bazelfiles/files_test.go +++ b/hack/bazel-deps-mirror/internal/bazelfiles/files_test.go @@ -42,22 +42,22 @@ func TestFindFiles(t *testing.T) { }, }, }, - "only WORKSPACE.bazel file": { - files: []string{"WORKSPACE.bazel"}, + "only WORKSPACE.bzlmod file": { + files: []string{"WORKSPACE.bzlmod"}, wantFiles: []BazelFile{ { - RelPath: "WORKSPACE.bazel", - AbsPath: "/WORKSPACE.bazel", + RelPath: "WORKSPACE.bzlmod", + AbsPath: "/WORKSPACE.bzlmod", Type: BazelFileTypeWorkspace, }, }, }, - "both WORKSPACE and WORKSPACE.bazel files": { - files: []string{"WORKSPACE", "WORKSPACE.bazel"}, + "both WORKSPACE and WORKSPACE.bzlmod files": { + files: []string{"WORKSPACE", "WORKSPACE.bzlmod"}, wantFiles: []BazelFile{ { - RelPath: "WORKSPACE.bazel", - AbsPath: "/WORKSPACE.bazel", + RelPath: "WORKSPACE.bzlmod", + AbsPath: "/WORKSPACE.bzlmod", Type: BazelFileTypeWorkspace, }, }, @@ -67,11 +67,11 @@ func TestFindFiles(t *testing.T) { wantErr: true, }, "all kinds": { - files: []string{"WORKSPACE", "WORKSPACE.bazel", "foo.bzl", "bar.bzl", "unused.txt", "folder/baz.bzl"}, + files: []string{"WORKSPACE", "WORKSPACE.bzlmod", "foo.bzl", "bar.bzl", "unused.txt", "folder/baz.bzl"}, wantFiles: []BazelFile{ { - RelPath: "WORKSPACE.bazel", - AbsPath: "/WORKSPACE.bazel", + RelPath: "WORKSPACE.bzlmod", + AbsPath: "/WORKSPACE.bzlmod", Type: BazelFileTypeWorkspace, }, { @@ -216,15 +216,15 @@ func TestDiff(t *testing.T) { assert := assert.New(t) require := require.New(t) fs := afero.NewMemMapFs() - err := afero.WriteFile(fs, "WORKSPACE.bazel", []byte(""), 0o644) + err := afero.WriteFile(fs, "WORKSPACE.bzlmod", []byte(""), 0o644) require.NoError(err) helper := Helper{ fs: fs, workspaceRoot: "/", } fileRef := BazelFile{ - RelPath: "WORKSPACE.bazel", - AbsPath: "/WORKSPACE.bazel", + RelPath: "WORKSPACE.bzlmod", + AbsPath: "/WORKSPACE.bzlmod", Type: BazelFileTypeWorkspace, } bf, err := helper.LoadFile(fileRef) @@ -247,10 +247,10 @@ func TestDiff(t *testing.T) { ) diff, err = helper.Diff(fileRef, bf) require.NoError(err) - assert.Equal("--- a/WORKSPACE.bazel\n+++ b/WORKSPACE.bazel\n@@ -1 +1 @@\n+workspace(name = \"foo\")\n", diff) + assert.Equal("--- a/WORKSPACE.bzlmod\n+++ b/WORKSPACE.bzlmod\n@@ -1 +1 @@\n+workspace(name = \"foo\")\n", diff) err = helper.WriteFile(fileRef, bf) require.NoError(err) - contents, err := afero.ReadFile(fs, "WORKSPACE.bazel") + contents, err := afero.ReadFile(fs, "WORKSPACE.bzlmod") assert.NoError(err) assert.Equal("workspace(name = \"foo\")\n", string(contents)) diff, err = helper.Diff(fileRef, bf) diff --git a/hack/qemu-metadata-api/BUILD.bazel b/hack/qemu-metadata-api/BUILD.bazel index 67811771c..2cfbeb83a 100644 --- a/hack/qemu-metadata-api/BUILD.bazel +++ b/hack/qemu-metadata-api/BUILD.bazel @@ -13,8 +13,9 @@ go_library( importpath = "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api", visibility = ["//visibility:private"], deps = [ + "//hack/qemu-metadata-api/dhcp/dnsmasq", + "//hack/qemu-metadata-api/dhcp/virtwrapper", "//hack/qemu-metadata-api/server", - "//hack/qemu-metadata-api/virtwrapper", "//internal/logger", "@org_libvirt_go_libvirt//:libvirt", ], diff --git a/hack/qemu-metadata-api/dhcp/BUILD.bazel b/hack/qemu-metadata-api/dhcp/BUILD.bazel new file mode 100644 index 000000000..21ba5404c --- /dev/null +++ b/hack/qemu-metadata-api/dhcp/BUILD.bazel @@ -0,0 +1,8 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "dhcp", + srcs = ["dhcp.go"], + importpath = "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/dhcp", + visibility = ["//visibility:public"], +) diff --git a/hack/qemu-metadata-api/virtwrapper/virtwrapper.go b/hack/qemu-metadata-api/dhcp/dhcp.go similarity index 67% rename from hack/qemu-metadata-api/virtwrapper/virtwrapper.go rename to hack/qemu-metadata-api/dhcp/dhcp.go index 4e5fb6732..6474b6666 100644 --- a/hack/qemu-metadata-api/virtwrapper/virtwrapper.go +++ b/hack/qemu-metadata-api/dhcp/dhcp.go @@ -4,9 +4,9 @@ Copyright (c) Edgeless Systems GmbH SPDX-License-Identifier: AGPL-3.0-only */ -package virtwrapper +package dhcp -// NetworkDHCPLease abstracts a libvirt DHCP lease. +// NetworkDHCPLease abstracts a DHCP lease. type NetworkDHCPLease struct { IPaddr string Hostname string diff --git a/hack/qemu-metadata-api/dhcp/dnsmasq/BUILD.bazel b/hack/qemu-metadata-api/dhcp/dnsmasq/BUILD.bazel new file mode 100644 index 000000000..ab5bbd249 --- /dev/null +++ b/hack/qemu-metadata-api/dhcp/dnsmasq/BUILD.bazel @@ -0,0 +1,24 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("//bazel/go:go_test.bzl", "go_test") + +go_library( + name = "dnsmasq", + srcs = ["dnsmasq.go"], + importpath = "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/dhcp/dnsmasq", + visibility = ["//visibility:public"], + deps = [ + "//hack/qemu-metadata-api/dhcp", + "@com_github_spf13_afero//:afero", + ], +) + +go_test( + name = "dnsmasq_test", + srcs = ["dnsmasq_test.go"], + embed = [":dnsmasq"], + deps = [ + "@com_github_spf13_afero//:afero", + "@com_github_stretchr_testify//assert", + "@com_github_stretchr_testify//require", + ], +) diff --git a/hack/qemu-metadata-api/dhcp/dnsmasq/dnsmasq.go b/hack/qemu-metadata-api/dhcp/dnsmasq/dnsmasq.go new file mode 100644 index 000000000..1e75e2abd --- /dev/null +++ b/hack/qemu-metadata-api/dhcp/dnsmasq/dnsmasq.go @@ -0,0 +1,56 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package dnsmasq + +import ( + "bufio" + "strings" + + "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/dhcp" + "github.com/spf13/afero" +) + +// DNSMasq is a DHCP lease getter for dnsmasq. +type DNSMasq struct { + leasesFileName string + fs *afero.Afero +} + +// New creates a new DNSMasq. +func New(leasesFileName string) *DNSMasq { + return &DNSMasq{ + leasesFileName: leasesFileName, + fs: &afero.Afero{Fs: afero.NewOsFs()}, + } +} + +// GetDHCPLeases returns the underlying DHCP leases. +func (d *DNSMasq) GetDHCPLeases() ([]dhcp.NetworkDHCPLease, error) { + file, err := d.fs.Open(d.leasesFileName) + if err != nil { + return nil, err + } + defer file.Close() + + // read file + var leases []dhcp.NetworkDHCPLease + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + // split by whitespace + fields := strings.Fields(line) + leases = append(leases, dhcp.NetworkDHCPLease{ + IPaddr: fields[2], + Hostname: fields[3], + }) + } + if err := scanner.Err(); err != nil { + return nil, err + } + + return leases, nil +} diff --git a/hack/qemu-metadata-api/dhcp/dnsmasq/dnsmasq_test.go b/hack/qemu-metadata-api/dhcp/dnsmasq/dnsmasq_test.go new file mode 100644 index 000000000..66a4483cd --- /dev/null +++ b/hack/qemu-metadata-api/dhcp/dnsmasq/dnsmasq_test.go @@ -0,0 +1,40 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package dnsmasq + +import ( + "testing" + + "github.com/spf13/afero" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetDHCPLeases(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + + fs := afero.NewMemMapFs() + leasesFileName := "dnsmasq.leases" + leasesFile, err := fs.Create(leasesFileName) + require.NoError(err) + _, err = leasesFile.WriteString("1716219737 52:54:af:a1:98:9f 10.42.2.1 worker0 ff:c2:72:f6:09:00:02:00:00:ab:11:18:fc:48:85:40:3f:bc:41\n") + require.NoError(err) + _, err = leasesFile.WriteString("1716219735 52:54:7f:8f:ba:91 10.42.1.1 controlplane0 ff:c2:72:f6:09:00:02:00:00:ab:11:21:7c:b5:14:ec:43:b7:43\n") + require.NoError(err) + leasesFile.Close() + + d := DNSMasq{leasesFileName: leasesFileName, fs: &afero.Afero{Fs: fs}} + leases, err := d.GetDHCPLeases() + require.NoError(err) + + assert.Len(leases, 2) + assert.Equal("10.42.2.1", leases[0].IPaddr) + assert.Equal("worker0", leases[0].Hostname) + assert.Equal("10.42.1.1", leases[1].IPaddr) + assert.Equal("controlplane0", leases[1].Hostname) +} diff --git a/hack/qemu-metadata-api/virtwrapper/BUILD.bazel b/hack/qemu-metadata-api/dhcp/virtwrapper/BUILD.bazel similarity index 68% rename from hack/qemu-metadata-api/virtwrapper/BUILD.bazel rename to hack/qemu-metadata-api/dhcp/virtwrapper/BUILD.bazel index c1ad3b7c9..762c0b301 100644 --- a/hack/qemu-metadata-api/virtwrapper/BUILD.bazel +++ b/hack/qemu-metadata-api/dhcp/virtwrapper/BUILD.bazel @@ -7,7 +7,10 @@ go_library( "virtwrapper_cgo.go", "virtwrapper_cross.go", ], - importpath = "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper", + importpath = "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/dhcp/virtwrapper", visibility = ["//visibility:public"], - deps = ["@org_libvirt_go_libvirt//:libvirt"], + deps = [ + "//hack/qemu-metadata-api/dhcp", + "@org_libvirt_go_libvirt//:libvirt", + ], ) diff --git a/hack/qemu-metadata-api/dhcp/virtwrapper/virtwrapper.go b/hack/qemu-metadata-api/dhcp/virtwrapper/virtwrapper.go new file mode 100644 index 000000000..fa77b81de --- /dev/null +++ b/hack/qemu-metadata-api/dhcp/virtwrapper/virtwrapper.go @@ -0,0 +1,7 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package virtwrapper diff --git a/hack/qemu-metadata-api/dhcp/virtwrapper/virtwrapper_cgo.go b/hack/qemu-metadata-api/dhcp/virtwrapper/virtwrapper_cgo.go new file mode 100644 index 000000000..bacd3c81f --- /dev/null +++ b/hack/qemu-metadata-api/dhcp/virtwrapper/virtwrapper_cgo.go @@ -0,0 +1,60 @@ +//go:build cgo + +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package virtwrapper + +import ( + "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/dhcp" + + "libvirt.org/go/libvirt" +) + +// Connect wraps a libvirt connection. +type Connect struct { + conn *libvirt.Connect + networkName string +} + +// New creates a new libvirt Connct wrapper. +func New(conn *libvirt.Connect, networkName string) *Connect { + return &Connect{ + conn: conn, + networkName: networkName, + } +} + +// LookupNetworkByName looks up a network by name. +func (c *Connect) lookupNetworkByName(name string) (*libvirt.Network, error) { + net, err := c.conn.LookupNetworkByName(name) + if err != nil { + return nil, err + } + return net, nil +} + +// GetDHCPLeases returns the underlying DHCP leases. +func (c *Connect) GetDHCPLeases() ([]dhcp.NetworkDHCPLease, error) { + net, err := c.lookupNetworkByName(c.networkName) + if err != nil { + return nil, err + } + defer net.Free() + + leases, err := net.GetDHCPLeases() + if err != nil { + return nil, err + } + ret := make([]dhcp.NetworkDHCPLease, len(leases)) + for i, l := range leases { + ret[i] = dhcp.NetworkDHCPLease{ + IPaddr: l.IPaddr, + Hostname: l.Hostname, + } + } + return ret, nil +} diff --git a/hack/qemu-metadata-api/dhcp/virtwrapper/virtwrapper_cross.go b/hack/qemu-metadata-api/dhcp/virtwrapper/virtwrapper_cross.go new file mode 100644 index 000000000..58e12f0f7 --- /dev/null +++ b/hack/qemu-metadata-api/dhcp/virtwrapper/virtwrapper_cross.go @@ -0,0 +1,24 @@ +//go:build !cgo + +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package virtwrapper + +import ( + "errors" + + "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/dhcp" +) + +// Connect wraps a libvirt connection. +type Connect struct{} + +// GetDHCPLeases returns the underlying DHCP leases. +// This function errors if CGO is disabled. +func (n *Connect) GetDHCPLeases() ([]dhcp.NetworkDHCPLease, error) { + return nil, errors.New("using virtwrapper requires building with CGO") +} diff --git a/hack/qemu-metadata-api/main.go b/hack/qemu-metadata-api/main.go index dd5be683c..5169200b3 100644 --- a/hack/qemu-metadata-api/main.go +++ b/hack/qemu-metadata-api/main.go @@ -13,29 +13,38 @@ import ( "log/slog" "os" + "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/dhcp/dnsmasq" + "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/dhcp/virtwrapper" "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/server" - "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper" "github.com/edgelesssys/constellation/v2/internal/logger" "libvirt.org/go/libvirt" ) func main() { bindPort := flag.String("port", "8080", "Port to bind to") - targetNetwork := flag.String("network", "constellation-network", "Name of the network in QEMU to use") + targetNetwork := flag.String("network", "constellation-network", "Name of the network in libvirt") libvirtURI := flag.String("libvirt-uri", "qemu:///system", "URI of the libvirt connection") + leasesFileName := flag.String("dnsmasq-leases", "", "Path to the dnsmasq leases file") initSecretHash := flag.String("initsecrethash", "", "brcypt hash of the init secret") flag.Parse() log := logger.NewJSONLogger(slog.LevelInfo) - conn, err := libvirt.NewConnect(*libvirtURI) - if err != nil { - log.With(slog.Any("error", err)).Error("Failed to connect to libvirt") - os.Exit(1) + var leaseGetter server.LeaseGetter + if *leasesFileName == "" { + conn, err := libvirt.NewConnect(*libvirtURI) + if err != nil { + log.With(slog.Any("error", err)).Error("Failed to connect to libvirt") + os.Exit(1) + } + defer conn.Close() + leaseGetter = virtwrapper.New(conn, *targetNetwork) + } else { + log.Info("Using dnsmasq leases file") + leaseGetter = dnsmasq.New(*leasesFileName) } - defer conn.Close() - serv := server.New(log, *targetNetwork, *initSecretHash, &virtwrapper.Connect{Conn: conn}) + serv := server.New(log, *targetNetwork, *initSecretHash, leaseGetter) if err := serv.ListenAndServe(*bindPort); err != nil { log.With(slog.Any("error", err)).Error("Failed to serve") os.Exit(1) diff --git a/hack/qemu-metadata-api/server/BUILD.bazel b/hack/qemu-metadata-api/server/BUILD.bazel index 5def36c03..683ec416a 100644 --- a/hack/qemu-metadata-api/server/BUILD.bazel +++ b/hack/qemu-metadata-api/server/BUILD.bazel @@ -10,7 +10,7 @@ go_library( ], visibility = ["//visibility:public"], deps = [ - "//hack/qemu-metadata-api/virtwrapper", + "//hack/qemu-metadata-api/dhcp", "//internal/cloud/metadata", "//internal/role", ], @@ -18,22 +18,17 @@ go_library( go_test( name = "server_test", - srcs = [ - "server_cgo_test.go", - "server_cross_test.go", - "server_test.go", - ], + srcs = ["server_test.go"], embed = [":server"], # keep pure = "on", # keep race = "off", deps = [ - "//hack/qemu-metadata-api/virtwrapper", + "//hack/qemu-metadata-api/dhcp", "//internal/cloud/metadata", "//internal/logger", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", - "@org_libvirt_go_libvirt//:libvirt", ], ) diff --git a/hack/qemu-metadata-api/server/server.go b/hack/qemu-metadata-api/server/server.go index 4f0cad9e9..2b3817247 100644 --- a/hack/qemu-metadata-api/server/server.go +++ b/hack/qemu-metadata-api/server/server.go @@ -14,7 +14,7 @@ import ( "net/http" "strings" - "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper" + "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/dhcp" "github.com/edgelesssys/constellation/v2/internal/cloud/metadata" "github.com/edgelesssys/constellation/v2/internal/role" ) @@ -22,16 +22,16 @@ import ( // Server that provides QEMU metadata. type Server struct { log *slog.Logger - virt virConnect + dhcpLeaseGetter LeaseGetter network string initSecretHashVal []byte } // New creates a new Server. -func New(log *slog.Logger, network, initSecretHash string, conn virConnect) *Server { +func New(log *slog.Logger, network, initSecretHash string, getter LeaseGetter) *Server { return &Server{ log: log, - virt: conn, + dhcpLeaseGetter: getter, network: network, initSecretHashVal: []byte(initSecretHash), } @@ -139,15 +139,7 @@ func (s *Server) getEndpoint(w http.ResponseWriter, r *http.Request) { log := s.log.With(slog.String("peer", r.RemoteAddr)) log.Info("Serving GET request for /endpoint") - net, err := s.virt.LookupNetworkByName(s.network) - if err != nil { - log.With(slog.Any("error", err)).Error("Failed to lookup network") - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - defer net.Free() - - leases, err := net.GetDHCPLeases() + leases, err := s.dhcpLeaseGetter.GetDHCPLeases() if err != nil { log.With(slog.Any("error", err)).Error("Failed to get DHCP leases") http.Error(w, err.Error(), http.StatusInternalServerError) @@ -172,13 +164,7 @@ func (s *Server) getEndpoint(w http.ResponseWriter, r *http.Request) { // listAll returns a list of all active peers. func (s *Server) listAll() ([]metadata.InstanceMetadata, error) { - net, err := s.virt.LookupNetworkByName(s.network) - if err != nil { - return nil, err - } - defer net.Free() - - leases, err := net.GetDHCPLeases() + leases, err := s.dhcpLeaseGetter.GetDHCPLeases() if err != nil { return nil, err } @@ -201,6 +187,7 @@ func (s *Server) listAll() ([]metadata.InstanceMetadata, error) { return peers, nil } -type virConnect interface { - LookupNetworkByName(name string) (*virtwrapper.Network, error) +// LeaseGetter is an interface for getting DHCP leases. +type LeaseGetter interface { + GetDHCPLeases() ([]dhcp.NetworkDHCPLease, error) } diff --git a/hack/qemu-metadata-api/server/server_cgo_test.go b/hack/qemu-metadata-api/server/server_cgo_test.go deleted file mode 100644 index 59c569535..000000000 --- a/hack/qemu-metadata-api/server/server_cgo_test.go +++ /dev/null @@ -1,41 +0,0 @@ -//go:build cgo - -/* -Copyright (c) Edgeless Systems GmbH - -SPDX-License-Identifier: AGPL-3.0-only -*/ - -package server - -import ( - "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper" - "libvirt.org/go/libvirt" -) - -type stubNetwork struct { - leases []libvirt.NetworkDHCPLease - getLeaseErr error -} - -func newStubNetwork(leases []virtwrapper.NetworkDHCPLease, getLeaseErr error) stubNetwork { - libvirtLeases := make([]libvirt.NetworkDHCPLease, len(leases)) - for i, l := range leases { - libvirtLeases[i] = libvirt.NetworkDHCPLease{ - IPaddr: l.IPaddr, - Hostname: l.Hostname, - } - } - return stubNetwork{ - leases: libvirtLeases, - getLeaseErr: getLeaseErr, - } -} - -func (n stubNetwork) GetDHCPLeases() ([]libvirt.NetworkDHCPLease, error) { - return n.leases, n.getLeaseErr -} - -func (n stubNetwork) Free() error { - return nil -} diff --git a/hack/qemu-metadata-api/server/server_cross_test.go b/hack/qemu-metadata-api/server/server_cross_test.go deleted file mode 100644 index 3f4488b26..000000000 --- a/hack/qemu-metadata-api/server/server_cross_test.go +++ /dev/null @@ -1,31 +0,0 @@ -//go:build !cgo - -/* -Copyright (c) Edgeless Systems GmbH - -SPDX-License-Identifier: AGPL-3.0-only -*/ - -package server - -import "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper" - -type stubNetwork struct { - leases []virtwrapper.NetworkDHCPLease - getLeaseErr error -} - -func newStubNetwork(leases []virtwrapper.NetworkDHCPLease, getLeaseErr error) stubNetwork { - return stubNetwork{ - leases: leases, - getLeaseErr: getLeaseErr, - } -} - -func (n stubNetwork) GetDHCPLeases() ([]virtwrapper.NetworkDHCPLease, error) { - return n.leases, n.getLeaseErr -} - -func (n stubNetwork) Free() error { - return nil -} diff --git a/hack/qemu-metadata-api/server/server_test.go b/hack/qemu-metadata-api/server/server_test.go index 3b04d214d..363cb3ed2 100644 --- a/hack/qemu-metadata-api/server/server_test.go +++ b/hack/qemu-metadata-api/server/server_test.go @@ -9,13 +9,12 @@ package server import ( "context" "encoding/json" - "errors" "io" "net/http" "net/http/httptest" "testing" - "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper" + "github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/dhcp" "github.com/edgelesssys/constellation/v2/internal/cloud/metadata" "github.com/edgelesssys/constellation/v2/internal/logger" "github.com/stretchr/testify/assert" @@ -23,15 +22,13 @@ import ( ) func TestListAll(t *testing.T) { - someErr := errors.New("error") - testCases := map[string]struct { - wantErr bool - connect *stubConnect + wantErr bool + stubLeaseGetter *stubLeaseGetter }{ "success": { - connect: &stubConnect{ - network: newStubNetwork([]virtwrapper.NetworkDHCPLease{ + stubLeaseGetter: &stubLeaseGetter{ + leases: []dhcp.NetworkDHCPLease{ { IPaddr: "192.0.100.1", Hostname: "control-plane-0", @@ -44,20 +41,12 @@ func TestListAll(t *testing.T) { IPaddr: "192.0.200.1", Hostname: "worker-0", }, - }, nil), + }, }, }, - "LookupNetworkByName error": { - connect: &stubConnect{ - getNetworkErr: someErr, - }, - wantErr: true, - }, "GetDHCPLeases error": { - connect: &stubConnect{ - network: stubNetwork{ - getLeaseErr: someErr, - }, + stubLeaseGetter: &stubLeaseGetter{ + getErr: assert.AnError, }, wantErr: true, }, @@ -67,7 +56,7 @@ func TestListAll(t *testing.T) { t.Run(name, func(t *testing.T) { assert := assert.New(t) - server := New(logger.NewTest(t), "test", "initSecretHash", tc.connect) + server := New(logger.NewTest(t), "test", "initSecretHash", tc.stubLeaseGetter) res, err := server.listAll() @@ -76,58 +65,56 @@ func TestListAll(t *testing.T) { return } assert.NoError(err) - assert.Len(tc.connect.network.leases, len(res)) + assert.Len(tc.stubLeaseGetter.leases, len(res)) }) } } func TestListSelf(t *testing.T) { - someErr := errors.New("error") - testCases := map[string]struct { - remoteAddr string - connect *stubConnect - wantErr bool + remoteAddr string + stubLeaseGetter *stubLeaseGetter + wantErr bool }{ "success": { remoteAddr: "192.0.100.1:1234", - connect: &stubConnect{ - network: newStubNetwork([]virtwrapper.NetworkDHCPLease{ + stubLeaseGetter: &stubLeaseGetter{ + leases: []dhcp.NetworkDHCPLease{ { IPaddr: "192.0.100.1", Hostname: "control-plane-0", }, - }, nil), + }, }, }, "listAll error": { remoteAddr: "192.0.100.1:1234", - connect: &stubConnect{ - getNetworkErr: someErr, + stubLeaseGetter: &stubLeaseGetter{ + getErr: assert.AnError, }, wantErr: true, }, "remoteAddr error": { remoteAddr: "", - connect: &stubConnect{ - network: newStubNetwork([]virtwrapper.NetworkDHCPLease{ + stubLeaseGetter: &stubLeaseGetter{ + leases: []dhcp.NetworkDHCPLease{ { IPaddr: "192.0.100.1", Hostname: "control-plane-0", }, - }, nil), + }, }, wantErr: true, }, "peer not found": { remoteAddr: "192.0.200.1:1234", - connect: &stubConnect{ - network: newStubNetwork([]virtwrapper.NetworkDHCPLease{ + stubLeaseGetter: &stubLeaseGetter{ + leases: []dhcp.NetworkDHCPLease{ { IPaddr: "192.0.100.1", Hostname: "control-plane-0", }, - }, nil), + }, }, wantErr: true, }, @@ -138,7 +125,7 @@ func TestListSelf(t *testing.T) { assert := assert.New(t) require := require.New(t) - server := New(logger.NewTest(t), "test", "initSecretHash", tc.connect) + server := New(logger.NewTest(t), "test", "initSecretHash", tc.stubLeaseGetter) req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://192.0.0.1/self", nil) require.NoError(err) @@ -157,22 +144,22 @@ func TestListSelf(t *testing.T) { var metadata metadata.InstanceMetadata require.NoError(json.Unmarshal(metadataRaw, &metadata)) - assert.Equal(tc.connect.network.leases[0].Hostname, metadata.Name) - assert.Equal(tc.connect.network.leases[0].IPaddr, metadata.VPCIP) + assert.Equal(tc.stubLeaseGetter.leases[0].Hostname, metadata.Name) + assert.Equal(tc.stubLeaseGetter.leases[0].IPaddr, metadata.VPCIP) }) } } func TestListPeers(t *testing.T) { testCases := map[string]struct { - remoteAddr string - connect *stubConnect - wantErr bool + remoteAddr string + stubNetworkGetter *stubLeaseGetter + wantErr bool }{ "success": { remoteAddr: "192.0.100.1:1234", - connect: &stubConnect{ - network: newStubNetwork([]virtwrapper.NetworkDHCPLease{ + stubNetworkGetter: &stubLeaseGetter{ + leases: []dhcp.NetworkDHCPLease{ { IPaddr: "192.0.100.1", Hostname: "control-plane-0", @@ -181,13 +168,13 @@ func TestListPeers(t *testing.T) { IPaddr: "192.0.200.1", Hostname: "worker-0", }, - }, nil), + }, }, }, "listAll error": { remoteAddr: "192.0.100.1:1234", - connect: &stubConnect{ - getNetworkErr: errors.New("error"), + stubNetworkGetter: &stubLeaseGetter{ + getErr: assert.AnError, }, wantErr: true, }, @@ -198,7 +185,7 @@ func TestListPeers(t *testing.T) { assert := assert.New(t) require := require.New(t) - server := New(logger.NewTest(t), "test", "initSecretHash", tc.connect) + server := New(logger.NewTest(t), "test", "initSecretHash", tc.stubNetworkGetter) req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://192.0.0.1/peers", nil) require.NoError(err) @@ -217,22 +204,23 @@ func TestListPeers(t *testing.T) { var metadata []metadata.InstanceMetadata require.NoError(json.Unmarshal(metadataRaw, &metadata)) - assert.Len(metadata, len(tc.connect.network.leases)) + assert.Len(metadata, len(tc.stubNetworkGetter.leases)) }) } } func TestInitSecretHash(t *testing.T) { - defaultConnect := &stubConnect{ - network: newStubNetwork([]virtwrapper.NetworkDHCPLease{ + defaultConnect := &stubLeaseGetter{ + leases: []dhcp.NetworkDHCPLease{ { IPaddr: "192.0.100.1", Hostname: "control-plane-0", }, - }, nil), + }, } + testCases := map[string]struct { - connect *stubConnect + connect *stubLeaseGetter method string wantHash string wantErr bool @@ -272,11 +260,11 @@ func TestInitSecretHash(t *testing.T) { } } -type stubConnect struct { - network stubNetwork - getNetworkErr error +type stubLeaseGetter struct { + leases []dhcp.NetworkDHCPLease + getErr error } -func (c stubConnect) LookupNetworkByName(_ string) (*virtwrapper.Network, error) { - return &virtwrapper.Network{Net: c.network}, c.getNetworkErr +func (c stubLeaseGetter) GetDHCPLeases() ([]dhcp.NetworkDHCPLease, error) { + return c.leases, c.getErr } diff --git a/hack/qemu-metadata-api/virtwrapper/virtwrapper_cgo.go b/hack/qemu-metadata-api/virtwrapper/virtwrapper_cgo.go deleted file mode 100644 index cda0bed96..000000000 --- a/hack/qemu-metadata-api/virtwrapper/virtwrapper_cgo.go +++ /dev/null @@ -1,56 +0,0 @@ -//go:build cgo - -/* -Copyright (c) Edgeless Systems GmbH - -SPDX-License-Identifier: AGPL-3.0-only -*/ - -package virtwrapper - -import "libvirt.org/go/libvirt" - -// Connect wraps a libvirt connection. -type Connect struct { - Conn *libvirt.Connect -} - -// LookupNetworkByName looks up a network by name. -func (c *Connect) LookupNetworkByName(name string) (*Network, error) { - net, err := c.Conn.LookupNetworkByName(name) - if err != nil { - return nil, err - } - return &Network{Net: net}, nil -} - -// Network wraps a libvirt network. -type Network struct { - Net virNetwork -} - -// GetDHCPLeases returns the underlying DHCP leases. -func (n *Network) GetDHCPLeases() ([]NetworkDHCPLease, error) { - leases, err := n.Net.GetDHCPLeases() - if err != nil { - return nil, err - } - ret := make([]NetworkDHCPLease, len(leases)) - for i, l := range leases { - ret[i] = NetworkDHCPLease{ - IPaddr: l.IPaddr, - Hostname: l.Hostname, - } - } - return ret, nil -} - -// Free the network resource. -func (n *Network) Free() { - _ = n.Net.Free() -} - -type virNetwork interface { - GetDHCPLeases() ([]libvirt.NetworkDHCPLease, error) - Free() error -} diff --git a/hack/qemu-metadata-api/virtwrapper/virtwrapper_cross.go b/hack/qemu-metadata-api/virtwrapper/virtwrapper_cross.go deleted file mode 100644 index 2faa95961..000000000 --- a/hack/qemu-metadata-api/virtwrapper/virtwrapper_cross.go +++ /dev/null @@ -1,40 +0,0 @@ -//go:build !cgo - -/* -Copyright (c) Edgeless Systems GmbH - -SPDX-License-Identifier: AGPL-3.0-only -*/ - -package virtwrapper - -import "errors" - -// Connect wraps a libvirt connection. -type Connect struct{} - -// LookupNetworkByName looks up a network by name. -// This function errors if CGO is disabled. -func (c *Connect) LookupNetworkByName(_ string) (*Network, error) { - return nil, errors.New("using virtwrapper requires building with CGO") -} - -// Network wraps a libvirt network. -type Network struct { - Net Net -} - -// GetDHCPLeases returns the underlying DHCP leases. -// This function errors if CGO is disabled. -func (n *Network) GetDHCPLeases() ([]NetworkDHCPLease, error) { - return n.Net.GetDHCPLeases() -} - -// Free the network resource. -// This function does nothing if CGO is disabled. -func (n *Network) Free() {} - -// Net is a libvirt Network. -type Net interface { - GetDHCPLeases() ([]NetworkDHCPLease, error) -} diff --git a/hack/tools/go.mod b/hack/tools/go.mod index 4c70062d1..210276e2b 100644 --- a/hack/tools/go.mod +++ b/hack/tools/go.mod @@ -1,13 +1,13 @@ module github.com/edgelesssys/constellation/v2/hack/tools -go 1.22 +go 1.23.2 require ( github.com/google/go-licenses v1.6.0 - github.com/google/keep-sorted v0.4.0 - github.com/katexochen/sh/v3 v3.8.0 - golang.org/x/tools v0.21.0 - golang.org/x/vuln v1.1.0 + github.com/google/keep-sorted v0.5.0 + github.com/katexochen/sh/v3 v3.9.0 + golang.org/x/tools v0.26.0 + golang.org/x/vuln v1.1.3 ) require ( @@ -26,7 +26,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/otiai10/copy v1.6.0 // indirect - github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/zerolog v1.31.0 // indirect github.com/sergi/go-diff v1.3.1 // indirect github.com/spf13/cobra v1.8.0 // indirect @@ -35,19 +35,19 @@ require ( github.com/stretchr/testify v1.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/term v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.19.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect gopkg.in/src-d/go-git.v4 v4.13.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.120.1 // indirect - mvdan.cc/editorconfig v0.2.1-0.20231228180347-1925077f8eb2 // indirect + mvdan.cc/editorconfig v0.3.0 // indirect ) diff --git a/hack/tools/go.sum b/hack/tools/go.sum index f3c11d9f4..f2eb97dfd 100644 --- a/hack/tools/go.sum +++ b/hack/tools/go.sum @@ -111,8 +111,6 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= @@ -122,6 +120,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -180,8 +180,8 @@ github.com/google/go-licenses v1.6.0 h1:MM+VCXf0slYkpWO0mECvdYDVCxZXIQNal5wqUIXE github.com/google/go-licenses v1.6.0/go.mod h1:Z8jgz2isEhdenOqd/00pq7I4y4k1xVVQJv415otjclo= github.com/google/go-replayers/httpreplay v1.1.1 h1:H91sIMlt1NZzN7R+/ASswyouLJfW0WLW7fhyUFvDEkY= github.com/google/go-replayers/httpreplay v1.1.1/go.mod h1:gN9GeLIs7l6NUoVaSSnv2RiqK1NiwAmD0MrKeC9IIks= -github.com/google/keep-sorted v0.4.0 h1:UNJGKBtOg4m4rgTYCpkBh0WBI2UTLm+xNC1lZvfQpp0= -github.com/google/keep-sorted v0.4.0/go.mod h1:sWIIDzox6hizdt59dsqD2yH800NXYBwRqylmBDs/QXM= +github.com/google/keep-sorted v0.5.0 h1:e6PsQA2InvsPmRc7kl20MYrN4baGtIdN1gN46cMmRAo= +github.com/google/keep-sorted v0.5.0/go.mod h1:JYy9vljs7P8b3QdPOQkywA+4u36FUHwsNITZIpJyPkE= github.com/google/licenseclassifier v0.0.0-20210722185704-3043a050f148 h1:TJsAqW6zLRMDTyGmc9TPosfn9OyVlHs8Hrn3pY6ONSY= github.com/google/licenseclassifier v0.0.0-20210722185704-3043a050f148/go.mod h1:rq9F0RSpNKlrefnf6ZYMHKUnEJBCNzf6AcCXMYBeYvE= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= @@ -235,8 +235,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/katexochen/sh/v3 v3.8.0 h1:/BNMhF21b6Q4vcB6YyGtxcGGcdT3NCTiUBNBYcI3EmI= -github.com/katexochen/sh/v3 v3.8.0/go.mod h1:yDdSo3LMdcNA6H2kjFyud/4RA5oPWc9lHZVO3qyXXEA= +github.com/katexochen/sh/v3 v3.9.0 h1:SZTvmo6PfC1aKCcXOS47DGEJMb9aiP6FAKGcz7e82cg= +github.com/katexochen/sh/v3 v3.9.0/go.mod h1:XZAr1U0VzhEu6lSPYs+UFFUuINN4hXiWoAS40r4H20c= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= @@ -268,8 +268,6 @@ github.com/otiai10/mint v1.3.2 h1:VYWnrP5fXmz1MXvjuUvcBrXSjGE6xjON+axB/UrpO3E= github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -343,8 +341,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -355,8 +353,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -384,8 +380,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -432,8 +428,8 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -470,8 +466,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -542,14 +538,16 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 h1:FemxDzfMUcK2f3YY4H+05K9CDzbSVr2+q/JKN45pey0= +golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -561,8 +559,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -621,10 +619,10 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= -golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= -golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/vuln v1.1.0 h1:ECEdI+aEtjpF90eqEcDL5Q11DWSZAw5PJQWlp0+gWqc= -golang.org/x/vuln v1.1.0/go.mod h1:HT/Ar8fE34tbxWG2s7PYjVl+iIE4Er36/940Z+K540Y= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/vuln v1.1.3 h1:NPGnvPOTgnjBc9HTaUx+nj+EaUYxl5SJOWqaDYGaFYw= +golang.org/x/vuln v1.1.3/go.mod h1:7Le6Fadm5FOqE9C926BCD0g12NWyhg7cxV4BwcPFuNY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -811,8 +809,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -845,8 +841,8 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -mvdan.cc/editorconfig v0.2.1-0.20231228180347-1925077f8eb2 h1:8nmqQGVnHUtHuT+yvuA49lQK0y5il5IOr2PtCBkDI2M= -mvdan.cc/editorconfig v0.2.1-0.20231228180347-1925077f8eb2/go.mod h1:r8RiQJRtzrPrZdcdEs5VCMqvRxAzYDUu9a4S9z7fKh8= +mvdan.cc/editorconfig v0.3.0 h1:D1D2wLYEYGpawWT5SpM5pRivgEgXjtEXwC9MWhEY0gQ= +mvdan.cc/editorconfig v0.3.0/go.mod h1:NcJHuDtNOTEJ6251indKiWuzK6+VcrMuLzGMLKBFupQ= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/image/README.md b/image/README.md index 24666a5c6..4316f6cfc 100644 --- a/image/README.md +++ b/image/README.md @@ -4,6 +4,9 @@ Ensure you have Nix installed. This is a requirement for the following steps. Consult the [developer docs](/dev-docs/workflows/build-develop-deploy.md) for more info. At the very least, `nix` should be in your PATH. +Building the image also requires `newuidmap` and `newgidmap` to be present in the PATH. On Debian and Ubuntu, these can be sourced through +the `uidmap` package. + ## Build You can build any image using Bazel. diff --git a/image/base/BUILD.bazel b/image/base/BUILD.bazel index 9028b8376..2928787f1 100644 --- a/image/base/BUILD.bazel +++ b/image/base/BUILD.bazel @@ -30,6 +30,7 @@ copy_to_directory( mkosi_image( name = "base_" + kernel_variant, srcs = [ + "mkosi.finalize", "mkosi.postinst", "mkosi.prepare", ] + glob([ diff --git a/image/base/mkosi.conf b/image/base/mkosi.conf index dad6a0e9f..5deab82c8 100644 --- a/image/base/mkosi.conf +++ b/image/base/mkosi.conf @@ -1,6 +1,7 @@ [Distribution] Distribution=fedora Release=40 +RepositoryKeyFetch=yes [Output] Format=tar diff --git a/image/base/mkosi.finalize b/image/base/mkosi.finalize new file mode 100755 index 000000000..561db202f --- /dev/null +++ b/image/base/mkosi.finalize @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euxo pipefail + +# For some reason yet unknown, SourceDateEpoch is not applied correctly to the +# users added by systemd-sysusers. This has only been observed in our mkosi +# flake so far, not in an upstream mkosi configuration. +# TODO(burgerdev): wait for a couple of Nix package upgrades and try again? + +# Strategy: unset the "last password change" date without leaving a trace in +# /etc/shadow-. +tmp=$(mktemp) +cp -a "${BUILDROOT}/etc/shadow-" "${tmp}" +mkosi-chroot chage -d "" etcd +cp -a "${tmp}" "${BUILDROOT}/etc/shadow-" diff --git a/image/base/mkosi.postinst b/image/base/mkosi.postinst index 62b680654..728e5ad17 100755 --- a/image/base/mkosi.postinst +++ b/image/base/mkosi.postinst @@ -15,3 +15,19 @@ cp "${BUILDROOT}/usr/share/constellation/packagemanifest" "${OUTPUTDIR}/" # copy rpmdb to outputs cp "${BUILDROOT}"/var/lib/rpm/{rpmdb.sqlite-wal,rpmdb.sqlite-shm,rpmdb.sqlite,.rpm.lock} "${OUTPUTDIR}/" + +# FIXME(msanft): +# Hack to satisfy Bazel's [output expectations](./BUILD.bazel). +# 2 Bazel packages can't share the same output paths, as it seems, and the +# files being copied around here aren't large, so copying them around doesn't +# hurt. +cp "${OUTPUTDIR}/packagemanifest" "${OUTPUTDIR}/lts-packagemanifest" +cp "${OUTPUTDIR}/.rpm.lock" "${OUTPUTDIR}/lts-.rpm.lock" +cp "${OUTPUTDIR}/rpmdb.sqlite" "${OUTPUTDIR}/lts-rpmdb.sqlite" +cp "${OUTPUTDIR}/rpmdb.sqlite-shm" "${OUTPUTDIR}/lts-rpmdb.sqlite-shm" +cp "${OUTPUTDIR}/rpmdb.sqlite-wal" "${OUTPUTDIR}/lts-rpmdb.sqlite-wal" +cp "${OUTPUTDIR}/packagemanifest" "${OUTPUTDIR}/mainline-packagemanifest" +cp "${OUTPUTDIR}/.rpm.lock" "${OUTPUTDIR}/mainline-.rpm.lock" +cp "${OUTPUTDIR}/rpmdb.sqlite" "${OUTPUTDIR}/mainline-rpmdb.sqlite" +cp "${OUTPUTDIR}/rpmdb.sqlite-shm" "${OUTPUTDIR}/mainline-rpmdb.sqlite-shm" +cp "${OUTPUTDIR}/rpmdb.sqlite-wal" "${OUTPUTDIR}/mainline-rpmdb.sqlite-wal" diff --git a/image/base/mkosi.skeleton/usr/etc/containers/containers.conf b/image/base/mkosi.skeleton/etc/containers/containers.conf similarity index 100% rename from image/base/mkosi.skeleton/usr/etc/containers/containers.conf rename to image/base/mkosi.skeleton/etc/containers/containers.conf diff --git a/image/base/mkosi.skeleton/usr/etc/containers/registries.conf b/image/base/mkosi.skeleton/etc/containers/registries.conf similarity index 100% rename from image/base/mkosi.skeleton/usr/etc/containers/registries.conf rename to image/base/mkosi.skeleton/etc/containers/registries.conf diff --git a/image/base/mkosi.skeleton/usr/lib/systemd/system/constellation-bootstrapper.service b/image/base/mkosi.skeleton/usr/lib/systemd/system/constellation-bootstrapper.service index 76ef974ce..cf93df780 100644 --- a/image/base/mkosi.skeleton/usr/lib/systemd/system/constellation-bootstrapper.service +++ b/image/base/mkosi.skeleton/usr/lib/systemd/system/constellation-bootstrapper.service @@ -10,7 +10,7 @@ RemainAfterExit=yes Restart=on-failure EnvironmentFile=/run/constellation.env Environment=PATH=/run/state/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin -ExecStart=/usr/bin/bootstrapper $CONSTELLATION_DEBUG_FLAGS +ExecStart=/usr/bin/bootstrapper [Install] WantedBy=multi-user.target diff --git a/image/base/mkosi.skeleton/usr/lib/systemd/system/constellation-upgrade-agent.service b/image/base/mkosi.skeleton/usr/lib/systemd/system/constellation-upgrade-agent.service index c3fefdcc5..ffa204085 100644 --- a/image/base/mkosi.skeleton/usr/lib/systemd/system/constellation-upgrade-agent.service +++ b/image/base/mkosi.skeleton/usr/lib/systemd/system/constellation-upgrade-agent.service @@ -8,7 +8,7 @@ RemainAfterExit=yes Restart=on-failure EnvironmentFile=/run/constellation.env Environment=PATH=/run/state/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin -ExecStart=/usr/bin/upgrade-agent $CONSTELLATION_DEBUG_FLAGS +ExecStart=/usr/bin/upgrade-agent [Install] WantedBy=multi-user.target diff --git a/image/base/mkosi.skeleton/usr/lib/systemd/system/export_constellation_debug.service b/image/base/mkosi.skeleton/usr/lib/systemd/system/export_constellation_debug.service index 6858dab9b..9b0fccabe 100644 --- a/image/base/mkosi.skeleton/usr/lib/systemd/system/export_constellation_debug.service +++ b/image/base/mkosi.skeleton/usr/lib/systemd/system/export_constellation_debug.service @@ -3,7 +3,7 @@ Description=Export Constellation Debug Level to Environment [Service] Type=oneshot -ExecStart=/bin/bash -c "tr ' ' '\n' < /proc/cmdline | grep -q 'constellation.debug' && echo CONSTELLATION_DEBUG_FLAGS=--debug >> /run/constellation.env" +ExecStart=/bin/bash -c "tr ' ' '\n' < /proc/cmdline | grep -q 'constel.debug' && echo CONSTELLATION_DEBUG_FLAGS=--debug >> /run/constellation.env" RemainAfterExit=yes [Install] diff --git a/image/initrd/mkosi.conf b/image/initrd/mkosi.conf index 18dc92361..bceb53c8a 100644 --- a/image/initrd/mkosi.conf +++ b/image/initrd/mkosi.conf @@ -1,6 +1,7 @@ [Distribution] Distribution=fedora Release=40 +RepositoryKeyFetch=yes [Output] Format=cpio diff --git a/image/mirror/SHA256SUMS b/image/mirror/SHA256SUMS index dd1cfed90..e8a5f795d 100644 --- a/image/mirror/SHA256SUMS +++ b/image/mirror/SHA256SUMS @@ -1,107 +1,108 @@ -a1d1bd1e3dd3f133c984039219a05703cb38b073daf8a864bd95805747633103 aardvark-dns-1.10.0-1.fc40.x86_64.rpm -7e635d208b2d3191973fbce9b2ee0a470204fa121270d9aa297ed5c3546f520b alternatives-1.26-3.fc40.x86_64.rpm -a8aac6e068011d76e89536ffcb29e516c3ccd0095ef8ada0a37a9fd21a2b39b0 audit-libs-4.0.1-1.fc40.i686.rpm -5b6386ac345c3fd388c509df4ad31ffe04f1a1ed6eb4f10d2b5f56c2a5b300dc audit-libs-4.0.1-1.fc40.x86_64.rpm -0fe4ed8770711ede2fcec43c4545b62461a24f03b3aa836d0e7071f4436e26f1 authselect-1.5.0-5.fc40.x86_64.rpm -db7d946583f2a91a3301d964a5adc7afb1620e0f72c9a9033ae3a4cfc2f332ad authselect-libs-1.5.0-5.fc40.x86_64.rpm +37abef83e8927b4b48f69fcbdcc249d349c6029cc669401676d01f0ea326999e WALinuxAgent-udev-2.10.0.8-2.fc40.noarch.rpm +eeca1e4f380330d602278b8069c03e0a712f9d7c1c9533c5869c66e5f5fce4a0 aardvark-dns-1.12.2-2.fc40.x86_64.rpm +ac860c52abbc65af5835d1bd97400c531a5635d39bc1d68e36a1fe54863385ea alternatives-1.27-1.fc40.x86_64.rpm +6d0cfcd0e97421b42af58a824c7e99a6cbcdd0e81980b4ea9e0d4051ef723db3 audit-libs-4.0.2-1.fc40.i686.rpm +f4ed40457780c13bebf84c1cf8981550da7e0e728e80250aed179eda8915bc7f audit-libs-4.0.2-1.fc40.x86_64.rpm +e9fd8dd4c9068501c169edb684de7f6e38657548e9d4d1b838a4d6316e9f17cc authselect-1.5.0-6.fc40.x86_64.rpm +db18a583ebde21d8b0b67f0306e25908b273bef9c532469ac0b7ab92578438f4 authselect-libs-1.5.0-6.fc40.x86_64.rpm 6404b1028262aeaf3e083f08959969abea1301f7f5e8610492cf900b3d13d5db basesystem-11-20.fc40.noarch.rpm 156e073308cb28a5a699d6ffafc71cbd28487628fd05471e1978e4b9a5c7a802 bash-5.2.26-3.fc40.x86_64.rpm 208ddebcd5edbff3dca54020a8a180f5410ea9b2d82c733e106992a729b4b84e bzip2-libs-1.0.8-18.fc40.i686.rpm 68a43532d10187888788625d0b6c2224ba95804280eddf2636e5ef700607e7d0 bzip2-libs-1.0.8-18.fc40.x86_64.rpm -e61d6858790314f9d9ab539c5531d2b67ce763c9e5ac6c22dd76293fec12f3f5 ca-certificates-2023.2.62_v7.0.401-6.fc40.noarch.rpm +1afcf80d5e7b22ee512ec9f24b4f2b148888ef95af3486cf48f2204c3406b12d ca-certificates-2024.2.69_v8.0.401-1.0.fc40.noarch.rpm 99d4976979c8b9d18c9d2d686de77882dc6a4e72ebfe358fb9a37a83f0ecdc90 catatonit-0.1.7-22.fc40.x86_64.rpm -ef93475ea699c80bb8e49b5a80fefeed23e553b0e492d74748a55958b4dde568 conmon-2.1.10-1.fc40.x86_64.rpm +588a2ab4dd93d58ca8b8d2c2d0b5e2c52007548c3fdd06f5ca1ab415ee236d86 composefs-1.0.6-1.fc40.x86_64.rpm +5935816e8d377d0385e5287ca12e4d3b43e3c3cdc9cc4deafa653a6dba78611a composefs-libs-1.0.6-1.fc40.x86_64.rpm +db246f6445469b5a71e965a081685471768393cf04181e7250ce0ddcb8a9c3d4 conmon-2.1.12-2.fc40.x86_64.rpm adf4b75cdd9fae9d2d37fb71d9f0bf625a6705c0f0a7784569ab21463fe22152 conntrack-tools-1.4.7-7.fc40.x86_64.rpm +fa073cc08e035fab231c2e9aa3116468e75f5056c169d5b095f3ee2956123d95 container-selinux-2.233.0-1.fc40.noarch.rpm bbe29e0c7b4ca076d50b4ac3954eb383459230d96b13f353ee71ebd5de33b6d1 containerd-1.6.23-5.fc40.x86_64.rpm -25fffa3b5f1b0b2349fd6f8f6ccb6e84936c50eeb8d4a292bcc2b74895fa7fcc containernetworking-plugins-1.4.0-4.fc40.x86_64.rpm -542e8c11b3af4c4bbbe2e8911c9f9dac12620d20be15011561cb3791165562c5 containers-common-0.58.0-2.fc40.noarch.rpm -483e8966b8f25fd5508ebe01a8b4fed75fd4c5105ba5d71284322ac3d3500b7b containers-common-extra-0.58.0-2.fc40.noarch.rpm -4af8d4cf81c8c368c2a128dcd2b1ffe228589568b162e2d482bd0e2b8d2ca0da container-selinux-2.230.0-1.fc40.noarch.rpm -d90e0c786e9406ac4f4db67a8d4bbf3d7bf724797dbf1dd422ff376eaa214b3e coreutils-single-9.4-6.fc40.x86_64.rpm +0705251ea64b1558098016b2120f202c5aba77470093cb8f89ce6adb2a0b46b6 containernetworking-plugins-1.5.1-1.fc40.x86_64.rpm +3e35525e9224d3427f10343c98036b251fac34bf67c9007335561d846736d0d5 containers-common-0.61.0-1.fc40.noarch.rpm +b0740195d12d356e5637b83ece8650fc3f764f37e734678a07cb637fb14faf7d containers-common-extra-0.61.0-1.fc40.noarch.rpm +299d3e7e1cbc110d9ae8a47f6ca95142c3e3783cb1464bfbd6bc550c414b97ec coreutils-single-9.4-9.fc40.x86_64.rpm d941a78ffb6e2e0b4c24d0097d0351ced8796edde90208b4bddee459bce0a949 cpio-2.15-1.fc40.x86_64.rpm faa23cb6a7a612c0a6e874c788c5add967c5e193bd38c2e6093b82b38a162f81 cracklib-2.9.11-5.fc40.i686.rpm ea1f43ef9a4b02a9c66726ee386f090145696fb93dff80d593ac82126f8037ec cracklib-2.9.11-5.fc40.x86_64.rpm fe24641e69545c428890a4b094f015c03f65a6c30c3db7bb0de7672bab66bfd6 cracklib-dicts-2.9.11-5.fc40.x86_64.rpm -e4407cbfeb01494457e941a56971ec3aefbd35206792918d60fc9417acacd1a8 criu-3.19-4.fc40.x86_64.rpm -6dd4fe61a462d20fd6fc07ecf8bf47198cc24733d82fe0e46ed4d5f988dffef4 criu-libs-3.19-4.fc40.x86_64.rpm -8a86435bf7382475bc7366b5dbf741e549c23b16c3430fecf9b84f3a1e6c9e88 crun-1.14.4-1.fc40.x86_64.rpm -11d4b45c1001ccd523e0e95cc4b8f84bd332d2df42d08fcfa451288bcd074142 crypto-policies-20240201-2.git9f501f3.fc40.noarch.rpm -126f9f1aa7312ff6841b44bd8f5cdec46998d8a73f978aa50144f6fb492a1658 crypto-policies-scripts-20240201-2.git9f501f3.fc40.noarch.rpm -d54dd64d6e5ec06ce51dd063cde948f71e8c0c930058e3232c963a7b7309947b cryptsetup-2.7.2-1.fc40.x86_64.rpm -ea1a32f78c86ea741d31d7166e641602e62a0797a2200725385e148b15977388 cryptsetup-libs-2.7.2-1.fc40.i686.rpm -41fdb51944e94625a8d4424c784482c426ca5ec7ca63f36b0f7231e7f8ccde13 cryptsetup-libs-2.7.2-1.fc40.x86_64.rpm -eb071367cc23b314bfc3f3d7d9611bd6d19fc17cebae4f790e4d6719545f283a curl-8.6.0-8.fc40.x86_64.rpm +f3f3e5f6a1c1bee67c0c6598a48143c36827f90a095897d649580a174468cdbc criu-4.0-1.fc40.x86_64.rpm +bbdb6014e2bd87db1bb2d4795a57cbb08bfdb03777c2b9730a3f45f7977fc4c9 criu-libs-4.0-1.fc40.x86_64.rpm +d388aa1a184a3ed04c68a39f81a9dcc39088b1f279d49d3631db608da6611937 crun-1.18.2-1.fc40.x86_64.rpm +d7a62ff0193375607d28d8fe7eedf3ff5b6ddac154e1474d79787b9f32ae298d crypto-policies-20241011-1.git5930b9a.fc40.noarch.rpm +0f1d436f879fa30f18adca576a1f91bb1a8d1ac42cff5f35c1d15e6dffc506fa crypto-policies-scripts-20241011-1.git5930b9a.fc40.noarch.rpm +26aadc06a9f98c58ca6250d811e749ee5fa76059b37445ec28b50ee73d548174 cryptsetup-2.7.5-1.fc40.x86_64.rpm +765d5162ad7b1eef16a3d3e4285743a3a358552112e7946dcd974e355dc9fa28 cryptsetup-libs-2.7.5-1.fc40.i686.rpm +6559b4d59d898317972e8d728253ba4315578c15fe23553958d6fb8033698794 cryptsetup-libs-2.7.5-1.fc40.x86_64.rpm +20b0f2923feae4c2f1d339e959d3f03d81f8ca985faa05872377b827d6f30467 curl-8.6.0-10.fc40.x86_64.rpm 0dff67dfeca59cb68cadafe8d9909b88dfaa2fc0a9a4426352f66a5fe351fbe3 cyrus-sasl-lib-2.1.28-19.fc40.x86_64.rpm 19197df26f76af5e78bd1e3ad2f777bea071eef6dfec1219f6b8ee3c80e10193 dbus-1.14.10-3.fc40.x86_64.rpm 84ca6055aa354df549fdc78d6d9df692ed4d12c14a489a6d2ce844b5f225a502 dbus-broker-36-2.fc40.x86_64.rpm 81bade4072aca4f5d22be29a916d9d0cfc9262a6c5d92ddfe750f7b8bf03f7c9 dbus-common-1.14.10-3.fc40.noarch.rpm 51bcbc8f98a8abea9a24f3f3988958b965dfe8d6b4201ee046255416fe3ce75c dbus-libs-1.14.10-3.fc40.x86_64.rpm -d4fb93847a0e94d3bdbea203c1df0895e254089d825dfaf040b1aae3ae9547ff device-mapper-1.02.197-1.fc40.x86_64.rpm -89cd53411d71097aeb5af16cf6d7fcb2c11103a5606a78e628fb1a138b0f0780 device-mapper-libs-1.02.197-1.fc40.i686.rpm -c736bdca85feb3982cc8772058e95c7794d37503d5a26a2f84d4092bd5300d18 device-mapper-libs-1.02.197-1.fc40.x86_64.rpm +6a2046c5a6c959cdf30519ec67385faf9b6156ffb3b449c54a0694d4d35985fd device-mapper-1.02.199-1.fc40.x86_64.rpm +33d2dfe3cf355511e6d7bbd1969675b9b73f58bac2a998e9d950ab99d762a299 device-mapper-libs-1.02.199-1.fc40.i686.rpm +f80de90bd6ab88c9071b200c0f0323f80145ca3ab9ac565e8f569390890137cc device-mapper-libs-1.02.199-1.fc40.x86_64.rpm 6913a547250df04ec388b96b7512977a25ab2fca62ed4345c3a9fc8782ce659f diffutils-3.10-5.fc40.x86_64.rpm -4e9636e8733ea13c399c1a37453bc087b6c515c624991d848db0621a91dcaec8 dracut-060-1.fc40.x86_64.rpm +cb0736689bd171b6c6ac7a60737fd6b9534c950958ad8e03138068bf9498e0b1 dracut-102-2.fc40.x86_64.rpm fa40cda554dc644d5a8354b18be748f21996dadd6193ee4ac32c02581266d313 duktape-2.7.0-7.fc40.x86_64.rpm ac4f1b2eaf5d452512e7b6172c93880c2b501946b71a228adc02d50bb3fb56e0 e2fsprogs-1.47.0-5.fc40.x86_64.rpm 8476fda117e3cb808129ddc2f975069685a8c7875ee04c3dafa6ceed948a2628 e2fsprogs-libs-1.47.0-5.fc40.x86_64.rpm -3e0ec4d7b4b95d10f58c5269688e03da7abb4d73169c76761f4fc7e7f7797a47 ec2-utils-1.2-47.amzn2.noarch.rpm +2e2bf662f060ddd75195e9d3d5f08cdd5d9cc857df3a9bcc45608337ba314a25 ec2-utils-1.2-48.amzn2.noarch.rpm e6231ec4268b3efa928250eb4106311e0f33396422245b938bfed4ba2d79c573 efitools-1.9.2-9.fc38.x86_64.rpm -649b961082dcba4abcf10102c73fd3f9a6877176bdb302906d24b2da212904b6 efivar-libs-39-1.fc40.x86_64.rpm -de10b1728571d2976e2f0f4cc5067d4575a5e97ec3914c57af537846ccaec753 elfutils-debuginfod-client-0.191-4.fc40.i686.rpm -877c66844c68044b2a29b5d7465eb97f429e9f38b56ebaa16d766c0979e93a80 elfutils-debuginfod-client-0.191-4.fc40.x86_64.rpm -3fbe1afd014386a436a25205d6727475a8f1107be734dd92fc40c3d5e0e5971d elfutils-default-yama-scope-0.191-4.fc40.noarch.rpm -36c4d77aa7cd45fb070273ac33ca3007ce0286c87be80072ef4f8fb4947405a2 elfutils-libelf-0.191-4.fc40.i686.rpm -c1eca14924981b987f9b17c01a97511d641f49ac6b2b0f2d8e83563343932302 elfutils-libelf-0.191-4.fc40.x86_64.rpm -393c5920c3b69834e5a75b05f48f04e696f509cb52c8055e686e63e677342547 elfutils-libs-0.191-4.fc40.i686.rpm -d7d1ed3fca0696b8c38effe21bc70c84a94cb66c0b59bb1980c0f455d23b7fec elfutils-libs-0.191-4.fc40.x86_64.rpm -7be0991d79544dadcaa16c0a23c8fea9a0839b4f65db3664b3a4209358aa5ff3 ethtool-6.7-1.fc40.x86_64.rpm -19d6e2f987c80d97b82c3d837d584eca60621b6d8cbd6797ba01a01ed8848799 expat-2.6.2-1.fc40.x86_64.rpm -601842a8c2ed5c58481e7cf14c03d128dd7b8512304d144c37aee9c8a1c3330d fedora-gpg-keys-40-1.noarch.rpm -bd62f80ae7dc50c20b0633d86f1c4a9f205f7df13c8ee1a5d5f624872c29271e fedora-release-40-39.noarch.rpm -590c9439a81fb9e35a8b4d19dc159ce09b756f8f7f66a6290d8785f424d97003 fedora-release-common-40-39.noarch.rpm -057acf25df0f6b028657790b2addca123faac0b80639ac6da13632dc7811d6f3 fedora-release-identity-basic-40-39.noarch.rpm -4eb9b6ecc46fb6c7592de7faabd9c460fa5b551a7074d5e5da49f69c5b9d0e09 fedora-repos-40-1.noarch.rpm +6ac676d78c2df896f9794a8dffb75ea69c58d202c68f4bcf084f0d264154a666 efivar-libs-39-2.fc40.x86_64.rpm +d4b391ee444de66794804962e441ccdba74e75630a2abbcc9a14b7fd2f7cb535 elfutils-debuginfod-client-0.192-6.fc40.i686.rpm +60befd76c16ce28b1f065fac31e88cdb74d5219421587fcdde2b46abace803c0 elfutils-debuginfod-client-0.192-6.fc40.x86_64.rpm +467cc1d14f1e6ca0a3b893c087ba5ecee2ec44c33b7455b6ad9cc9b2aa1f2f54 elfutils-default-yama-scope-0.192-6.fc40.noarch.rpm +5c4abd06417a9bed0a93adf00ef7a9195101069445fe7f2873408b3d4010a760 elfutils-libelf-0.192-6.fc40.i686.rpm +98d770d563c5898abd6847e728dd793f6ee985904020084c62c7568463614428 elfutils-libelf-0.192-6.fc40.x86_64.rpm +61f3912d147750749d3b4b5031d0f2ca95fa21615a36bd55ea4b4b9be0493e02 elfutils-libs-0.192-6.fc40.i686.rpm +f215ebf2e586330f93c52b228c98912a0b42db9ceeff830b611817401a84252a elfutils-libs-0.192-6.fc40.x86_64.rpm +95cf8ee199b2e1b3471f920ebad57d3d8178f5e68d37ee35a8a94727473ec8d3 ethtool-6.11-1.fc40.x86_64.rpm +3a5ba168021a01107d6dd4dc7cffe8bb5553c64f236c436979b9fddfdc4cb59d expat-2.6.3-1.fc40.x86_64.rpm +849feb04544096f9bbe16bc78c2198708fe658bdafa08575c911e538a7d31c18 fedora-gpg-keys-40-2.noarch.rpm +8f0a56982aa10b607bd3b8009e91bac1a7d9b7ba40eb4435ff9bd9efe7e5e76e fedora-release-40-40.noarch.rpm +dde6f4b5d4415ce20df40cf1cb9ff3015aa5b1896c5b5625e49aa686cdce1d1d fedora-release-common-40-40.noarch.rpm +f133aabe97d4aff7e6c83b8d364fb9805f655b32150e2f6e876958966293e467 fedora-release-identity-basic-40-40.noarch.rpm +e85d69eeea62f4f5a7c6584bc8bae3cb559c1c381838ca89f7d63b28d2368c4b fedora-repos-40-2.noarch.rpm a6f2098fc2ed16df92c9325bd7459cc41479e17306a4f9cddfd5df8a1b80d0f8 file-5.45-4.fc40.x86_64.rpm f76684ee78408660db83ab9932978a1346b280f4210cd744524b00b2e5891fe1 file-libs-5.45-4.fc40.x86_64.rpm 063af3db3808bea0d5c07dbb2d8369b275e1d05ad0850c80a8fec0413f47cd64 filesystem-3.18-8.fc40.x86_64.rpm -f17ca5526d2cf34b82916a0cd1afe73d68856fdb5b19754312f61512aef0a7c3 findutils-4.9.0-8.fc40.x86_64.rpm -2d6631d65e3b5c91afdb100a51ee8e50294f0e074a944c1662008d878d47456e fuse3-3.16.2-3.fc40.x86_64.rpm -a9c6502a5b190aaf169e93afd337c009e0b2e235e31f3da23d29c7d063ad2ff9 fuse3-libs-3.16.2-3.fc40.x86_64.rpm +21725de2a93e1ea19f8d298e32a2428a3a08b9c98f22561cc778a807ed43639f findutils-4.9.0-9.fc40.x86_64.rpm f4c2d51c7b4577f7b7ef498f8e2afb1b007da2de00cca28e220f50129c40a48c fuse-common-3.16.2-3.fc40.x86_64.rpm f94315e447afb7442033b7b82e43a4ed62754f603afda53930280300855e46c7 fuse-libs-2.9.9-21.fc40.x86_64.rpm 8fe84b7e0319afcc9c9eb28130b74e0cd7c675667a6ce075eb7ee2ec1b0014c2 fuse-overlayfs-1.13-1.fc40.x86_64.rpm +2d6631d65e3b5c91afdb100a51ee8e50294f0e074a944c1662008d878d47456e fuse3-3.16.2-3.fc40.x86_64.rpm +a9c6502a5b190aaf169e93afd337c009e0b2e235e31f3da23d29c7d063ad2ff9 fuse3-libs-3.16.2-3.fc40.x86_64.rpm 6c80dfdaf7b27ea92c1276856b8b2ae5fde1ae5c391b773805be725515fdc1ac gawk-5.3.0-3.fc40.x86_64.rpm c4cc69bf3a2655b9ee9ac23492d377bac57811c5b4f81fbf43537520ee33c7af gawk-all-langpacks-5.3.0-3.fc40.x86_64.rpm 21470eb4ec55006c9efeee84c97772462008fceda1ab332e58d2caddfdaa0d1e gdbm-1.23-6.fc40.x86_64.rpm 93450209842a296ea4b295f6d86b69aa52dd8ec45b121ede0d5125aa49bad509 gdbm-libs-1.23-6.fc40.x86_64.rpm -1af2b6d450ecc168e5604654dc83433bf0658bba5cacd55377400d7db7db650b gettext-envsubst-0.22.5-2.fc40.x86_64.rpm -834c3441835069b61208792b9b9ae1ebfadadb9d2d211357d7f42838932b59a7 gettext-libs-0.22.5-2.fc40.x86_64.rpm -1126bf8d28dff9f165865d83c239e6a2d3988fc935957b9b869d8ed7989a2ae9 gettext-runtime-0.22.5-2.fc40.x86_64.rpm -0d07452b71741856258e6ddba673a6f0a9fbf2ade0d751ea2d735531f019c398 glib2-2.80.2-1.fc40.x86_64.rpm -d271514135604e4bc7e0c7a1fefd4e7f619ea82a42df2322dc9c91ae06fc40be glibc-2.39-8.fc40.i686.rpm -041201b485a5d5b68d5324c9006d117c01c96459e6a7260ffc311bf13cbc3db3 glibc-2.39-8.fc40.x86_64.rpm -df2dc4473fa092ba3b73522e8af9219d4d9aa71e56acbcd7265a1c0cd6825935 glibc-common-2.39-8.fc40.x86_64.rpm -0b8d0bc78141e239697bd8d5c5af6dfcdb44b7ced3f0e6e7058c4ced6cc48c26 glibc-gconv-extra-2.39-8.fc40.i686.rpm -5edcb7ad87a4008ebaa073ace1817407d7c13e85f90d55b07483937a7d8222cc glibc-gconv-extra-2.39-8.fc40.x86_64.rpm -3b474d0bb881ace5622f180b04b69d13da1602f28c719335e0d3779326c42831 glibc-minimal-langpack-2.39-8.fc40.x86_64.rpm +40337d9167737abe23af9c6b586b883f33cc82028d69b29c1d68b524201d9248 gettext-envsubst-0.22.5-4.fc40.x86_64.rpm +554a68e692ccdd0cf71ea67a4c550bac910685465f17eee503732d48ccda9c90 gettext-libs-0.22.5-4.fc40.x86_64.rpm +046971e9f5f0c88737854e1c9e02cce8f5854633575984b235cf3f8b11ec7b91 gettext-runtime-0.22.5-4.fc40.x86_64.rpm +0a32c6874ce180375c2c0b1e2f0c8fed38131a598e5c4ba3866cf3aee1f3f5fc glib2-2.80.3-1.fc40.x86_64.rpm +a2d94eb4028fad9789f0d5561b4c4a7a03020013af2a79be7aea3fb0390b8caf glibc-2.39-22.fc40.i686.rpm +726a1d707dfcf20d1f4c94f76bdba38d166eb574ecc2d83ec438bdc161f3ec27 glibc-2.39-22.fc40.x86_64.rpm +0b502c1140a1f6461dbd63d3daefedded6c705769476cec5e69466aab7693ea6 glibc-common-2.39-22.fc40.x86_64.rpm +c09983bc2c7fbc23e7e622739532b554357103d99161d458c4f0c5eabce5d8c5 glibc-gconv-extra-2.39-22.fc40.i686.rpm +c185634bd4f161c35292daa028823a607c78f1e71727b6c506d640771ddd88aa glibc-gconv-extra-2.39-22.fc40.x86_64.rpm +e99290c1fa76536f0bb0024dbe14527a6d5efcf00436493f705a75c6f76d3df3 glibc-minimal-langpack-2.39-22.fc40.x86_64.rpm b054d6a9ee3477e935686b327aa47379bd1909eac4ce06c4c45dff1a201ecb49 gmp-6.2.1-8.fc40.x86_64.rpm 0a8b1b3fb625e4d1864ad6726f583e2db5db7f10d9f3564b5916ca7fed1b71cb gnupg2-2.4.4-1.fc40.x86_64.rpm 4425dbd35ab65f25b092d12ac56c4b565371a1c52ac882c8896dbeae7d52bbb1 gnupg2-smime-2.4.4-1.fc40.x86_64.rpm -4a41802154b079185f306fb9a2e9522e2dc1b866b1f947707cdb04ee876f3fd2 gnutls-3.8.5-1.fc40.x86_64.rpm -41eccf83033fa7ba4d181659eb2e3a94d8b276c6f75557ca0a3b7fd196733f29 gnutls-dane-3.8.5-1.fc40.x86_64.rpm -8f4e437e2eda2636f58952f3f5f258313c1f5ff333407c08f87cd83c8f872dfd google-compute-engine-guest-configs-udev-20240501.00-1.fc40.noarch.rpm +4289ccbb44e4a764ef6f58593a56f2598c6821feebac52be6fa04c771eebf029 gnutls-3.8.6-1.fc40.x86_64.rpm +0e5c3c13d4c34d83453667a8011eab1859d0db5ff7409fba0dce3fbd68604226 gnutls-dane-3.8.6-1.fc40.x86_64.rpm +f8510eeec17b9258de9a68ce15af21f3ea135b5e767f3bc9047f851d81dbac6e google-compute-engine-guest-configs-udev-20240830.00-1.fc40.noarch.rpm 94e443590221fb17e0330f076ebac32baab17b8d9c22566db372899ae750ca64 gpgme-1.23.2-3.fc40.x86_64.rpm 6d54af0fc5ae216eb97720415acda4245ebc6c021420a2892b58620b5b25ca38 gpm-libs-1.20.7-46.fc40.x86_64.rpm 8e2310f6cde324576e537749cf1d4fee8028edfc0c8df3070f147ee162b423ce grep-3.11-7.fc40.x86_64.rpm -50723d6fa868659466090da71ddaf59b5201a435de86b4e70d4f1e94de138f41 grub2-common-2.06-121.fc40.noarch.rpm -cbba9b3c7947fd14a88a8a2c4d5d022ecf3e280b8d2381b3902ba95112677a97 grub2-tools-2.06-121.fc40.x86_64.rpm -8cd674db8d05f6e4cc905dcaeffd353c2bb21c38d8bda4a0884697a068b631cc grub2-tools-minimal-2.06-121.fc40.x86_64.rpm +cfdba55bf65221d4cb6574e18586340f813ee948fb90f94088ab730a8cbd4400 grub2-common-2.06-123.fc40.noarch.rpm +a265c8c4acac4c2a3c5f63f98df89e689b87f6f6bcceac1c83882d9cdab90eab grub2-tools-2.06-123.fc40.x86_64.rpm +3ff26313487d9656195f2e121eb57ea6411deab71b0ec3ae57f11785ba86f330 grub2-tools-minimal-2.06-123.fc40.x86_64.rpm 6a146fa9b154e67eb67eeb258df37814a863997c87171fdc2bd771e5a46b1cc4 grubby-8.40-75.fc40.x86_64.rpm -6a502364cc7cfa1ec1918dbff2d678b4392c9f0279b66302bc8c039c36d7bde6 gvisor-tap-vsock-0.7.3-2.fc40.x86_64.rpm -7976f6318044e7adbf543edb4d3da4fbc43ef628e433a0c55b4652dc1c15a735 gvisor-tap-vsock-gvforwarder-0.7.3-2.fc40.x86_64.rpm 6dcc2f8885135fc873c8ab94a6c7df05883060c5b25287956bebb3aa15a84e71 gzip-1.13-1.fc40.x86_64.rpm -a1e1c7b374615851ddc52fefd89fc4ea1850730f6fd840b1fc655a1f62a222f2 iproute-6.7.0-1.fc40.x86_64.rpm -b15281c08e6840353cae883a90c19f6df757313ca8eb54c84f9312a88ae8c65a iproute-tc-6.7.0-1.fc40.x86_64.rpm +7ea61bdaada7c1ab5b8567e054a73e2cb3ca6019e3db887049998fed7eea8514 iproute-6.7.0-2.fc40.x86_64.rpm +21d9bc4c677edd86b2e88ebe4c20b097412c2fa3ef4a91d7de0f9b03e1306f5d iproute-tc-6.7.0-2.fc40.x86_64.rpm 21e1196534fbb6d6a4f8d29a1e76518e2740ae53f63080fc811e7ce9cc6d0982 iptables-legacy-1.8.10-7.fc40.x86_64.rpm 6e78bebc0bde8c2f1bd9c4a5f40010a779e7505a0fe87aab516db1bb4a840f02 iptables-legacy-libs-1.8.10-7.fc40.x86_64.rpm 98115e0aa89bc9a8ec66c160af80cf32519db427a83d23d8f3dd9185b3aa591e iptables-libs-1.8.10-7.fc40.x86_64.rpm @@ -118,21 +119,21 @@ c8e382e9de90e6946dd9bc2f706d6c307ea4ebba3eca91a283f1bb72b5b3ac9c kbd-2.6.4-3.fc 42994ac67877595861b55adafd75ab3ce02d397e2ccddac8fb40ec0fecb4436b kmod-libs-31-5.fc40.i686.rpm 53dd95341767a2ea40b68e4621a231883bd5b69426f0920ce1f1ca94e18765cb kmod-libs-31-5.fc40.x86_64.rpm 9a03b21936528f6d08700757cb460c48e9557a71efaaa5e93b01b3f7614320f3 kpartx-0.9.7-7.fc40.x86_64.rpm -b71c8e48abe4b3f4898e59233bf071b75ae9a58c691c7d1b988c661b700931ff krb5-libs-1.21.2-5.fc40.i686.rpm -9fa9b3dc437120759814d4b33f05d84b4317f55dc310d8075f4555f341e25ff1 krb5-libs-1.21.2-5.fc40.x86_64.rpm +821a2a47fa5ff1f9450f82118c812bc105f8afd5eb6a8e00523665c2a14a651d krb5-libs-1.21.3-2.fc40.i686.rpm +2db3a289d5a710b5f8ebbd603228d67ee59281622f086e3530efe8f2545057d6 krb5-libs-1.21.3-2.fc40.x86_64.rpm 6f2f0a522f2f10f273a77a60fdb7e066c14059d0a3676c9f723162daa7110b42 libacl-2.3.2-1.fc40.i686.rpm b753174804f57c3c6bae7afeb6145005498f18ae5d1aa0d340f9df5b8d71312f libacl-2.3.2-1.fc40.x86_64.rpm -a8492446b11c5813bde22268957d6bd74b7a5eab9d0cb77dee47bbe23bc01754 libarchive-3.7.2-3.fc40.x86_64.rpm +74d72760c1982830358d676794ee3972ab05550fe7235ae9756a40de8266091f libarchive-3.7.2-7.fc40.x86_64.rpm e131ab89604dbd4fdc4f80af632099e48bf68bb328dbf0e7dcbef1d1e134dc09 libassuan-2.5.7-1.fc40.x86_64.rpm 67facd893f5082be270d0887a43ba22492c47e652e06e5d53ecd681a1aec8ac7 libattr-2.5.2-3.fc40.i686.rpm 504cff39c51a04c1d302096899c47dc34ac0eba47524c2fc94c27904149e72cf libattr-2.5.2-3.fc40.x86_64.rpm 649cceb60f2e284f8d5dadeec4af8e7035650fe0e5aa75c552354b3fa5708cfe libb2-0.98.1-11.fc40.x86_64.rpm 46e35f0fcf3c5ac842c4fd7ba63c0106b73fa2250a9ae1f8e92c53d552201d7f libblkid-2.40-0.9.rc1.fc40.i686.rpm f4278c28f2bb21b0c24a5975384a5ccfc0934504d8a7c036ca1346b7683e1b5c libblkid-2.40-0.9.rc1.fc40.x86_64.rpm -688ef20e1e1fd0e3884c9f0070a3251636a81e08d299b13609dfb4152434b5da libblkid-2.40.1-1.fc40.i686.rpm -0870933f0565a25e0cbf5246dd754722f5df9946f4f5c09cf420e85cc1a1e4fb libblkid-2.40.1-1.fc40.x86_64.rpm -e653f622e46e8fd6a5d7fd1ba3d4691a7a7f57ae54879da4577c0788b7da2c4f libbpf-1.2.0-3.fc40.i686.rpm -6aaea5de69154d81ef39d3faa72d42d04ae57fc5071492d6ccb9899ca43948fc libbpf-1.2.0-3.fc40.x86_64.rpm +c0f6262d325a8a0609935abcb922033c6e56d6b6e5096ba8fbb9c972817e27d9 libblkid-2.40.2-1.fc40.i686.rpm +b506de64d63262d9d957a75fdf2282d82b1e4978cebbdfc191ef93bba37e3b7c libblkid-2.40.2-1.fc40.x86_64.rpm +d8fab37e62c441e5d35421086a20923ff15561ad28c858cfb670b7c095106dee libbpf-1.2.3-1.fc40.i686.rpm +fca2d942f6264b630b33991e48dcb605543a4c837371f28f92994bf956677f24 libbpf-1.2.3-1.fc40.x86_64.rpm 97e9e5339bb0ca6ce3d0195c8ebe48384bcfc087ee6bc7a35b1d27d4de23fbfa libbrotli-1.1.0-3.fc40.x86_64.rpm 8163fa05deeb06414a6e9ad78ba8d3e65eab9af87f35f0790f8c81bee8359ab6 libbsd-0.12.2-3.fc40.x86_64.rpm 0bdb66863b60abc8c2ca540e80ef58e9d4da3f700b685ecc49042616387dee8d libcap-2.69-8.fc40.i686.rpm @@ -142,34 +143,35 @@ dc22477c3ac762f92ecc322af4f39fee2c5371bedc495ce242f9b94c590c580f libcap-ng-0.8. 274fd72d27570f3fcc9f06efedd21ea7a71e0903c286222fdbbefd6b30b9a80c libcbor-0.11.0-1.fc40.x86_64.rpm c890a19d2c4a3da836bae1db40b778fe0339cd0d26bddfbe584aaccb1a0f1485 libcom_err-1.47.0-5.fc40.i686.rpm 0d100701976c37fe94e904ed78437db7477ae1dc600ece07bea23fbbd968762c libcom_err-1.47.0-5.fc40.x86_64.rpm -7cacae48a3f76e77ffae047db34146efd3ae45b51188431a161ea93f83b9a231 libcurl-minimal-8.6.0-8.fc40.i686.rpm -df01bb4a19148d5ef8bad7e97d6b9ff0926bdd6c04f97620b27dc3d2ff9059cb libcurl-minimal-8.6.0-8.fc40.x86_64.rpm -783f1bc7ab5fb88b5bfaea82f70457fba8e76bde5821b61bafbb1acb301f9834 libeconf-0.6.2-1.fc40.i686.rpm -05ad4ddff82db6a9c6cec0fc0188ae3a946c1387fbf69773eef9b9cd21c36251 libeconf-0.6.2-1.fc40.x86_64.rpm -2c4a70a136b81fd13407660b999546f88568b477e86404793ba15c4325f2ab3c libedit-3.1-50.20230828cvs.fc40.x86_64.rpm +7583f6b188f19e5112403ad53d0e5c98d35a5b736d355ea91d4a35ade5ef014c libcurl-minimal-8.6.0-10.fc40.i686.rpm +e3dc770fc4c48bec2da9ac948bcd43e053608d0397ad0a57056409a7d427289d libcurl-minimal-8.6.0-10.fc40.x86_64.rpm +700d56839e1bc16c08f71c505a7e62f655e4c18f4bf71bf2f36f3854f829e6f5 libeconf-0.6.2-2.fc40.i686.rpm +2ef764049e121ee2a9fa5d0296e6e2dd0abc7541040b8e49d67960bd9bde74e4 libeconf-0.6.2-2.fc40.x86_64.rpm +b003de79beac86385d212fce137417439e8ec7cb863115d560e02834c84efd1e libedit-3.1-53.20240808cvs.fc40.x86_64.rpm c4adcee5dd9e22ea50d6c318ac4936a8df708121741958ce5aa8f038c46c61a9 libevent-2.1.12-12.fc40.x86_64.rpm a1ba3045c99ef1b266383f0801731a68f9e0cb069a6c808267ad33b759381907 libfdisk-2.40-0.9.rc1.fc40.i686.rpm 17f02ca51b90580887d739f52b995034e0929fc6bcd92be308554a2f5337bbe4 libfdisk-2.40-0.9.rc1.fc40.x86_64.rpm -c8b9967345ed0393c17101b970bb86258380494d99edf07787bc32ee4de96a7b libfdisk-2.40.1-1.fc40.i686.rpm -2481691bd2ee6aab48b1a0306357337007b2b0af082e4fdef47dcc5a8a8357be libfdisk-2.40.1-1.fc40.x86_64.rpm +34db4e48052a47e1c6f445dec3edbdb279890ae24c5ecfa44e8a19fdee0a99a2 libfdisk-2.40.2-1.fc40.i686.rpm +aa6a51bbe265bb3d3a50c37557f6513d51298301e4957ce4484e56feb837fa32 libfdisk-2.40.2-1.fc40.x86_64.rpm 25caa7ee56f6013369c2fac26afd3035a7d580af0b919621ba8d495d13a5af86 libffi-3.4.4-7.fc40.x86_64.rpm f9c5369b6d168a2b8e46159bc41ef0755ee1a8d12f4c6766fdfe23e827cf5cdf libfido2-1.14.0-4.fc40.x86_64.rpm -1fa9fec23745248ce8a2684a01daa3bed2cf181f09fb3b316a69be2c99093008 libgcc-14.1.1-1.fc40.i686.rpm -d42d466e052b7926a4f9bc7d6620f1d3f8e2c4610665d224a032264a09b2dd19 libgcc-14.1.1-1.fc40.x86_64.rpm +460a36745833f629ac1f5d232ec0daec092b7cb654a4bf3e4fde7c693fea9fbb libgcc-14.2.1-3.fc40.i686.rpm +cd073c42cb4dfcd224e9b4619883f2c7923ab0b083d7c90b01e3052c89f6b814 libgcc-14.2.1-3.fc40.x86_64.rpm 10c4c12c6539ffea68974cd9b57013d471ac35fe3bef4833c0a22f6b29fbf489 libgcrypt-1.10.3-3.fc40.x86_64.rpm -4d1d4538f152eaff22aa957ebdc724148f31519d75e6a56699ab2698c0699f59 libgomp-14.1.1-1.fc40.x86_64.rpm +03d5f4d139dec2e7c94714b1b9f59d37236dbda9f09271bdda99c71251f15f0e libgomp-14.2.1-3.fc40.x86_64.rpm 8d0a9840e06e72ccf756fa5a79c49f572dc827b0c75ea5a1f923235150d27ae2 libgpg-error-1.49-1.fc40.x86_64.rpm 677a67726c759c94faa94475185e46d028f171c9215390ac601ccd914188afb2 libidn2-2.3.7-1.fc40.i686.rpm 2fd2038b4a94eeede34e46ed0e035e619f77d0e412c70cf4e9bb836957e8f31b libidn2-2.3.7-1.fc40.x86_64.rpm -e6dd9a7c8c5e03f30363a1bd3abe97a33fed294c695a9d1029587635bdb9b04e libkcapi-1.4.0-10.fc40.x86_64.rpm -8692d0bfe4c5ed1fa4594dae4d020815217ed1999676cedbef58e6c9549d681d libkcapi-hmaccalc-1.4.0-10.fc40.x86_64.rpm +98b0d9d25bd93c7061ce50480e214944a02d7de725e1d31f4461604380ffb74a libkcapi-1.5.0-4.fc40.x86_64.rpm +84977f5f157172dc7642a3f6602692bb6323b4b106c69f7081882e6c6a81a346 libkcapi-hasher-1.5.0-4.fc40.x86_64.rpm +906bb224af7b2e1ea64c258c6978a610b899b0af5be572ce1c09e36ec58b8a79 libkcapi-hmaccalc-1.5.0-4.fc40.x86_64.rpm a77eed0fe1b84c11f9175f4642db058753d4eaa1f88e999f01df72e1d10a3826 libksba-1.6.6-1.fc40.x86_64.rpm d5d9c95e38aeb8c852cda4516057d86a5fec2485cb3413067d625059a4d97b30 libmd-1.1.0-4.fc40.x86_64.rpm 7b307e95fb7584889d35108de86ebfa34d0aea6eabb5a68d574647f83f25ed77 libmnl-1.0.5-5.fc40.x86_64.rpm 4aa44fc80c1d3e3496a406740b9ae3ada3df28b37fecc611e44183f542758f76 libmount-2.40-0.9.rc1.fc40.i686.rpm c5231753426984926daba70cc61d20e777048e91167f2e3c217e21e9205573a6 libmount-2.40-0.9.rc1.fc40.x86_64.rpm -f5946a9bd8432cba1475e4fafedc2ab3493c1c9e02a062a605c9d4add001ebbb libmount-2.40.1-1.fc40.i686.rpm -2589c1e241991dbefd89188aabd9b1f99c277bfee30c300a185633df3caa7913 libmount-2.40.1-1.fc40.x86_64.rpm +76ae4cbab05343ba545c2c3898153493f0663a2f6ff382df464cebe9d260bab4 libmount-2.40.2-1.fc40.i686.rpm +a695daa293bb78b033a2629f5af1284fe212b748227e94efa59a8292eb6b9f40 libmount-2.40.2-1.fc40.x86_64.rpm 157c1256a9529dea2215f6c77f40647baf19c6f8ac6058934c0f2a593f436c4d libnet-1.3-3.fc40.x86_64.rpm a2d50812dec895ba654fc424a458e99ceb81423046ad870ffabfef3081382ef6 libnetfilter_conntrack-1.0.9-5.fc40.x86_64.rpm 3de45cea1d877e58f1a8fadb3902e585c070bfd2813bb107145a2f28a2e6edb3 libnetfilter_cthelper-1.0.0-27.fc40.x86_64.rpm @@ -179,47 +181,48 @@ ad8d041ab07f62567f80e9a751529091f591a542dd91b6473b7cba5749b56d69 libnetfilter_q db4841a294c5ec3759d77f356a05d0c7f852270aa75c900daac4992f12147dd3 libnftnl-1.2.6-5.fc40.x86_64.rpm 0e9b7c72112f58e83d66422eb2d77d346dc0810cdb652906f0d0fcbd9799fc7d libnghttp2-1.59.0-3.fc40.i686.rpm 550160732fc268914a422cfddc3c745febf8da161f8eacbce8649c67117b1476 libnghttp2-1.59.0-3.fc40.x86_64.rpm -7bfd9a41bedcf082dcc40ba2a980115ccdb1a843b9d28912a3bd8d99771f6015 libnl3-3.9.0-3.fc40.x86_64.rpm +d7062104274c9b8eae85b7c199a69c2f8692c17f31d3fdf4364b53f6a3553e9c libnl3-3.11.0-1.fc40.x86_64.rpm fa6dccd7aee4a74a5cfa12c7927c7326485704ebe57c54774b0f157fda639360 libnsl2-2.0.1-1.fc40.x86_64.rpm 9e27ce1072ef67dd8877175f9a7daa1bcddbbcec3fd6f161e6bc2f2b453c360b libnvme-1.8-1.fc40.x86_64.rpm bb9ceaba0d3283777777524e8c99b8eaa2155e9000d8e3ef5d0ece336f8c1392 libpsl-0.21.5-3.fc40.x86_64.rpm 87e8725c378e16a983abee0b8bfbdaf2214f32b55c822741e627db34427ed9a3 libpwquality-1.4.5-9.fc40.i686.rpm 210e797a265da7111c1a59eca95f9e301ad05c5c8772aed54af9363e5684950b libpwquality-1.4.5-9.fc40.x86_64.rpm -c34657225d5c9c57dc9261e765cb85704397eec6ec4fa01a6ee6ae2b2fcf87dc libseccomp-2.5.3-8.fc40.i686.rpm -40e88dedc3fc64e70f0c2c16af598d9701c089cd205d5bf312517984bf0194fa libseccomp-2.5.3-8.fc40.x86_64.rpm +571fad7baa286ca36a2b2cdb171d22142ba82b99663ec0408b5db99514773956 libseccomp-2.5.5-1.fc40.i686.rpm +91668f5d08a663948c7d888d7cdef3248285c5d9fbe369ae031d7ca31c6e398c libseccomp-2.5.5-1.fc40.x86_64.rpm 280edce0c5cda3a725edaca0db10a16d1c4b24b849a8ddfeac066ddb84057e6e libsecret-0.21.4-2.fc40.x86_64.rpm -97f18f8852a7b60a2990f6cb25f39de0593599eb6ba0e455436bc783f34b931e libselinux-3.6-4.fc40.i686.rpm -b67135643467acef3417d6f961ef3dc987ca726681a25026fce29cbd15fa76f9 libselinux-3.6-4.fc40.x86_64.rpm -33dd223a3ca3ef3e7128c84016f7cc95829802fc6a0d4f0c0329632fc6a2a2fc libselinux-utils-3.6-4.fc40.x86_64.rpm -1313cb0d72005c8b469466a7ee12a7c30b7e283ed5ed0f601d2c911fa84d5137 libsemanage-3.6-3.fc40.x86_64.rpm -d5e6fc8b4595cccae415bc18b971ea4a4ed64c816e45de5d3f588b78ecf12708 libsepol-3.6-3.fc40.i686.rpm -2a84c1dcbf391374eb7f66f75a5ce62eadf11241f33d4df950a7bd94a9e0853e libsepol-3.6-3.fc40.x86_64.rpm +69161fabb22dd4c5c8aeab0b6465dafe06117ce5173aaf4dce425a10cb11c434 libselinux-3.7-5.fc40.i686.rpm +2070bdf786c926400739254f08568ccf564ce613ddacacb36b6a9a499345aa5e libselinux-3.7-5.fc40.x86_64.rpm +aca271d814ee3be14c09963985011c201315a186d3e3b634af8d59cd5eb01208 libselinux-utils-3.7-5.fc40.x86_64.rpm +e200b862d5063f6e85859c5be99c50d5636edae91bd3f603c3a22383b7e2ac88 libsemanage-3.7-2.fc40.x86_64.rpm +a4cd1c54d0f8b543ffa7cc6ce366a6a3f233e084f2e52ea07a70da6127347b8e libsepol-3.7-2.fc40.i686.rpm +85cbaeca877a166cda9637a8ea0d43dd63488fdcc250fe564696cf8beaf8913f libsepol-3.7-2.fc40.x86_64.rpm 716b91d85eb887fe10db607608294475289b9e9fc4d51fbddcf24046ea016147 libsmartcols-2.40-0.9.rc1.fc40.i686.rpm 34111597814e385c8c1cdd48ff72c4ed64e7e6ed9bd6660bb2bfda6aebdb3200 libsmartcols-2.40-0.9.rc1.fc40.x86_64.rpm -302124d98a491472ec0982b89afbf576922d6921a89dda479d354e6582566f0e libsmartcols-2.40.1-1.fc40.x86_64.rpm -91d67f2a3be65b2904c432f4585189540978dcfb6ef994c2eaac5b7cfb4010a5 libsodium-1.0.19-4.fc40.x86_64.rpm +e9c3e9e3458af7a2f9b5cd6bc45020bb7f2c6cfbd0429b0b1853928bd3e02004 libsmartcols-2.40.2-1.fc40.x86_64.rpm +45d032fb4d59ee0f6a921dd1f0addfcdd38fc46917243fdd6248194ffddb9067 libsodium-1.0.20-1.fc40.x86_64.rpm c8bbfa2762cc601f8a97d8d5a39a658f0e91ba477ebebd798b30f7fc8ffdd457 libss-1.47.0-5.fc40.x86_64.rpm -b37a2a57ff60a21e0ac539f994e6b87b849684cb721c795bf6ddfe6cdc161c00 libstdc++-14.1.1-1.fc40.x86_64.rpm +89e7282e0a94d641871dfed423ba2ce6f8b088eaf9aabdea1805708bcafa6a01 libstdc++-14.2.1-3.fc40.x86_64.rpm d92173d6fbfb7e2af3b35a8554229e247666e15dc5b36cba43b7bbfc4144b781 libtasn1-4.19.0-6.fc40.x86_64.rpm -adc082c8d4af5cc81a9de428c39de59717177109aedb4b15888a8ca9d51167ab libtirpc-1.3.4-1.rc3.fc40.x86_64.rpm +9ca680998686ee852fa8e1667cd6e7c436bfd5fe7da898bd314d808303d447f8 libtextstyle-0.22.5-4.fc40.x86_64.rpm +a660c40fc2af9578a7cf283bd18df6ae00d68f25b7d102f4e4f49a3805f6c575 libtirpc-1.3.6-1.fc40.x86_64.rpm e5d150d23f95e4a23288b84145af442607a88bf457c0e04b325b1d1e8e708c2b libtool-ltdl-2.4.7-10.fc40.x86_64.rpm e541a1c8397dccf159b3602eb6bbb381ba21c544db337a3b3bfc49ccc2ef5c21 libunistring-1.1-7.fc40.i686.rpm 58719c2f205b23598e31b72144ab55215947ad8fca96af46a641288692c159d2 libunistring-1.1-7.fc40.x86_64.rpm -813c8cb7828e15c0de655b215d456b8049ed7e8454f4e56026762359b4870a62 libusb1-1.0.27-2.fc40.x86_64.rpm +bc60959e98e5f690bc3df03bfa8afee2d0cf28e794c4e3c52f19769885771321 libusb1-1.0.27-4.fc40.x86_64.rpm 896d671852ed3f28e8c778dca361c5b5c57a89855df11755e6be1d088f64d43a libutempter-1.2.1-13.fc40.i686.rpm 0093a8d3f490fbbbc71b01e0c8f9b083040dbf7513be31a91a0769d846198c1b libutempter-1.2.1-13.fc40.x86_64.rpm 5aaa12bba361ae29b2a6b35c4b21da935423bc2ad763eaa8267008c7a533cb3c libuuid-2.40-0.9.rc1.fc40.i686.rpm 18ae5558dd719fcc92bd4d2c7c73c6a093af82a35c67444ccc9cdf4b3dce1824 libuuid-2.40-0.9.rc1.fc40.x86_64.rpm -66f09c3f1128b27e4bef6b095f6d4de6cc85e5c83b22aa867b522069e10f82eb libuuid-2.40.1-1.fc40.i686.rpm -833153a38690923cfdfb9645061ea48249bacb33449c819dd340a0a8424cac98 libuuid-2.40.1-1.fc40.x86_64.rpm +7273be2566ee7c865ca3154715e2f7fa938e852bc6114af9cb8530fa88d833ca libuuid-2.40.2-1.fc40.i686.rpm +b6db3e72ae6575127216145c1f65414ea94acd9db26d08c5081cb5d786101c1f libuuid-2.40.2-1.fc40.x86_64.rpm bea578631618692ba5e302beadfdf6d5894e23e5bddaea4b4fca2f377dd1aaac libverto-0.3.2-8.fc40.i686.rpm fadf7dd93c5eee57ba78e0628bf041dbd2ea037ace52f0a5cbac55b363234d27 libverto-0.3.2-8.fc40.x86_64.rpm -2e2ab8784cce3e877f87977f651a046faa2121d716d06daa510981f7d946dba2 libxcrypt-4.4.36-5.fc40.i686.rpm -26c27a101cf40f84f313d81a28cbca9450e8d901e6fcd315ac6036895a369b92 libxcrypt-4.4.36-5.fc40.x86_64.rpm +a0036606133ba74df47cba7f5349a024bcb6367150a5450ac414508c67d852a9 libxcrypt-4.4.36-10.fc40.i686.rpm +0d93dd9ea48dcfe8f9ecdfc3ec8ac736635334e23fc1cf8ba04e562e0637de17 libxcrypt-4.4.36-10.fc40.x86_64.rpm a17f9a8894a00ee97a42219b3b21d64bfb850d74059d89ae299210bc477e8967 libxkbcommon-1.6.0-2.fc40.i686.rpm 1f1d0c1e1132016735acc6fc3390102b35f9eb257244547c7b61c32a9c2314cc libxkbcommon-1.6.0-2.fc40.x86_64.rpm -a8b9940585cfd8f3a6e18e9ab63b0cc0f401bedba1e12d46b4c62c4a469e52d7 libxml2-2.12.6-1.fc40.i686.rpm -a4c3648577f35a59c7b1e4437bfa493d737156cbcba798c7cfa1d8f081969c83 libxml2-2.12.6-1.fc40.x86_64.rpm +302104acbc7b094958be4f764c14f738462fdb381fc38aac63e0e7eaedaa82a7 libxml2-2.12.8-1.fc40.i686.rpm +ed8d18570524445954dae5aff6239d9cc987cf8b3313fcd48c42f1b79b8eb247 libxml2-2.12.8-1.fc40.x86_64.rpm cd866911efd52e3a70655df3da9d71ad2f4a326463aeaa381493a7547e14871d libzstd-1.5.6-1.fc40.i686.rpm bed3075b9ff919eded25cb45e9e03b8a7c63bcc8e893ec28c999aecaa68c51d3 libzstd-1.5.6-1.fc40.x86_64.rpm 81409455da42a5ffdcf5b8cc711632ce037fec25d5ae00cbfda5010c9db04157 lua-libs-5.4.6-5.fc40.x86_64.rpm @@ -229,41 +232,41 @@ f5f022440c4340b5e7fb1c1dbc382e6b0fd57030b3ff056940f2bb3d254408ec lz4-libs-1.9.4 2030e8622b6f9ceb4b56f5c771ae7e4ccbff3d8bf563df5bf929725f4c4f18c9 mkpasswd-5.5.20-3.fc40.x86_64.rpm 03fbefea8c8d8465cf1caf66870fb935292ee18b4ca341853b5576ca9c7801eb mokutil-0.7.1-1.fc40.x86_64.rpm 0a3a3fc2471d2d64cbc85f4b23c93620df6eeee814851a2b69fc5ddf75406b56 mpdecimal-2.5.1-9.fc40.x86_64.rpm -ef6285ceb3baff0bef0e541094c04a899dda37c5961b053b58be2a4a9085302f mpfr-4.2.1-3.fc40.x86_64.rpm -ed211fa5d0d0a70e4db0099a01e7b7a46f28b064e2af7064d3c7836663229917 mtools-4.0.43-4.fc40.x86_64.rpm +bc873693a8b8423d7f82e329abe207c9160a4c746fea9a32ef2a6ae8c912f227 mpfr-4.2.1-4.fc40.x86_64.rpm +a02bb93695bf3bf945441fc1d72d864ec537d0440d7f41ad06d24a002801d6b6 mtools-4.0.45-1.fc40.x86_64.rpm 7dfae7d898dfc40f3fe1fc66104cf31e434e866fec4d4944b55952d7f2f16657 nano-7.2-7.fc40.x86_64.rpm b404c27af03bb1e43fb0dc472d5a1fa152e0563fa2e4eefa29199c47578a829b nano-default-editor-7.2-7.fc40.noarch.rpm 8a93376ce7423bd1a649a13f4b5105f270b4603f5cf3b3e230bdbda7f25dd788 ncurses-base-6.4-12.20240127.fc40.noarch.rpm 39bba59320e6276a3b7b07bc94d319511bdd7d32ba098fd49723f4d542794d41 ncurses-libs-6.4-12.20240127.fc40.i686.rpm a18edf32e89aefd453998d5d0ec3aa1ea193dac43f80b99db195abd7e8cf1a04 ncurses-libs-6.4-12.20240127.fc40.x86_64.rpm -07253a2a49c6554632408bc006af14847eb5d89551e7221678de5f24a228ce8a netavark-1.10.3-3.fc40.x86_64.rpm +f1e77a65e098b105ce6a47e386de84937217ed72a0c47f2568ae11da0ea7d75d netavark-1.12.2-1.fc40.x86_64.rpm 16172412cfd45453292e18f84fc57e42a3ce92aca72b47ef7e15b44554049cfe nettle-3.9.1-6.fc40.x86_64.rpm 188ce5004e6ed764b4a619b64a4a0f36f1cc4fa919fe0a300599ff1171844144 nftables-1.0.9-3.fc40.x86_64.rpm 784e0fbc9ccb7087c10f4c41edbed13904f94244ff658f308614abe48cdf0d42 npth-1.7-1.fc40.x86_64.rpm f814bc09b50daaab468715088ec056373dbc209a5075306e4ce76f5c55eb2b42 nvme-cli-2.8-1.fc40.x86_64.rpm b09089231ec94ee1b2dc26e34d8d7f19586d411bc40df7d0e495e559ac2d871a openldap-2.6.7-1.fc40.x86_64.rpm -2fa5030d1c80979dd5fd0c304e4151282e0eb2749186926c4d8283c4ca14340f openssl-libs-3.2.1-2.fc40.i686.rpm -eba1bd09317cc1f1f80e722e9a545dd404e1fad444045438f254e99cab4f1ed6 openssl-libs-3.2.1-2.fc40.x86_64.rpm +5df04d37e492e5f107cc21e547240f9f98b0b7613320467bc0b08f6aa1b0fb88 openssl-libs-3.2.2-3.fc40.i686.rpm +e9fca52d76eb6277b9fec3238226faafc0938806318fad1143a527fdd28a16cf openssl-libs-3.2.2-3.fc40.x86_64.rpm 9f0336deb6f1b1524ec48d837622e7e2291995369b0356d7ad1e1d427f3b659a os-prober-1.81-6.fc40.x86_64.rpm -2c8e47f98df74fe89b23f0a1347aba91383da06e0ae903949b015943da4e1b5b p11-kit-0.25.3-4.fc40.x86_64.rpm -93159ba4fffd7c91bd28d3942564368c402dc65ee7998e81688f3d566fe7633f p11-kit-trust-0.25.3-4.fc40.x86_64.rpm -9997fbbe5aca567c2d8afc5d745034bca0a4d8bda62ea7f88122e0dff2dfcdf8 pam-1.6.0-2.fc40.x86_64.rpm -ac7b46f2807ec0faa6dff991c89875b7ebd7edefef5b0ad75934196405303c7a pam-libs-1.6.0-2.fc40.i686.rpm -8b233033e715d594326fe5ad84c06361928a787299c734206de7deccff7b3c10 pam-libs-1.6.0-2.fc40.x86_64.rpm +70fba929aab38a9d69a457cef1b01962161a1df2b78dc5a4e86ff4b994b51079 p11-kit-0.25.5-1.fc40.x86_64.rpm +c728dbd90872b7597a8ace70a70555bff576231bb6dbde14b75626d601706af8 p11-kit-trust-0.25.5-1.fc40.x86_64.rpm +374bd91b0fb10dd09d543a1aab6328d3801bd9a0bdfbfbf0b594ce79ab3423ce pam-1.6.1-4.fc40.x86_64.rpm +b6251990de342b9f4de8ab7360de435751c0b3e524ea6e1ad78a294d7d541483 pam-libs-1.6.1-4.fc40.i686.rpm +227f1d93b7125b5a71def58146ddaa0853bd489da6707f0564482e290e77930c pam-libs-1.6.1-4.fc40.x86_64.rpm 9bbce784622e02af0371ced8e9a7d26adba7eabd66ecfcb8bbe2d24cf616e3c1 parted-3.6-4.fc40.x86_64.rpm -88ed733f4474cd561c7ccda6031190367156aec2317a675dbb9f799c80016dcc passt-0^20240426.gd03c4e2-1.fc40.x86_64.rpm -771176f50aebf7916d4e0ee2ea6caa82bdd570ec7085292661ea8f5724b45cfc passt-selinux-0^20240426.gd03c4e2-1.fc40.noarch.rpm -757dc11e76123116a505879b5b00dbb1f132b25578f738979220397965d7fa38 pcre2-10.42-2.fc40.2.i686.rpm -8d36bcee4d3e39d5b8162ab8de347bb0f7d7b260a6b6c76bc4b577c5bff6ba5e pcre2-10.42-2.fc40.2.x86_64.rpm -f2042a010126c04faea45cea4b62f8443e73f4a0a218858092e0fcf5ca7967fa pcre2-syntax-10.42-2.fc40.2.noarch.rpm +02c01edaee6fe2af5174562387d530b73ee40e39dbe108ab4553de82228f6621 passt-0^20241030.gee7d0b6-1.fc40.x86_64.rpm +7909af3b8d248c344693b4f7893172d465fde6d1fb8d719f1179f8c971cb786b passt-selinux-0^20241030.gee7d0b6-1.fc40.noarch.rpm +a0fb808d6b7ff8cd9cfdc1a60f213851cecdcace334d6e5aa1e0e54b81d79a25 pcre2-10.44-1.fc40.i686.rpm +73e50df09266fcffda9c24a3738f579dd365c2c187c294da054ef9915edc3851 pcre2-10.44-1.fc40.x86_64.rpm +dbec699e88d42fc6fb1df0a8c0b9023941ed1b1b7625694253a612eaf9f2691d pcre2-syntax-10.44-1.fc40.noarch.rpm d207e7cdb8602403c8aab36c1342f55bcb4503bf4e296d11dae013e6fd9ac920 pcsc-lite-2.0.3-1.fc40.x86_64.rpm cbd3f6cdbb19126dc703f140fafcac84d0d2ef63b54dfa08332d4bce2def076f pcsc-lite-ccid-1.5.5-3.fc40.x86_64.rpm f796a31cad58f4ebea8787020868581d9a721297ee0ef6a7c63a7f8444f60c17 pcsc-lite-libs-2.0.3-1.fc40.x86_64.rpm 5443db8875acc0c1c436dbe1ed62b776543e049b8d9c7e33198379d367814093 pigz-2.8-4.fc40.x86_64.rpm cb7c5036f1d25c696de23a6670cb64caec9945116fb0c9a93555414746ecf253 pinentry-1.3.0-2.fc40.x86_64.rpm bbb4abafa9f7664e21350b56d49af2c928288e6d4dd68c304c4ab5d45b2c8ad7 pkcs11-provider-0.3-2.fc40.x86_64.rpm -8f71536999a1ac6ebc148050382cc9716d68577cc49afeebd64ac0d5742183a0 podman-5.0.2-1.fc40.x86_64.rpm -fc0270713aefd482937adc4d6905f806760ea54c70379cb675be521251e5a177 policycoreutils-3.6-3.fc40.x86_64.rpm +ad5ac0506bf19875bd3e1860c1bea3ec1034605d6ff3374794f7343370c2d03a podman-5.3.0-1.fc40.x86_64.rpm +8a0ee0be826338862ecd65d04032b43122cda333ba6bb6891b2ae6aed5208832 policycoreutils-3.7-3.fc40.x86_64.rpm 30a4f9d3631aaa1280c93ce4305847a9773973aa312e1802d1cd676cb2421689 polkit-124-2.fc40.x86_64.rpm f47bc65177a8b160916c00df9c84442afa1dd353880b3c0503d5a0b052d4956c polkit-libs-124-2.fc40.x86_64.rpm b7decdd8a6fcb175fea2bb39bb1dbecad1ba820c365bab5a273a7b3982e55157 polkit-pkla-compat-0.1-28.fc40.x86_64.rpm @@ -272,30 +275,30 @@ c03ba1c46e0e2dda36e654941f307aaa0d6574ee5143d6fec6e9af2bdf3252a2 popt-1.19-6.fc af85755cda79959a19161ebc26a45e507003298bd97b472b9ab0d512afa5e46a protobuf-c-1.5.0-3.fc40.x86_64.rpm 45ff2e9814aa059f323b23710c73309d41d36306667a3004f5fbb86b0cab4484 psmisc-23.6-6.fc40.x86_64.rpm cca50802d4f75306bc37126feb92db79fed44dcdabf76c1556853334995b9d3b publicsuffix-list-dafsa-20240107-3.fc40.noarch.rpm -a8111a574e98417b87d6a5613da029eed14c12a545d10d5ffaf95024ffeae4bd python3-3.12.3-2.fc40.x86_64.rpm -9a6d3854bf22c47f9b14981dbcc606ccd5ddda631b2feaae460239881306e2db python3-libs-3.12.3-2.fc40.x86_64.rpm -1cfc81c8761cd0381cc5020a3686afec8350aadea01998518e8aa2407419fe9f python-pip-wheel-23.3.2-1.fc40.noarch.rpm -ce44e24ec0c7c292fdec76b055a5e32320a51545e3bc3147c27ba9c418b6afc6 python-unversioned-command-3.12.3-2.fc40.noarch.rpm -74f89e3304571c9d4eb8df444fa895aa71910dcb1909738c1f69781280da87e7 qemu-user-static-8.2.2-1.fc40.x86_64.rpm -a40c17e5681b201891c6dfaed0f6fc0dba1cdb9eb208d9ff47f9be52de76d177 qemu-user-static-aarch64-8.2.2-1.fc40.x86_64.rpm -fcf593362df5c9193264bf3bd74a6b25d73c1ef24cb7384b6f0bf4e36284365b qemu-user-static-alpha-8.2.2-1.fc40.x86_64.rpm -a241f91547dd638bfb15a1ac1c97baaaabb9b5bd64e40cd1ea444758233f119b qemu-user-static-arm-8.2.2-1.fc40.x86_64.rpm -f236b50236e4003b71eb293b769588d779fc68719f1562dd05a788b9f996a856 qemu-user-static-cris-8.2.2-1.fc40.x86_64.rpm -b8250ea3b6ab5511ffb68f01aab0253de627c6e65f1bc8f61a1322d04390c1c1 qemu-user-static-hexagon-8.2.2-1.fc40.x86_64.rpm -91f9eb36f2d9556058f320573b785775603c7c2bc31886ddfef1fd30b39f8893 qemu-user-static-hppa-8.2.2-1.fc40.x86_64.rpm -689376c3a0f33907c88b619414bd8ea6cd5c09a1ad8f45f208c1a7b6f0f536b5 qemu-user-static-loongarch64-8.2.2-1.fc40.x86_64.rpm -939ef3d38ee0c6a616879a5be56a42956cda3bc4a0e278343e06978ad1fd7feb qemu-user-static-m68k-8.2.2-1.fc40.x86_64.rpm -e3f3af44aa7ea424025872a34267354f9f28e463ef4fce4e96855724935f49ac qemu-user-static-microblaze-8.2.2-1.fc40.x86_64.rpm -2975de005d77b208c8acb01ec2b628f8ae72fa1ffca00ec4aa43ff75f29a1bca qemu-user-static-mips-8.2.2-1.fc40.x86_64.rpm -d095a53430ac1cedb2ea88a322ce8d01514d9deb4c5c187632954f48fe3ae518 qemu-user-static-nios2-8.2.2-1.fc40.x86_64.rpm -fb1eb4db02470dd2ef9f7ae0a25a9418b281d2fd9d19094b5c5b7b70731efcd6 qemu-user-static-or1k-8.2.2-1.fc40.x86_64.rpm -c81aa2cb89a3b5e939021c232c70176798480788a867773ba42a30805249483d qemu-user-static-ppc-8.2.2-1.fc40.x86_64.rpm -cb3cea7ef4e920cf4d1917c5e9f19bcc487357405e697e8a31eb2c21ae7cd961 qemu-user-static-riscv-8.2.2-1.fc40.x86_64.rpm -17782c2c4cc9c647c40ae3208635ef7c6c31f1eab07e359597816e7517f24425 qemu-user-static-s390x-8.2.2-1.fc40.x86_64.rpm -4d87a91ff166cd2a3af5420be4e668c716e4adb0dc1859e207455d5f03217257 qemu-user-static-sh4-8.2.2-1.fc40.x86_64.rpm -d3f2ab7e3d249654b1f7dca507f81de64ea004c079f7c34858e12916c2f99db8 qemu-user-static-sparc-8.2.2-1.fc40.x86_64.rpm -0111d6f799d20f1dca09b2a06f5c9510e8951bd5e56e3075c5802f17ed41a445 qemu-user-static-x86-8.2.2-1.fc40.x86_64.rpm -fd2dec7911de16e5a076eb5b8be246ec2845481dbca49a16b52293eb42d3d1bd qemu-user-static-xtensa-8.2.2-1.fc40.x86_64.rpm +7c703b431508f44c5184b5c1df052ed0f49b7439d68aa3597a9a57a5b26bd648 python-pip-wheel-23.3.2-2.fc40.noarch.rpm +bcac955e69958e064669ed6e0a394bd9dd2c76e63f558a205ced18a9755012ab python-unversioned-command-3.12.7-1.fc40.noarch.rpm +6d8342314daafde5c5ec4ec2935e74edb9bea107dc8cd72642e322444f264c7d python3-3.12.7-1.fc40.x86_64.rpm +839d6dd1d8ac9b55f14b504eca5ac5e66b8330341608f7c9132cb29816116ecb python3-libs-3.12.7-1.fc40.x86_64.rpm +4197fb5b5c5072b22b246160d176f4d45d32499b12efca8d20acee113b43565f qemu-user-static-8.2.7-1.fc40.x86_64.rpm +5cde16ada3d387c8fe8cf2badf697f35fc6284697da080bdd41ae588d4cbfb59 qemu-user-static-aarch64-8.2.7-1.fc40.x86_64.rpm +3d7d124c154265410069909741ba3de98d80d54bab749ddb2eed64a5f7efa50d qemu-user-static-alpha-8.2.7-1.fc40.x86_64.rpm +cccb61e5417bd18f398156a1987827d615114796081c7d11cc62db5e0b2eac83 qemu-user-static-arm-8.2.7-1.fc40.x86_64.rpm +5b4f9648b3bb97b83a1eeca49ccf1bdbd86899b7081f7e2a75d1a043ef414162 qemu-user-static-cris-8.2.7-1.fc40.x86_64.rpm +8d9fed13c84c5e7bce85b0ab187a35a32b37560036eea0981d1a84e98c6e0ace qemu-user-static-hexagon-8.2.7-1.fc40.x86_64.rpm +e3d0f954419049e8da75cacdb0957d50dc4c4d15231618571e740ba75bc94a42 qemu-user-static-hppa-8.2.7-1.fc40.x86_64.rpm +862e4ab69693bfcf9bf4df224eaa4ff86b545f2fc66640a51fb1ddac088eda88 qemu-user-static-loongarch64-8.2.7-1.fc40.x86_64.rpm +4bc124edbc3bf481d336d2d5be048bbbdf15001700eea72b3e239d3909e3d121 qemu-user-static-m68k-8.2.7-1.fc40.x86_64.rpm +8a614a710ae025431c6caac4ccbe70011580ff30a4f672f733dede537e9a393a qemu-user-static-microblaze-8.2.7-1.fc40.x86_64.rpm +5d722e655b8d7f7655be4189fb1859db3ce3900c4ef84a305373584a1698891c qemu-user-static-mips-8.2.7-1.fc40.x86_64.rpm +e41ce93809e5cf63c06fd7ccc44e0d3afaba555f71ddfc0cfa929ce35b587856 qemu-user-static-nios2-8.2.7-1.fc40.x86_64.rpm +27fcfa89b7aa1035d96e85698319bc7b4048c244dfe90304fa0a32e405f6964a qemu-user-static-or1k-8.2.7-1.fc40.x86_64.rpm +85212911fef356d2ffbc7eed3948f88572fade0271ea1a3f0434709b8a734926 qemu-user-static-ppc-8.2.7-1.fc40.x86_64.rpm +cd7842fa018c33d0aac9940315321d4847b1e052345fd11cb7175a538a47aad2 qemu-user-static-riscv-8.2.7-1.fc40.x86_64.rpm +b8164876c487d70df7d162a5487867af8a80445481621160b06e69101bec9e9e qemu-user-static-s390x-8.2.7-1.fc40.x86_64.rpm +2d316e5781d257f09f96fb95cebda52db6ad38db0e12958a50354958586db068 qemu-user-static-sh4-8.2.7-1.fc40.x86_64.rpm +1dc60bde4b84d9e26671dfcc6c789fd87fdea29059da2d5fa13fb1704d964ad1 qemu-user-static-sparc-8.2.7-1.fc40.x86_64.rpm +5d4edeb727f6644d81eede2ff55835198f76dd31c7cc53284dc34451184ddd71 qemu-user-static-x86-8.2.7-1.fc40.x86_64.rpm +63704659a3bab9bf58b548f98ea635ae900698e7ce1a5b50a198d134c4eed1be qemu-user-static-xtensa-8.2.7-1.fc40.x86_64.rpm 8d50fba416f81e4091b144748fff22665ee88699fdc4a372b905d999d05fd3e8 qrencode-libs-4.1.1-7.fc40.i686.rpm 93781052576cc40a2c203bbc1bf865189a11b2c82436e614da9811baedc082fc qrencode-libs-4.1.1-7.fc40.x86_64.rpm 3527582fddcb54892228658b3929ffbb89766941a9794e726216e0800ac05721 readline-8.2-8.fc40.i686.rpm @@ -304,53 +307,52 @@ dacd59edbe4744fd9f6823d672e01eff89f871e88537554f16c0a275a17d04e9 readline-8.2-8 c48c149f4aebfe44d649eea6f7a8eaa229dc8db71ff70b66c7403aa9bd072820 rpm-libs-4.19.1.1-1.fc40.x86_64.rpm 7bebda41ea91faf8cf8911a403c051eb59d444e60f8091d14d10987b713f39ff rpm-plugin-audit-4.19.1.1-1.fc40.x86_64.rpm d400a4e4440bea56566fb1e9582d86d1ac2e07745d37fa6e71f43a8fea05217c rpm-plugin-selinux-4.19.1.1-1.fc40.x86_64.rpm -9aa5ca949c570a6519e50d6c75a951bb04fa5704129003a7ee2ea915c319cd31 rpm-sequoia-1.6.0-2.fc40.x86_64.rpm -63af9d11e956f54577a54460afda4377d78fdb9e265b1eae3f0f7a6f94f70146 runc-1.1.12-3.fc40.x86_64.rpm -3b940ff1f16fdb3ddcc19d7d76241c9b81d81099ff5147c4c9967d2c4ca6fb5b sbsigntools-0.9.5-3.fc40.x86_64.rpm +9015e31297a54b708071d347b7877d885a2a97c3b18a89fa31f1481b6406eb06 rpm-sequoia-1.7.0-1.fc40.x86_64.rpm +bcea58cd71bc4a7a2ff993b7d9140b9c05125d726f611f5fc257e1f23440ec99 runc-1.2.1-1.fc40.x86_64.rpm +5dbd069183076ed8048c839c31f713c0f6080fb9ebfdda92ac550030688e811b sbsigntools-0.9.5-6.fc40.x86_64.rpm 6a21b2c132a54fd6d9acb846d0a96289ab739b745cdc4c2b31bdbf6b2434a1a7 sed-4.9-1.fc40.x86_64.rpm -b4835a7eb3bf2e2a9dd4e9546ba182997698f3e889a3d0ea1eadf541ad2607eb selinux-policy-40.18-2.fc40.noarch.rpm -cbf1da8c46e36e6990fec9da331c10dc6e8df83b732b3621e30aa5106c4ca934 selinux-policy-targeted-40.18-2.fc40.noarch.rpm +b4e188db51c7ec2d5f0cba79783eb2df7c14a92c2c6e55a9eb490d28d17d123d selinux-policy-40.29-2.fc40.noarch.rpm +05fb13cf2c4d20425e8aa8d2035a8e10e33ca1a28db2ce209db44d755d380eaf selinux-policy-targeted-40.29-2.fc40.noarch.rpm 89862f646cd64e81497f01a8b69ab30ac8968c47afef92a2c333608fdb90ccc1 setup-2.14.5-2.fc40.noarch.rpm -14c4208826d1c859899f35978a80e0448fabead39f860fd3bae41b4e3e8e1883 shadow-utils-4.15.1-2.fc40.x86_64.rpm -0a1e1e3502b65b8620cbcc74dfc75203fb9ce913f0580f49ed8fdcb8e89c106c shadow-utils-subid-4.15.1-2.fc40.x86_64.rpm +cfde0d25ecac7e689ee083b330b78df51d346c2b7557c83a189d5df95c4e2c8d shadow-utils-4.15.1-4.fc40.x86_64.rpm +6e9b6b6196f1782419e447ac806c762d002c6930fe39b18999d9b32c24a0ecfc shadow-utils-subid-4.15.1-4.fc40.x86_64.rpm 67eede27af5b4773eb2f7ac794df694be030310d40bce462864c05b8f65c87c3 socat-1.8.0.0-2.fc40.x86_64.rpm a1e23ae521e93ab19d3df77889a6a418c3432025e4880cfd893e40f7165876a7 sqlite-libs-3.45.1-2.fc40.x86_64.rpm -bb0115e08518e9e439b62eda713dc8b94daaf0f2e5f840ee2162586ea44c88da systemd-255.6-1.fc40.i686.rpm -f602c28dfcd5b0148d88f8c86a32479afc9daefd08f5e5ce8b10f55aac976f09 systemd-255.6-1.fc40.x86_64.rpm -f866e3bb336c0ea9180acfffa3222460c27ee884f54c7f731c0c5b7eef568de5 systemd-boot-unsigned-255.6-1.fc40.x86_64.rpm -48e5fc1e7d55c84d2a0418cb2f6b57b16e841700dd858ff51c0ea997665f154a systemd-libs-255.6-1.fc40.i686.rpm -55cd520eb24dee8890482d9d8c7f3a434965656d38ad9dc60711ea5184ffbf3c systemd-libs-255.6-1.fc40.x86_64.rpm -2e750b7f4e584ddd38daec07f771dd6a312ec51438b4d2d370e2d4b5714f8860 systemd-networkd-255.6-1.fc40.x86_64.rpm -e8bfc9f3fcd7a8e7013f4a2129fc1fa4a4f1bf0ee13ae9d9bc7804a1af864d0d systemd-pam-255.6-1.fc40.i686.rpm -27544b4c3606444491447225347d8419579f13cb1024aab321c76a7dc11f025e systemd-pam-255.6-1.fc40.x86_64.rpm -bac4dc6245600d6fa65e4e63b5340c7ec42268aa9c6fbbf8b4d7d742e86aec9a systemd-resolved-255.6-1.fc40.x86_64.rpm -f53b587ff73b3372f35470fd55aa9c97d2e163068f11b957a7f6e83dbfaa735d systemd-udev-255.6-1.fc40.x86_64.rpm +cf80eb17778b4be0c8d31d2ed6478aaf1135da4e283c034573b4e79c3c5c350f systemd-255.14-1.fc40.i686.rpm +bb602e98503df8b961e7ae391805eed444baf44162b8408f6b86b9447e936e3c systemd-255.14-1.fc40.x86_64.rpm +5e5055ac6c18707f58c07dc25033dfc16a3bc0dfb50820165d169a93a6d89e15 systemd-boot-unsigned-255.14-1.fc40.x86_64.rpm +c5e5f2e6789aeb6945e56a31c010e62242dda7a0e8394ac8b4c20c8e5cbdba9f systemd-libs-255.14-1.fc40.i686.rpm +38aca012b5b875240bda5b67e60d698cdd826c4afa0e2fc584452d2c2b68a951 systemd-libs-255.14-1.fc40.x86_64.rpm +191f7622473d6899998c024c7630ff55daa3a04b0b12a0ce82204d8279095fce systemd-networkd-255.14-1.fc40.x86_64.rpm +c651dfc9bc27fc10814bb8d6f06f08df67641fe9a979e10635f968f3e7c07b5d systemd-pam-255.14-1.fc40.i686.rpm +225af60cab0699bac889f02b26e4be38b080266e79f7c9ac89ce4dc93a8545d2 systemd-pam-255.14-1.fc40.x86_64.rpm +59c9c90d52653cab601677b6e867bc73804a5121bd22dc5b8a0c350f23a097e5 systemd-resolved-255.14-1.fc40.x86_64.rpm +62f74c06c1a2fb04dcfa6722b5b91e4eeb31f12da5e529eedaeae881a77c8ce2 systemd-udev-255.14-1.fc40.x86_64.rpm 65819c502727dc293a71a74b9a5f6b0ba781f12a99c5d5535085f168e5eac56e tar-1.35-3.fc40.x86_64.rpm 0478e12152cc3432a31dfca5ddbc80966800af437c6d7c0b26be307d5e1272e7 tpm2-tools-5.7-1.fc40.x86_64.rpm -f8f7d1b48e3a2193a9929544503c72d79c5de555816a3812f30158d136a2bf15 tpm2-tss-4.1.0-1.fc40.x86_64.rpm -7da3dc1d28b8154f36e6c2e68ea7e5378729d9adfa48d9817bdacf8f309a43e2 tpm2-tss-fapi-4.1.0-1.fc40.x86_64.rpm +c3be8a6d0ea23b1d0bf466b19857b97f7ffde811ad7adec0599161059d84cc74 tpm2-tss-4.1.3-1.fc40.x86_64.rpm +5df98756883badf7743cdd75f5689b62606bff0b74494b20241cb9d78335c251 tpm2-tss-fapi-4.1.3-1.fc40.x86_64.rpm 0bd358e7dfb2bd730b62c7375c8d8f8d9e2470f085ca8dc4ec626dc0332d5687 tzdata-2024a-5.fc40.noarch.rpm -f54615a1c38064a32e408765e5914d5dc2cbaec14cdf1b95fcf6800c3139b1f4 unbound-anchor-1.19.3-1.fc40.x86_64.rpm -73a122907049f35648c590727f6d719aa1b4e3cb4987404f27ec9e4a1510be83 unbound-libs-1.19.3-1.fc40.x86_64.rpm +9fc3b3f602c81bdb5e1daa4a7f9a254d35481bd1186ac0b01fbb0c3243440ca8 unbound-anchor-1.21.1-3.fc40.x86_64.rpm +1432f6a67a9400d10b09b5eee96c6fbf89b8bef99cc7e1abc6d885cf69a61fb2 unbound-libs-1.21.1-3.fc40.x86_64.rpm 36ffa617a0dfe523424a28290241a81cd51f7d82e776e58131f16d092d49797b util-linux-2.40-0.9.rc1.fc40.i686.rpm -41b777c50f1ec74795551c7d930a3d6eceab278ff03608893a5dbd49f2de5363 util-linux-2.40.1-1.fc40.x86_64.rpm +945aa536bc30050abc1870cef167cb944cf78d6628923476db43201a0054574b util-linux-2.40.2-1.fc40.x86_64.rpm 7ec1b5df780c5a30f8e901179480125a6ea87f1f7bad3b69da7f4b351b88c3dd util-linux-core-2.40-0.9.rc1.fc40.x86_64.rpm -a00108f45cd60afffb9c1b5db8bef9c6fd5b3c233a546dde787efa5b4485e5b6 util-linux-core-2.40.1-1.fc40.x86_64.rpm -22875117bc7b5d47f1edec6daa06e1c8d167b692c31954a28dcf5426eae12369 vim-common-9.1.393-1.fc40.x86_64.rpm -3face3fce765d64b1112213f80ac36dcf6f1521d5b1cbdb6b3e50822ce9a8e24 vim-data-9.1.393-1.fc40.noarch.rpm -1e9362eca139cee383318efa5818450768c5d44d063621d5600704aa05929149 vim-enhanced-9.1.393-1.fc40.x86_64.rpm -3c57e0840dfd7073e5ac0a2d5ae240960bc593689ab027face333a3e76284c60 vim-filesystem-9.1.393-1.fc40.noarch.rpm -30b11481b28e47cb568507ddaa4a9a2b67648f845859efb58e99e36801fd10d1 WALinuxAgent-udev-2.10.0.8-1.fc40.noarch.rpm -21ecc005f54161fb5c88241f344bd0f00a19747911ea158872f00ca2ab91f238 wget2-2.1.0-8.fc40.x86_64.rpm -d36fb4c83416b16df53c00501addd134a208c8596dd09aad9c4a4497ddedde83 wget2-libs-2.1.0-8.fc40.x86_64.rpm -0b198f659f4ba8b00e8841c2fe6a75ff30dec1b194f8065046cafb11b85f93f7 wget2-wget-2.1.0-8.fc40.x86_64.rpm +b1aa4e816c01c08c18924865640f214f717cdfc66837e53a24b8edfb80a86f9d util-linux-core-2.40.2-1.fc40.x86_64.rpm +50879411e244c6531e09376ef87c9f081d1988a88e462404a24835d515211a9a vim-common-9.1.866-1.fc40.x86_64.rpm +3f39232a1cd7fffbdfbb1cd0b64f5107f33c83f3ed335180655f30763c292988 vim-data-9.1.866-1.fc40.noarch.rpm +c99d7857daa246ccd36db2ddedd6a723097d9e3d090464d6fcd3476f572ffee7 vim-enhanced-9.1.866-1.fc40.x86_64.rpm +ec8ea126510e9ba2950bd1f72d78dee97dbbc440d15bf1e5542a9029443d53d6 vim-filesystem-9.1.866-1.fc40.noarch.rpm +c5682a1b02bb02578e9997ae221a7f6c6db711084129824e207fe1febdc55b9d wget2-2.1.0-11.fc40.x86_64.rpm +38aaee4829df7e1a4719991c4fc6d65a1265b6a556b182ecac3145c287c320f4 wget2-libs-2.1.0-11.fc40.x86_64.rpm +a12b44ee7cc5a0e916bcf72e80c4d618abb7406254578e947f3ba9dd0d445d25 wget2-wget-2.1.0-11.fc40.x86_64.rpm cf0306ceed1c6b3be39060d85f16b1953b464d3a625488b170d3b7aadf600645 which-2.21-41.fc40.x86_64.rpm 4ede95a2fa3bc0ae617c8bf3a375b800163d58733b4829b15d9f038505d79fee whois-nls-5.5.20-3.fc40.noarch.rpm e2195010e857f56b19246f8b821f9391922880b7691b3728a413f540edc890a6 xkeyboard-config-2.41-1.fc40.noarch.rpm -7a455af0f845962e84ee327a32a26a369ba15f328400ad24c49d68e351ece175 xxd-9.1.393-1.fc40.x86_64.rpm +627c89d516a12ab0686eabecfab5f8e952f431a1aedc445aa43a2721c3740f8b xxd-9.1.866-1.fc40.x86_64.rpm ee599a1c4d7ee635e54ec137af4dded83f433b9c8a5976f75ecdcd000b5246e3 xz-5.4.6-3.fc40.x86_64.rpm b92ef78d8ab424c22130e457d0ef691d8197bff61c3b8852205d1b02baba3819 xz-libs-5.4.6-3.fc40.i686.rpm b6ee44b3d7e494b0364f26b7d0b169a8092180af787423cd5e8a47dc0f738a66 xz-libs-5.4.6-3.fc40.x86_64.rpm 9e263e0a9b656178519de20733f3e0950fef494aa056daaa2004b522ba50b952 yajl-2.1.0-23.fc40.x86_64.rpm -b51702fa6253036579b2b7fcc2f5146f589c4ee1ef759cf80c6c1730f2023ed7 zlib-ng-compat-2.1.6-2.fc40.i686.rpm -02ed309305b380ed7ac270798e820e963dff51ba51200da30e6188193598178c zlib-ng-compat-2.1.6-2.fc40.x86_64.rpm +ffab1c8720480b498f65d0d480825ccd890e4f797c3850712879eb04a4739690 zlib-ng-compat-2.1.7-2.fc40.i686.rpm +e50b69054de16d757f5667e3acf2e7439302c91a9c418243467f288dfb79f6ea zlib-ng-compat-2.1.7-2.fc40.x86_64.rpm diff --git a/image/sysroot-tree/usr/lib/systemd/system/getty@tty1.service.d/autologin.conf b/image/sysroot-tree/usr/lib/systemd/system/getty@tty1.service.d/autologin.conf new file mode 100644 index 000000000..ec52d1369 --- /dev/null +++ b/image/sysroot-tree/usr/lib/systemd/system/getty@tty1.service.d/autologin.conf @@ -0,0 +1,11 @@ +[Unit] +Description=autologin +ConditionPathExists=/proc/cmdline +ConditionKernelCommandLine=|constel.console +ConditionKernelCommandLine=|constel.debug + +[Service] +ExecStart= +ExecStart=-/sbin/agetty -o '-p -f -- \\u' --noclear --autologin root %I $TERM +[Install] +WantedBy=multi-user.target diff --git a/image/sysroot-tree/usr/lib/systemd/system/serial-getty@ttyS0.service.d/autologin.conf b/image/sysroot-tree/usr/lib/systemd/system/serial-getty@ttyS0.service.d/autologin.conf new file mode 100644 index 000000000..24fe28a99 --- /dev/null +++ b/image/sysroot-tree/usr/lib/systemd/system/serial-getty@ttyS0.service.d/autologin.conf @@ -0,0 +1,12 @@ +[Unit] +Description=autologin +ConditionPathExists=/proc/cmdline +ConditionKernelCommandLine=|constel.console +ConditionKernelCommandLine=|constel.debug + +[Service] +ExecStart= +ExecStart=-/sbin/agetty -o '-p -f -- \\u' --keep-baud --autologin root 115200,57600,38400,9600 - $TERM + +[Install] +WantedBy=multi-user.target diff --git a/image/system/BUILD.bazel b/image/system/BUILD.bazel index 3765667b8..3a51c92a4 100644 --- a/image/system/BUILD.bazel +++ b/image/system/BUILD.bazel @@ -1,6 +1,6 @@ load("//bazel/mkosi:mkosi_image.bzl", "mkosi_image") load("//bazel/osimage:upload_os_images.bzl", "upload_os_images") -load(":variants.bzl", "CSPS", "STREAMS", "VARIANTS", "autologin", "base_image", "constellation_packages", "images_for_csp", "images_for_csp_and_stream", "images_for_stream", "kernel_command_line", "kernel_command_line_dict") +load(":variants.bzl", "CSPS", "STREAMS", "VARIANTS", "base_image", "constellation_packages", "images_for_csp", "images_for_csp_and_stream", "images_for_stream", "kernel_command_line", "kernel_command_line_dict") [ mkosi_image( @@ -10,11 +10,6 @@ load(":variants.bzl", "CSPS", "STREAMS", "VARIANTS", "autologin", "base_image", ] + glob([ "mkosi.repart/**", ]), - autologin = autologin( - variant["csp"], - variant["attestation_variant"], - stream, - ), base_trees = [ base_image( variant["csp"], diff --git a/image/system/mkosi.conf b/image/system/mkosi.conf index fc956f06e..d97bbc1bb 100644 --- a/image/system/mkosi.conf +++ b/image/system/mkosi.conf @@ -1,6 +1,7 @@ [Distribution] Distribution=fedora Release=40 +RepositoryKeyFetch=yes [Output] Format=disk diff --git a/image/system/variants.bzl b/image/system/variants.bzl index 3cca05c95..b9b1c6bd8 100644 --- a/image/system/variants.bzl +++ b/image/system/variants.bzl @@ -50,33 +50,29 @@ CSPS = [ "qemu", ] -base_cmdline = "selinux=1 enforcing=0 audit=0" +base_cmdline = "selinux=1 enforcing=0 audit=0 console=tty1 console=ttyS0" csp_settings = { "aws": { "kernel_command_line_dict": { "console": "ttyS0", "constel.csp": "aws", - "idle": "poll", - "mitigations": "auto", + "mitigations": "auto,nosmt", }, }, "azure": { "kernel_command_line_dict": { - "console": "ttyS0", "constel.csp": "azure", "mitigations": "auto,nosmt", }, }, "gcp": { "kernel_command_line_dict": { - "console": "ttyS0", "constel.csp": "gcp", "mitigations": "auto,nosmt", }, }, "openstack": { - "kernel_command_line": "console=tty0 console=ttyS0 console=ttyS1", "kernel_command_line_dict": { "constel.csp": "openstack", "kvm_amd.sev": "1", @@ -86,9 +82,8 @@ csp_settings = { }, }, "qemu": { - "autologin": True, + "kernel_command_line": "constel.console", # All qemu images have console enabled independent of stream "kernel_command_line_dict": { - "console": "ttyS0", "constel.csp": "qemu", "mitigations": "auto,nosmt", }, @@ -136,11 +131,10 @@ attestation_variant_settings = { stream_settings = { "console": { - "autologin": True, + "kernel_command_line": "constel.console", }, "debug": { - "autologin": True, - "kernel_command_line": "constellation.debug", + "kernel_command_line": "constel.debug", }, "nightly": {}, "stable": {}, @@ -181,26 +175,6 @@ def constellation_packages(stream): "//bootstrapper/cmd/bootstrapper:bootstrapper-package", ] + base_packages -def autologin(csp, attestation_variant, stream): - """Generates a boolean indicating whether autologin should be enabled for the given csp, attestation_variant and stream. - - Args: - csp: The cloud service provider to use. - attestation_variant: The attestation variant to use. - stream: The stream to use. - - Returns: - A boolean indicating whether autologin should be enabled. - """ - out = None - for settings in from_settings(csp, attestation_variant, stream): - if not "autologin" in settings: - continue - if out != None and out != settings["autologin"]: - fail("Inconsistent autologin settings") - out = settings["autologin"] - return out - def kernel_command_line(csp, attestation_variant, stream): cmdline = base_cmdline for settings in from_settings(csp, attestation_variant, stream, default = {}): diff --git a/internal/api/attestationconfigapi/BUILD.bazel b/internal/api/attestationconfigapi/BUILD.bazel index 5db942eb3..80397adb3 100644 --- a/internal/api/attestationconfigapi/BUILD.bazel +++ b/internal/api/attestationconfigapi/BUILD.bazel @@ -5,32 +5,24 @@ go_library( name = "attestationconfigapi", srcs = [ "attestationconfigapi.go", - "client.go", "fetcher.go", - "reporter.go", - "snp.go", + "version.go", ], importpath = "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi", visibility = ["//:__subpackages__"], deps = [ - "//internal/api/client", "//internal/api/fetcher", "//internal/attestation/variant", "//internal/constants", "//internal/sigstore", - "//internal/staticupload", - "@com_github_aws_aws_sdk_go//aws", - "@com_github_aws_aws_sdk_go_v2_service_s3//:s3", ], ) go_test( name = "attestationconfigapi_test", srcs = [ - "client_test.go", "fetcher_test.go", - "reporter_test.go", - "snp_test.go", + "version_test.go", ], embed = [":attestationconfigapi"], deps = [ diff --git a/internal/api/attestationconfigapi/cli/BUILD.bazel b/internal/api/attestationconfigapi/cli/BUILD.bazel index 1d2fe3ae6..df2856aeb 100644 --- a/internal/api/attestationconfigapi/cli/BUILD.bazel +++ b/internal/api/attestationconfigapi/cli/BUILD.bazel @@ -10,6 +10,7 @@ go_binary( go_library( name = "cli_lib", srcs = [ + "compare.go", "delete.go", "main.go", "upload.go", @@ -19,8 +20,9 @@ go_library( visibility = ["//visibility:private"], deps = [ "//internal/api/attestationconfigapi", + "//internal/api/attestationconfigapi/cli/client", + "//internal/api/fetcher", "//internal/attestation/variant", - "//internal/cloud/cloudprovider", "//internal/constants", "//internal/file", "//internal/logger", @@ -29,6 +31,7 @@ go_library( "@com_github_aws_aws_sdk_go_v2//aws", "@com_github_aws_aws_sdk_go_v2_service_s3//:s3", "@com_github_aws_aws_sdk_go_v2_service_s3//types", + "@com_github_google_go_tdx_guest//proto/tdx", "@com_github_spf13_afero//:afero", "@com_github_spf13_cobra//:cobra", ], diff --git a/internal/api/attestationconfigapi/cli/client/BUILD.bazel b/internal/api/attestationconfigapi/cli/client/BUILD.bazel new file mode 100644 index 000000000..c90cb34b9 --- /dev/null +++ b/internal/api/attestationconfigapi/cli/client/BUILD.bazel @@ -0,0 +1,34 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("//bazel/go:go_test.bzl", "go_test") + +go_library( + name = "client", + srcs = [ + "client.go", + "reporter.go", + ], + importpath = "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi/cli/client", + visibility = ["//:__subpackages__"], + deps = [ + "//internal/api/attestationconfigapi", + "//internal/api/client", + "//internal/attestation/variant", + "//internal/sigstore", + "//internal/staticupload", + "@com_github_aws_aws_sdk_go//aws", + "@com_github_aws_aws_sdk_go_v2_service_s3//:s3", + ], +) + +go_test( + name = "client_test", + srcs = [ + "client_test.go", + "reporter_test.go", + ], + embed = [":client"], + deps = [ + "//internal/api/attestationconfigapi", + "@com_github_stretchr_testify//assert", + ], +) diff --git a/internal/api/attestationconfigapi/cli/client/client.go b/internal/api/attestationconfigapi/cli/client/client.go new file mode 100644 index 000000000..53c79285e --- /dev/null +++ b/internal/api/attestationconfigapi/cli/client/client.go @@ -0,0 +1,178 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +/* +package client contains code to manage CVM versions in Constellation's CDN API. +It is used to upload and delete "latest" versions for AMD SEV-SNP and Intel TDX. +*/ +package client + +import ( + "context" + "errors" + "fmt" + "log/slog" + "path" + "strings" + + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/aws/aws-sdk-go/aws" + "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" + apiclient "github.com/edgelesssys/constellation/v2/internal/api/client" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" + "github.com/edgelesssys/constellation/v2/internal/sigstore" + + "github.com/edgelesssys/constellation/v2/internal/staticupload" +) + +// VersionFormat is the format of the version name in the S3 bucket. +const VersionFormat = "2006-01-02-15-04" + +// Client manages (modifies) the version information for the attestation variants. +type Client struct { + s3Client *apiclient.Client + s3ClientClose func(ctx context.Context) error + bucketID string + signer sigstore.Signer + cacheWindowSize int + + log *slog.Logger +} + +// New returns a new Client. +func New(ctx context.Context, cfg staticupload.Config, cosignPwd, privateKey []byte, dryRun bool, versionWindowSize int, log *slog.Logger) (*Client, apiclient.CloseFunc, error) { + s3Client, clientClose, err := apiclient.NewClient(ctx, cfg.Region, cfg.Bucket, cfg.DistributionID, dryRun, log) + if err != nil { + return nil, nil, fmt.Errorf("failed to create s3 storage: %w", err) + } + + repo := &Client{ + s3Client: s3Client, + s3ClientClose: clientClose, + signer: sigstore.NewSigner(cosignPwd, privateKey), + bucketID: cfg.Bucket, + cacheWindowSize: versionWindowSize, + log: log, + } + return repo, clientClose, nil +} + +// DeleteVersion deletes the given version (without .json suffix) from the API. +func (c Client) DeleteVersion(ctx context.Context, attestation variant.Variant, versionStr string) error { + versions, err := c.List(ctx, attestation) + if err != nil { + return fmt.Errorf("fetch version list: %w", err) + } + + ops, err := c.deleteVersion(versions, versionStr) + if err != nil { + return err + } + return executeAllCmds(ctx, c.s3Client, ops) +} + +// List returns the list of versions for the given attestation variant. +func (c Client) List(ctx context.Context, attestation variant.Variant) (attestationconfigapi.List, error) { + versions, err := apiclient.Fetch(ctx, c.s3Client, attestationconfigapi.List{Variant: attestation}) + if err != nil { + var notFoundErr *apiclient.NotFoundError + if errors.As(err, ¬FoundErr) { + return attestationconfigapi.List{Variant: attestation}, nil + } + return attestationconfigapi.List{}, err + } + + versions.Variant = attestation + + return versions, nil +} + +func (c Client) deleteVersion(versions attestationconfigapi.List, versionStr string) (ops []crudCmd, err error) { + versionStr = versionStr + ".json" + ops = append(ops, deleteCmd{ + apiObject: attestationconfigapi.Entry{ + Variant: versions.Variant, + Version: versionStr, + }, + }) + + removedVersions, err := removeVersion(versions, versionStr) + if err != nil { + return nil, err + } + ops = append(ops, putCmd{ + apiObject: removedVersions, + signer: c.signer, + }) + return ops, nil +} + +func (c Client) listCachedVersions(ctx context.Context, attestation variant.Variant) ([]string, error) { + list, err := c.s3Client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{ + Bucket: aws.String(c.bucketID), + Prefix: aws.String(reportVersionDir(attestation)), + }) + if err != nil { + return nil, fmt.Errorf("list objects: %w", err) + } + + var dates []string + for _, obj := range list.Contents { + fileName := path.Base(*obj.Key) + + // The cache contains signature and json files + // We only want the json files + if date, ok := strings.CutSuffix(fileName, ".json"); ok { + dates = append(dates, date) + } + } + return dates, nil +} + +func removeVersion(list attestationconfigapi.List, versionStr string) (removedVersions attestationconfigapi.List, err error) { + versions := list.List + for i, v := range versions { + if v == versionStr { + if i == len(versions)-1 { + removedVersions = attestationconfigapi.List{List: versions[:i], Variant: list.Variant} + } else { + removedVersions = attestationconfigapi.List{List: append(versions[:i], versions[i+1:]...), Variant: list.Variant} + } + return removedVersions, nil + } + } + return attestationconfigapi.List{}, fmt.Errorf("version %s not found in list %v", versionStr, versions) +} + +type crudCmd interface { + Execute(ctx context.Context, c *apiclient.Client) error +} + +type deleteCmd struct { + apiObject apiclient.APIObject +} + +func (d deleteCmd) Execute(ctx context.Context, c *apiclient.Client) error { + return apiclient.DeleteWithSignature(ctx, c, d.apiObject) +} + +type putCmd struct { + apiObject apiclient.APIObject + signer sigstore.Signer +} + +func (p putCmd) Execute(ctx context.Context, c *apiclient.Client) error { + return apiclient.SignAndUpdate(ctx, c, p.apiObject, p.signer) +} + +func executeAllCmds(ctx context.Context, client *apiclient.Client, cmds []crudCmd) error { + for _, cmd := range cmds { + if err := cmd.Execute(ctx, client); err != nil { + return fmt.Errorf("execute operation %+v: %w", cmd, err) + } + } + return nil +} diff --git a/internal/api/attestationconfigapi/cli/client/client_test.go b/internal/api/attestationconfigapi/cli/client/client_test.go new file mode 100644 index 000000000..008414f59 --- /dev/null +++ b/internal/api/attestationconfigapi/cli/client/client_test.go @@ -0,0 +1,34 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ +package client + +import ( + "testing" + + "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" + "github.com/stretchr/testify/assert" +) + +func TestDeleteAzureSEVSNPVersions(t *testing.T) { + sut := Client{ + bucketID: "bucket", + } + versions := attestationconfigapi.List{List: []string{"2023-01-01.json", "2021-01-01.json", "2019-01-01.json"}} + + ops, err := sut.deleteVersion(versions, "2021-01-01") + + assert := assert.New(t) + assert.NoError(err) + assert.Contains(ops, deleteCmd{ + apiObject: attestationconfigapi.Entry{ + Version: "2021-01-01.json", + }, + }) + + assert.Contains(ops, putCmd{ + apiObject: attestationconfigapi.List{List: []string{"2023-01-01.json", "2019-01-01.json"}}, + }) +} diff --git a/internal/api/attestationconfigapi/cli/client/reporter.go b/internal/api/attestationconfigapi/cli/client/reporter.go new file mode 100644 index 000000000..295c7b2b7 --- /dev/null +++ b/internal/api/attestationconfigapi/cli/client/reporter.go @@ -0,0 +1,367 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package client + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "path" + "sort" + "strings" + "time" + + "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" + "github.com/edgelesssys/constellation/v2/internal/api/client" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" +) + +// cachedVersionsSubDir is the subdirectory in the bucket where the cached versions are stored. +const cachedVersionsSubDir = "cached-versions" + +// ErrNoNewerVersion is returned if the input version is not newer than the latest API version. +var ErrNoNewerVersion = errors.New("input version is not newer than latest API version") + +func reportVersionDir(attestation variant.Variant) string { + return path.Join(attestationconfigapi.AttestationURLPath, attestation.String(), cachedVersionsSubDir) +} + +// IsInputNewerThanOtherVersion compares the input version with the other version and returns true if the input version is newer. +// This function panics if the input versions are not TDX or SEV-SNP versions. +func IsInputNewerThanOtherVersion(variant variant.Variant, inputVersion, otherVersion any) bool { + var result bool + actionForVariant(variant, + func() { + input := inputVersion.(attestationconfigapi.TDXVersion) + other := otherVersion.(attestationconfigapi.TDXVersion) + result = isInputNewerThanOtherTDXVersion(input, other) + }, + func() { + input := inputVersion.(attestationconfigapi.SEVSNPVersion) + other := otherVersion.(attestationconfigapi.SEVSNPVersion) + result = isInputNewerThanOtherSEVSNPVersion(input, other) + }, + ) + return result +} + +// UploadLatestVersion saves the given version to the cache, determines the smallest +// TCB version in the cache among the last cacheWindowSize versions and updates +// the latest version in the API if there is an update. +// force can be used to bypass the validation logic against the cached versions. +func (c Client) UploadLatestVersion( + ctx context.Context, attestationVariant variant.Variant, + inputVersion, latestVersionInAPI any, + now time.Time, force bool, +) error { + // Validate input versions against configured attestation variant + // This allows us to skip these checks in the individual variant implementations + var err error + actionForVariant(attestationVariant, + func() { + if _, ok := inputVersion.(attestationconfigapi.TDXVersion); !ok { + err = fmt.Errorf("input version %q is not a TDX version", inputVersion) + } + if _, ok := latestVersionInAPI.(attestationconfigapi.TDXVersion); !ok { + err = fmt.Errorf("latest API version %q is not a TDX version", latestVersionInAPI) + } + }, + func() { + if _, ok := inputVersion.(attestationconfigapi.SEVSNPVersion); !ok { + err = fmt.Errorf("input version %q is not a SNP version", inputVersion) + } + if _, ok := latestVersionInAPI.(attestationconfigapi.SEVSNPVersion); !ok { + err = fmt.Errorf("latest API version %q is not a SNP version", latestVersionInAPI) + } + }, + ) + if err != nil { + return err + } + + if err := c.addVersionToCache(ctx, attestationVariant, inputVersion, now); err != nil { + return fmt.Errorf("adding version to cache: %w", err) + } + + // If force is set, immediately update the latest version to the new version in the API. + if force { + return c.uploadAsLatestVersion(ctx, attestationVariant, inputVersion, now) + } + + // Otherwise, check the cached versions and update the latest version in the API if necessary. + versionDates, err := c.listCachedVersions(ctx, attestationVariant) + if err != nil { + return fmt.Errorf("listing existing cached versions: %w", err) + } + if len(versionDates) < c.cacheWindowSize { + c.log.Warn(fmt.Sprintf("Skipping version update, found %d, expected %d reported versions.", len(versionDates), c.cacheWindowSize)) + return nil + } + + minVersion, minDate, err := c.findMinVersion(ctx, attestationVariant, versionDates) + if err != nil { + return fmt.Errorf("determining minimal version in cache: %w", err) + } + c.log.Info(fmt.Sprintf("Found minimal version: %+v with date: %s", minVersion, minDate)) + + if !IsInputNewerThanOtherVersion(attestationVariant, minVersion, latestVersionInAPI) { + c.log.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v. Skipping list update", minVersion, latestVersionInAPI)) + return ErrNoNewerVersion + } + + c.log.Info(fmt.Sprintf("Input version: %+v is newer than latest API version: %+v", minVersion, latestVersionInAPI)) + t, err := time.Parse(VersionFormat, minDate) + if err != nil { + return fmt.Errorf("parsing date: %w", err) + } + + if err := c.uploadAsLatestVersion(ctx, attestationVariant, minVersion, t); err != nil { + return fmt.Errorf("uploading as latest version: %w", err) + } + + c.log.Info(fmt.Sprintf("Successfully uploaded new %s version: %+v", attestationVariant, minVersion)) + return nil +} + +// uploadAsLatestVersion uploads the given version and updates the list to set it as the "latest" version. +// The version's name is the UTC timestamp of the date. +// The /list entry stores the version name + .json suffix. +func (c Client) uploadAsLatestVersion(ctx context.Context, variant variant.Variant, inputVersion any, date time.Time) error { + versions, err := c.List(ctx, variant) + if err != nil { + return fmt.Errorf("fetch version list: %w", err) + } + if !variant.Equal(versions.Variant) { + return nil + } + + dateStr := date.Format(VersionFormat) + ".json" + var ops []crudCmd + + obj := apiVersionObject{version: dateStr, variant: variant, cached: false} + obj.setVersion(inputVersion) + ops = append(ops, putCmd{ + apiObject: obj, + signer: c.signer, + }) + + versions.AddVersion(dateStr) + + ops = append(ops, putCmd{ + apiObject: versions, + signer: c.signer, + }) + + return executeAllCmds(ctx, c.s3Client, ops) +} + +// addVersionToCache adds the given version to the cache. +func (c Client) addVersionToCache(ctx context.Context, variant variant.Variant, inputVersion any, date time.Time) error { + dateStr := date.Format(VersionFormat) + ".json" + obj := apiVersionObject{version: dateStr, variant: variant, cached: true} + obj.setVersion(inputVersion) + cmd := putCmd{ + apiObject: obj, + signer: c.signer, + } + return cmd.Execute(ctx, c.s3Client) +} + +// findMinVersion returns the minimal version in the cache among the last cacheWindowSize versions. +func (c Client) findMinVersion( + ctx context.Context, attestationVariant variant.Variant, versionDates []string, +) (any, string, error) { + var getMinimalVersion func() (any, string, error) + + actionForVariant(attestationVariant, + func() { + getMinimalVersion = func() (any, string, error) { + return findMinimalVersion[attestationconfigapi.TDXVersion](ctx, attestationVariant, versionDates, c.s3Client, c.cacheWindowSize) + } + }, + func() { + getMinimalVersion = func() (any, string, error) { + return findMinimalVersion[attestationconfigapi.SEVSNPVersion](ctx, attestationVariant, versionDates, c.s3Client, c.cacheWindowSize) + } + }, + ) + return getMinimalVersion() +} + +func findMinimalVersion[T attestationconfigapi.TDXVersion | attestationconfigapi.SEVSNPVersion]( + ctx context.Context, variant variant.Variant, versionDates []string, + s3Client *client.Client, cacheWindowSize int, +) (T, string, error) { + var minimalVersion *T + var minimalDate string + sort.Sort(sort.Reverse(sort.StringSlice(versionDates))) // sort in reverse order to slice the latest versions + versionDates = versionDates[:cacheWindowSize] + sort.Strings(versionDates) // sort with oldest first to to take the minimal version with the oldest date + + for _, date := range versionDates { + obj, err := client.Fetch(ctx, s3Client, apiVersionObject{version: date + ".json", variant: variant, cached: true}) + if err != nil { + return *new(T), "", fmt.Errorf("get object: %w", err) + } + obj.variant = variant // variant is not set by Fetch, set it manually + + if minimalVersion == nil { + v := obj.getVersion().(T) + minimalVersion = &v + minimalDate = date + continue + } + + // If the current minimal version has newer versions than the one we just fetched, + // update the minimal version to the older version. + if IsInputNewerThanOtherVersion(variant, *minimalVersion, obj.getVersion()) { + v := obj.getVersion().(T) + minimalVersion = &v + minimalDate = date + } + } + + return *minimalVersion, minimalDate, nil +} + +type apiVersionObject struct { + version string `json:"-"` + variant variant.Variant `json:"-"` + cached bool `json:"-"` + snp attestationconfigapi.SEVSNPVersion + tdx attestationconfigapi.TDXVersion +} + +func (a apiVersionObject) MarshalJSON() ([]byte, error) { + var res []byte + var err error + actionForVariant(a.variant, + func() { + res, err = json.Marshal(a.tdx) + }, + func() { + res, err = json.Marshal(a.snp) + }, + ) + return res, err +} + +func (a *apiVersionObject) UnmarshalJSON(data []byte) error { + errTDX := json.Unmarshal(data, &a.tdx) + errSNP := json.Unmarshal(data, &a.snp) + if errTDX == nil || errSNP == nil { + return nil + } + return fmt.Errorf("trying to unmarshal data into both TDX and SNP versions: %w", errors.Join(errTDX, errSNP)) +} + +// JSONPath returns the path to the JSON file for the request to the config api. +// This is the path to the cached version in the S3 bucket. +func (a apiVersionObject) JSONPath() string { + if a.cached { + return path.Join(reportVersionDir(a.variant), a.version) + } + return path.Join(attestationconfigapi.AttestationURLPath, a.variant.String(), a.version) +} + +// ValidateRequest validates the request. +func (a apiVersionObject) ValidateRequest() error { + if !strings.HasSuffix(a.version, ".json") { + return fmt.Errorf("version has no .json suffix") + } + return nil +} + +// Validate is a No-Op. +func (a apiVersionObject) Validate() error { + return nil +} + +// getVersion returns the version. +func (a apiVersionObject) getVersion() any { + var res any + actionForVariant(a.variant, + func() { + res = a.tdx + }, + func() { + res = a.snp + }, + ) + return res +} + +// setVersion sets the version. +func (a *apiVersionObject) setVersion(version any) { + actionForVariant(a.variant, + func() { + a.tdx = version.(attestationconfigapi.TDXVersion) + }, + func() { + a.snp = version.(attestationconfigapi.SEVSNPVersion) + }, + ) +} + +// actionForVariant performs the given action based on the whether variant is a TDX or SEV-SNP variant. +func actionForVariant( + attestationVariant variant.Variant, + tdxAction func(), snpAction func(), +) { + switch attestationVariant { + case variant.AWSSEVSNP{}, variant.AzureSEVSNP{}, variant.GCPSEVSNP{}: + snpAction() + case variant.AzureTDX{}: + tdxAction() + default: + panic(fmt.Sprintf("unsupported attestation variant: %s", attestationVariant)) + } +} + +// isInputNewerThanOtherSEVSNPVersion compares all version fields and returns false if any input field is older, or the versions are equal. +func isInputNewerThanOtherSEVSNPVersion(input, other attestationconfigapi.SEVSNPVersion) bool { + if input == other { + return false + } + if input.TEE < other.TEE { + return false + } + if input.SNP < other.SNP { + return false + } + if input.Microcode < other.Microcode { + return false + } + if input.Bootloader < other.Bootloader { + return false + } + return true +} + +// isInputNewerThanOtherSEVSNPVersion compares all version fields and returns false if any input field is older, or the versions are equal. +func isInputNewerThanOtherTDXVersion(input, other attestationconfigapi.TDXVersion) bool { + if input == other { + return false + } + + if input.PCESVN < other.PCESVN { + return false + } + if input.QESVN < other.QESVN { + return false + } + + // Validate component-wise security version numbers + for idx, inputVersion := range input.TEETCBSVN { + if inputVersion < other.TEETCBSVN[idx] { + return false + } + } + + return true +} diff --git a/internal/api/attestationconfigapi/cli/client/reporter_test.go b/internal/api/attestationconfigapi/cli/client/reporter_test.go new file mode 100644 index 000000000..9d786f33d --- /dev/null +++ b/internal/api/attestationconfigapi/cli/client/reporter_test.go @@ -0,0 +1,138 @@ +/* +Copyright (c) Edgeless Systems GmbH +SPDX-License-Identifier: AGPL-3.0-only +*/ +package client + +import ( + "testing" + + "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" + "github.com/stretchr/testify/assert" +) + +func TestIsInputNewerThanOtherSEVSNPVersion(t *testing.T) { + newTestCfg := func() attestationconfigapi.SEVSNPVersion { + return attestationconfigapi.SEVSNPVersion{ + Microcode: 93, + TEE: 0, + SNP: 6, + Bootloader: 2, + } + } + + testCases := map[string]struct { + latest attestationconfigapi.SEVSNPVersion + input attestationconfigapi.SEVSNPVersion + expect bool + }{ + "input is older than latest": { + input: func(c attestationconfigapi.SEVSNPVersion) attestationconfigapi.SEVSNPVersion { + c.Microcode-- + return c + }(newTestCfg()), + latest: newTestCfg(), + expect: false, + }, + "input has greater and smaller version field than latest": { + input: func(c attestationconfigapi.SEVSNPVersion) attestationconfigapi.SEVSNPVersion { + c.Microcode++ + c.Bootloader-- + return c + }(newTestCfg()), + latest: newTestCfg(), + expect: false, + }, + "input is newer than latest": { + input: func(c attestationconfigapi.SEVSNPVersion) attestationconfigapi.SEVSNPVersion { + c.TEE++ + return c + }(newTestCfg()), + latest: newTestCfg(), + expect: true, + }, + "input is equal to latest": { + input: newTestCfg(), + latest: newTestCfg(), + expect: false, + }, + } + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + isNewer := isInputNewerThanOtherSEVSNPVersion(tc.input, tc.latest) + assert.Equal(t, tc.expect, isNewer) + }) + } +} + +func TestIsInputNewerThanOtherTDXVersion(t *testing.T) { + newTestVersion := func() attestationconfigapi.TDXVersion { + return attestationconfigapi.TDXVersion{ + QESVN: 1, + PCESVN: 2, + TEETCBSVN: [16]byte{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, + QEVendorID: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + XFAM: [8]byte{0, 1, 2, 3, 4, 5, 6, 7}, + } + } + + testCases := map[string]struct { + latest attestationconfigapi.TDXVersion + input attestationconfigapi.TDXVersion + expect bool + }{ + "input is older than latest": { + input: func(c attestationconfigapi.TDXVersion) attestationconfigapi.TDXVersion { + c.QESVN-- + return c + }(newTestVersion()), + latest: newTestVersion(), + expect: false, + }, + "input has greater and smaller version field than latest": { + input: func(c attestationconfigapi.TDXVersion) attestationconfigapi.TDXVersion { + c.QESVN++ + c.PCESVN-- + return c + }(newTestVersion()), + latest: newTestVersion(), + expect: false, + }, + "input is newer than latest": { + input: func(c attestationconfigapi.TDXVersion) attestationconfigapi.TDXVersion { + c.QESVN++ + return c + }(newTestVersion()), + latest: newTestVersion(), + expect: true, + }, + "input is equal to latest": { + input: newTestVersion(), + latest: newTestVersion(), + expect: false, + }, + "tee tcb svn is newer": { + input: func(c attestationconfigapi.TDXVersion) attestationconfigapi.TDXVersion { + c.TEETCBSVN[4]++ + return c + }(newTestVersion()), + latest: newTestVersion(), + expect: true, + }, + "xfam is different": { + input: func(c attestationconfigapi.TDXVersion) attestationconfigapi.TDXVersion { + c.XFAM[3]++ + return c + }(newTestVersion()), + latest: newTestVersion(), + expect: true, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + isNewer := isInputNewerThanOtherTDXVersion(tc.input, tc.latest) + assert.Equal(t, tc.expect, isNewer) + }) + } +} diff --git a/internal/api/attestationconfigapi/cli/compare.go b/internal/api/attestationconfigapi/cli/compare.go new file mode 100644 index 000000000..9921ab76e --- /dev/null +++ b/internal/api/attestationconfigapi/cli/compare.go @@ -0,0 +1,101 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ +package main + +import ( + "fmt" + "os" + "slices" + + "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi/cli/client" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" + "github.com/edgelesssys/constellation/v2/internal/file" + "github.com/edgelesssys/constellation/v2/internal/verify" + "github.com/google/go-tdx-guest/proto/tdx" + "github.com/spf13/afero" + "github.com/spf13/cobra" +) + +func newCompareCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "compare VARIANT FILE [FILE...]", + Short: "Returns the minimum version of all given attestation reports.", + Long: "Compare a list of attestation reports and return the report with the minimum version.", + Example: "cli compare azure-sev-snp report1.json report2.json", + Args: cobra.MatchAll(cobra.MinimumNArgs(2), arg0isAttestationVariant()), + RunE: runCompare, + } + + return cmd +} + +func runCompare(cmd *cobra.Command, args []string) error { + cmd.SetOut(os.Stdout) + + variant, err := variant.FromString(args[0]) + if err != nil { + return fmt.Errorf("parsing variant: %w", err) + } + + return compare(cmd, variant, args[1:], file.NewHandler(afero.NewOsFs())) +} + +func compare(cmd *cobra.Command, attestationVariant variant.Variant, files []string, fs file.Handler) (retErr error) { + if !slices.Contains([]variant.Variant{variant.AWSSEVSNP{}, variant.AzureSEVSNP{}, variant.GCPSEVSNP{}, variant.AzureTDX{}}, attestationVariant) { + return fmt.Errorf("variant %s not supported", attestationVariant) + } + + lowestVersion, err := compareVersions(attestationVariant, files, fs) + if err != nil { + return fmt.Errorf("comparing versions: %w", err) + } + + cmd.Println(lowestVersion) + return nil +} + +func compareVersions(attestationVariant variant.Variant, files []string, fs file.Handler) (string, error) { + readReport := readSNPReport + if attestationVariant.Equal(variant.AzureTDX{}) { + readReport = readTDXReport + } + + lowestVersion := files[0] + lowestReport, err := readReport(files[0], fs) + if err != nil { + return "", fmt.Errorf("reading report: %w", err) + } + + for _, file := range files[1:] { + report, err := readReport(file, fs) + if err != nil { + return "", fmt.Errorf("reading report: %w", err) + } + + if client.IsInputNewerThanOtherVersion(attestationVariant, lowestReport, report) { + lowestVersion = file + lowestReport = report + } + } + + return lowestVersion, nil +} + +func readSNPReport(file string, fs file.Handler) (any, error) { + var report verify.Report + if err := fs.ReadJSON(file, &report); err != nil { + return nil, fmt.Errorf("reading snp report: %w", err) + } + return convertTCBVersionToSNPVersion(report.SNPReport.LaunchTCB), nil +} + +func readTDXReport(file string, fs file.Handler) (any, error) { + var report *tdx.QuoteV4 + if err := fs.ReadJSON(file, &report); err != nil { + return nil, fmt.Errorf("reading tdx report: %w", err) + } + return convertQuoteToTDXVersion(report), nil +} diff --git a/internal/api/attestationconfigapi/cli/delete.go b/internal/api/attestationconfigapi/cli/delete.go index daf457415..a800f7e80 100644 --- a/internal/api/attestationconfigapi/cli/delete.go +++ b/internal/api/attestationconfigapi/cli/delete.go @@ -16,8 +16,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" + "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi/cli/client" "github.com/edgelesssys/constellation/v2/internal/attestation/variant" - "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/staticupload" "github.com/spf13/cobra" @@ -26,21 +26,21 @@ import ( // newDeleteCmd creates the delete command. func newDeleteCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "delete {aws|azure|gcp} {snp-report|guest-firmware} ", + Use: "delete VARIANT KIND ", Short: "Delete an object from the attestationconfig API", Long: "Delete a specific object version from the config api. is the name of the object to delete (without .json suffix)", - Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli delete azure snp-report 1.0.0", - Args: cobra.MatchAll(cobra.ExactArgs(3), isCloudProvider(0), isValidKind(1)), + Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli delete azure-sev-snp attestation-report 1.0.0", + Args: cobra.MatchAll(cobra.ExactArgs(3), arg0isAttestationVariant(), isValidKind(1)), PreRunE: envCheck, RunE: runDelete, } recursivelyCmd := &cobra.Command{ - Use: "recursive {aws|azure|gcp}", + Use: "recursive {aws-sev-snp|azure-sev-snp|azure-tdx|gcp-sev-snp}", Short: "delete all objects from the API path constellation/v1/attestation/", Long: "Delete all objects from the API path constellation/v1/attestation/", - Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli delete recursive azure", - Args: cobra.MatchAll(cobra.ExactArgs(1), isCloudProvider(0)), + Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli delete recursive azure-sev-snp", + Args: cobra.MatchAll(cobra.ExactArgs(1), arg0isAttestationVariant()), RunE: runRecursiveDelete, } @@ -62,7 +62,7 @@ func runDelete(cmd *cobra.Command, args []string) (retErr error) { Region: deleteCfg.region, DistributionID: deleteCfg.distribution, } - client, clientClose, err := attestationconfigapi.NewClient(cmd.Context(), cfg, + client, clientClose, err := client.New(cmd.Context(), cfg, []byte(cosignPwd), []byte(privateKey), false, 1, log) if err != nil { return fmt.Errorf("create attestation client: %w", err) @@ -74,16 +74,7 @@ func runDelete(cmd *cobra.Command, args []string) (retErr error) { } }() - switch deleteCfg.provider { - case cloudprovider.AWS: - return deleteEntry(cmd.Context(), variant.AWSSEVSNP{}, client, deleteCfg) - case cloudprovider.Azure: - return deleteEntry(cmd.Context(), variant.AzureSEVSNP{}, client, deleteCfg) - case cloudprovider.GCP: - return deleteEntry(cmd.Context(), variant.GCPSEVSNP{}, client, deleteCfg) - default: - return fmt.Errorf("unsupported cloud provider: %s", deleteCfg.provider) - } + return deleteEntry(cmd.Context(), client, deleteCfg) } func runRecursiveDelete(cmd *cobra.Command, args []string) (retErr error) { @@ -111,23 +102,13 @@ func runRecursiveDelete(cmd *cobra.Command, args []string) (retErr error) { } }() - var deletePath string - switch deleteCfg.provider { - case cloudprovider.AWS: - deletePath = path.Join(attestationconfigapi.AttestationURLPath, variant.AWSSEVSNP{}.String()) - case cloudprovider.Azure: - deletePath = path.Join(attestationconfigapi.AttestationURLPath, variant.AzureSEVSNP{}.String()) - case cloudprovider.GCP: - deletePath = path.Join(attestationconfigapi.AttestationURLPath, variant.GCPSEVSNP{}.String()) - default: - return fmt.Errorf("unsupported cloud provider: %s", deleteCfg.provider) - } + deletePath := path.Join(attestationconfigapi.AttestationURLPath, deleteCfg.variant.String()) return deleteEntryRecursive(cmd.Context(), deletePath, client, deleteCfg) } type deleteConfig struct { - provider cloudprovider.Provider + variant variant.Variant kind objectKind version string region string @@ -154,12 +135,15 @@ func newDeleteConfig(cmd *cobra.Command, args [3]string) (deleteConfig, error) { } apiCfg := getAPIEnvironment(testing) - provider := cloudprovider.FromString(args[0]) + variant, err := variant.FromString(args[0]) + if err != nil { + return deleteConfig{}, fmt.Errorf("invalid attestation variant: %q: %w", args[0], err) + } kind := kindFromString(args[1]) version := args[2] return deleteConfig{ - provider: provider, + variant: variant, kind: kind, version: version, region: region, @@ -170,12 +154,12 @@ func newDeleteConfig(cmd *cobra.Command, args [3]string) (deleteConfig, error) { }, nil } -func deleteEntry(ctx context.Context, attvar variant.Variant, client *attestationconfigapi.Client, cfg deleteConfig) error { - if cfg.kind != snpReport { +func deleteEntry(ctx context.Context, client *client.Client, cfg deleteConfig) error { + if cfg.kind != attestationReport { return fmt.Errorf("kind %s not supported", cfg.kind) } - return client.DeleteSEVSNPVersion(ctx, attvar, cfg.version) + return client.DeleteVersion(ctx, cfg.variant, cfg.version) } func deleteEntryRecursive(ctx context.Context, path string, client *staticupload.Client, cfg deleteConfig) error { diff --git a/internal/api/attestationconfigapi/cli/e2e/test.sh.in b/internal/api/attestationconfigapi/cli/e2e/test.sh.in index 5fb23f06f..647fd6e08 100755 --- a/internal/api/attestationconfigapi/cli/e2e/test.sh.in +++ b/internal/api/attestationconfigapi/cli/e2e/test.sh.in @@ -19,39 +19,67 @@ configapi_cli=$(realpath @@CONFIGAPI_CLI@@) stat "${configapi_cli}" >> /dev/null configapi_cli="${configapi_cli} --testing" ###### script body ###### -function variant() { - if [[ $1 == "aws" ]]; then - echo "aws-sev-snp" - return 0 - elif [[ $1 == "azure" ]]; then - echo "azure-sev-snp" - return 0 - elif [[ $1 == "gcp" ]]; then - echo "gcp-sev-snp" - return 0 - else - echo "Unknown CSP: $1" - exit 1 - fi -} - -csp=$1 -readonly csp -attestationType=$(variant "$csp") +attestationVariant=$1 +readonly attestationVariant readonly region="eu-west-1" readonly bucket="resource-api-testing" tmpdir=$(mktemp -d) readonly tmpdir -registerExitHandler "rm -rf $tmpdir" +registerExitHandler "rm -rf ${tmpdir}" # empty the bucket version state -${configapi_cli} delete recursive "$csp" --region "$region" --bucket "$bucket" +${configapi_cli} delete recursive "${attestationVariant}" --region "${region}" --bucket "${bucket}" -# the high version numbers ensure that it's newer than the current latest value -readonly current_report_path="$tmpdir/currentSnpReport.json" -cat << EOF > "$current_report_path" +readonly current_report_path="${tmpdir}/attestationReportCurrent.json" +readonly report_path="${tmpdir}/attestationReport.json" +readonly older_report_path="${tmpdir}/attestationReportOld.json" + +if [[ ${attestationVariant} == *-tdx ]]; then + cat << EOF > "${current_report_path}" +{ + "header": { + "qe_svn": "AAA=", + "pce_svn": "AAA=", + "qe_vendor_id": "KioqKioqKioqKioqKioqKg==" + }, + "td_quote_body": { + "tee_tcb_svn": "AAAAAAAAAAAAAAAAAAAAAA==", + "xfam": "AAAAAAAAAAA=" + } +} +EOF + # the high version numbers ensure that it's newer than the current latest value + cat << EOF > "${report_path}" +{ + "header": { + "qe_svn": "//8=", + "pce_svn": "//8=", + "qe_vendor_id": "KioqKioqKioqKioqKioqKg==" + }, + "td_quote_body": { + "tee_tcb_svn": "/////////////////////w==", + "xfam": "AQIDBAUGBwg=" + } +} +EOF + # has an older version + cat << EOF > "${older_report_path}" +{ + "header": { + "qe_svn": "//8=", + "pce_svn": "/v8=", + "qe_vendor_id": "KioqKioqKioqKioqKioqKg==" + }, + "td_quote_body": { + "tee_tcb_svn": "/////////////////////g==", + "xfam": "AQIDBAUGBwg=" + } +} +EOF +elif [[ ${attestationVariant} == *-sev-snp ]]; then + cat << EOF > "${current_report_path}" { "snp_report": { "reported_tcb": { @@ -75,90 +103,105 @@ cat << EOF > "$current_report_path" } } EOF + # the high version numbers ensure that it's newer than the current latest value + cat << EOF > "${report_path}" +{ + "snp_report": { + "reported_tcb": { + "bootloader": 255, + "tee": 255, + "snp": 255, + "microcode": 255 + }, + "committed_tcb": { + "bootloader": 255, + "tee": 255, + "snp": 255, + "microcode": 255 + }, + "launch_tcb": { + "bootloader": 255, + "tee": 255, + "snp": 255, + "microcode": 255 + } + } +} +EOF + # has an older version + cat << EOF > "${older_report_path}" +{ + "snp_report": { + "reported_tcb": { + "bootloader": 255, + "tee": 255, + "snp": 255, + "microcode": 254 + }, + "committed_tcb": { + "bootloader": 255, + "tee": 255, + "snp": 255, + "microcode": 254 + }, + "launch_tcb": { + "bootloader": 255, + "tee": 255, + "snp": 255, + "microcode": 254 + } + } +} +EOF +else + echo "Unknown attestation variant: ${attestationVariant}" + exit 1 +fi + # upload a fake latest version for the fetcher -${configapi_cli} upload "$csp" snp-report "$current_report_path" --force --upload-date "2000-01-01-01-01" --region "$region" --bucket "$bucket" - -# the high version numbers ensure that it's newer than the current latest value -readonly report_path="$tmpdir/snpReport.json" -cat << EOF > "$report_path" -{ - "snp_report": { - "reported_tcb": { - "bootloader": 255, - "tee": 255, - "snp": 255, - "microcode": 255 - }, - "committed_tcb": { - "bootloader": 255, - "tee": 255, - "snp": 255, - "microcode": 255 - }, - "launch_tcb": { - "bootloader": 255, - "tee": 255, - "snp": 255, - "microcode": 255 - } - } -} -EOF - -# has an older version -readonly older_report_path="$tmpdir/snpReportOld.json" -cat << EOF > "$older_report_path" -{ - "snp_report": { - "reported_tcb": { - "bootloader": 255, - "tee": 255, - "snp": 255, - "microcode": 254 - }, - "committed_tcb": { - "bootloader": 255, - "tee": 255, - "snp": 255, - "microcode": 254 - }, - "launch_tcb": { - "bootloader": 255, - "tee": 255, - "snp": 255, - "microcode": 254 - } - } -} -EOF +${configapi_cli} upload "${attestationVariant}" attestation-report "${current_report_path}" --force --upload-date "2000-01-01-01-01" --region "${region}" --bucket "${bucket}" # report 3 versions with different dates to fill the reporter cache readonly date_oldest="2023-02-01-03-04" -${configapi_cli} upload "$csp" snp-report "$older_report_path" --upload-date "$date_oldest" --region "$region" --bucket "$bucket" --cache-window-size 3 +${configapi_cli} upload "${attestationVariant}" attestation-report "${older_report_path}" --upload-date "${date_oldest}" --region "${region}" --bucket "${bucket}" --cache-window-size 3 readonly date_older="2023-02-02-03-04" -${configapi_cli} upload "$csp" snp-report "$older_report_path" --upload-date "$date_older" --region "$region" --bucket "$bucket" --cache-window-size 3 +${configapi_cli} upload "${attestationVariant}" attestation-report "${older_report_path}" --upload-date "${date_older}" --region "${region}" --bucket "${bucket}" --cache-window-size 3 readonly date="2023-02-03-03-04" -${configapi_cli} upload "$csp" snp-report "$report_path" --upload-date "$date" --region "$region" --bucket "$bucket" --cache-window-size 3 +${configapi_cli} upload "${attestationVariant}" attestation-report "${report_path}" --upload-date "${date}" --region "${region}" --bucket "${bucket}" --cache-window-size 3 # expect that $date_oldest is served as latest version -basepath="constellation/v1/attestation/${attestationType}" +basepath="constellation/v1/attestation/${attestationVariant}" baseurl="https://d33dzgxuwsgbpw.cloudfront.net/${basepath}" -if ! curl -fsSL "${baseurl}"/${date_oldest}.json > version.json; then +if ! curl -fsSL "${baseurl}/${date_oldest}.json" > version.json; then echo "Checking for uploaded version file ${basepath}/${date_oldest}.json: request returned ${?}" exit 1 fi -# check that version values are equal to expected -if ! cmp -s <(echo -n '{"bootloader":255,"tee":255,"snp":255,"microcode":254}') version.json; then - echo "The version content:" - cat version.json - echo " is not equal to the expected version content:" - echo '{"bootloader":255,"tee":255,"snp":255,"microcode":254}' - exit 1 + +if [[ ${attestationVariant} == *-tdx ]]; then + # check that version values are equal to expected + if ! cmp -s <(echo -n '{"qeSVN":65535,"pceSVN":65534,"teeTCBSVN":[255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254],"qeVendorID":[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42],"xfam":[1,2,3,4,5,6,7,8]}') version.json; then + echo "The version content:" + cat version.json + echo " is not equal to the expected version content:" + echo '{"qeSVN":65535,"pceSVN":65534,"teeTCBSVN":[255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254],"qeVendorID":[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42],"xfam":[1,2,3,4,5,6,7,8]}' + exit 1 + fi +elif [[ ${attestationVariant} == *-sev-snp ]]; then + # check that version values are equal to expected + if ! cmp -s <(echo -n '{"bootloader":255,"tee":255,"snp":255,"microcode":254}') version.json; then + echo "The version content:" + cat version.json + echo " is not equal to the expected version content:" + echo '{"bootloader":255,"tee":255,"snp":255,"microcode":254}' + exit 1 + fi fi -if ! curl -fsSL "${baseurl}"/${date_oldest}.json.sig > /dev/null; then + +if ! curl -fsSL "${baseurl}/${date_oldest}.json.sig" > /dev/null; then echo "Checking for uploaded version signature file ${basepath}/${date_oldest}.json.sig: request returned ${?}" exit 1 fi + # check list endpoint if ! curl -fsSL "${baseurl}"/list > list.json; then echo "Checking for uploaded list file ${basepath}/list: request returned ${?}" @@ -174,28 +217,28 @@ if ! cmp -s <(echo -n '["2023-02-01-03-04.json","2000-01-01-01-01.json"]') list. fi # check that the other versions are not uploaded -http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}"/${date_older}.json) -if [[ $http_code -ne 404 ]]; then +http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}/${date_older}.json") +if [[ ${http_code} -ne 404 ]]; then echo "Expected HTTP code 404 for: ${basepath}/${date_older}.json, but got ${http_code}" exit 1 fi -http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}"/${date}.json.sig) -if [[ $http_code -ne 404 ]]; then +http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}/${date}.json.sig") +if [[ ${http_code} -ne 404 ]]; then echo "Expected HTTP code 404 for: ${basepath}/${date}.json, but got ${http_code}" exit 1 fi -${configapi_cli} delete "$csp" snp-report "$date_oldest" --region "$region" --bucket "$bucket" +${configapi_cli} delete "${attestationVariant}" attestation-report "${date_oldest}" --region "${region}" --bucket "${bucket}" # Omit -f to check for 404. We want to check that a file was deleted, therefore we expect the query to fail. -http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}"/${date_oldest}.json) -if [[ $http_code -ne 404 ]]; then +http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}/${date_oldest}.json") +if [[ ${http_code} -ne 404 ]]; then echo "Expected HTTP code 404 for: ${basepath}/${date_oldest}.json, but got ${http_code}" exit 1 fi # Omit -f to check for 404. We want to check that a file was deleted, therefore we expect the query to fail. -http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}"/${date_oldest}.json.sig) -if [[ $http_code -ne 404 ]]; then +http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}/${date_oldest}.json.sig") +if [[ ${http_code} -ne 404 ]]; then echo "Expected HTTP code 404 for: ${basepath}/${date_oldest}.json, but got ${http_code}" exit 1 fi diff --git a/internal/api/attestationconfigapi/cli/main.go b/internal/api/attestationconfigapi/cli/main.go index e6e951f1b..ee1b0c354 100644 --- a/internal/api/attestationconfigapi/cli/main.go +++ b/internal/api/attestationconfigapi/cli/main.go @@ -27,8 +27,11 @@ const ( distributionID = constants.CDNDefaultDistributionID envCosignPwd = "COSIGN_PASSWORD" envCosignPrivateKey = "COSIGN_PRIVATE_KEY" - // versionWindowSize defines the number of versions to be considered for the latest version. Each week 5 versions are uploaded for each node of the verify cluster. - versionWindowSize = 15 + // versionWindowSize defines the number of versions to be considered for the latest version. + // Through our weekly e2e tests, each week 2 versions are uploaded: + // One from a stable release, and one from a debug image. + // A window size of 6 ensures we update only after a version has been "stable" for 3 weeks. + versionWindowSize = 6 ) var ( @@ -56,6 +59,7 @@ func newRootCmd() *cobra.Command { rootCmd.AddCommand(newUploadCmd()) rootCmd.AddCommand(newDeleteCmd()) + rootCmd.AddCommand(newCompareCmd()) return rootCmd } diff --git a/internal/api/attestationconfigapi/cli/upload.go b/internal/api/attestationconfigapi/cli/upload.go index 98303cae2..4032f4626 100644 --- a/internal/api/attestationconfigapi/cli/upload.go +++ b/internal/api/attestationconfigapi/cli/upload.go @@ -7,6 +7,7 @@ package main import ( "context" + "encoding/binary" "errors" "fmt" "log/slog" @@ -14,31 +15,33 @@ import ( "time" "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" + "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi/cli/client" + "github.com/edgelesssys/constellation/v2/internal/api/fetcher" "github.com/edgelesssys/constellation/v2/internal/attestation/variant" - "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/staticupload" "github.com/edgelesssys/constellation/v2/internal/verify" + "github.com/google/go-tdx-guest/proto/tdx" "github.com/spf13/afero" "github.com/spf13/cobra" ) func newUploadCmd() *cobra.Command { uploadCmd := &cobra.Command{ - Use: "upload {aws|azure|gcp} {snp-report|guest-firmware} ", + Use: "upload VARIANT KIND FILE", Short: "Upload an object to the attestationconfig API", - Long: fmt.Sprintf("Upload a new object to the attestationconfig API. For snp-reports the new object is added to a cache folder first."+ + Long: fmt.Sprintf("Upload a new object to the attestationconfig API. For snp-reports the new object is added to a cache folder first.\n"+ "The CLI then determines the lowest version within the cache-window present in the cache and writes that value to the config api if necessary. "+ - "For guest-firmware objects the object is added to the API directly. "+ - "Please authenticate with AWS through your preferred method (e.g. environment variables, CLI)"+ + "For guest-firmware objects the object is added to the API directly.\n"+ + "Please authenticate with AWS through your preferred method (e.g. environment variables, CLI) "+ "to be able to upload to S3. Set the %s and %s environment variables to authenticate with cosign.", envCosignPrivateKey, envCosignPwd, ), - Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli upload azure snp-report /some/path/report.json", + Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli upload azure-sev-snp attestation-report /some/path/report.json", - Args: cobra.MatchAll(cobra.ExactArgs(3), isCloudProvider(0), isValidKind(1)), + Args: cobra.MatchAll(cobra.ExactArgs(3), arg0isAttestationVariant(), isValidKind(1)), PreRunE: envCheck, RunE: runUpload, } @@ -68,18 +71,15 @@ func runUpload(cmd *cobra.Command, args []string) (retErr error) { return fmt.Errorf("parsing cli flags: %w", err) } - client, clientClose, err := attestationconfigapi.NewClient( - ctx, + client, clientClose, err := client.New(ctx, staticupload.Config{ Bucket: uploadCfg.bucket, Region: uploadCfg.region, DistributionID: uploadCfg.distribution, }, - []byte(cosignPwd), - []byte(privateKey), - false, - uploadCfg.cacheWindowSize, - log) + []byte(cosignPwd), []byte(privateKey), + false, uploadCfg.cacheWindowSize, log, + ) defer func() { err := clientClose(cmd.Context()) @@ -92,56 +92,57 @@ func runUpload(cmd *cobra.Command, args []string) (retErr error) { return fmt.Errorf("creating client: %w", err) } - var attestation variant.Variant - switch uploadCfg.provider { - case cloudprovider.AWS: - attestation = variant.AWSSEVSNP{} - case cloudprovider.Azure: - attestation = variant.AzureSEVSNP{} - case cloudprovider.GCP: - attestation = variant.GCPSEVSNP{} - default: - return fmt.Errorf("unsupported cloud provider: %s", uploadCfg.provider) - } - - return uploadReport(ctx, attestation, client, uploadCfg, file.NewHandler(afero.NewOsFs()), log) + return uploadReport(ctx, client, uploadCfg, file.NewHandler(afero.NewOsFs()), log) } -func uploadReport(ctx context.Context, - attestation variant.Variant, - client *attestationconfigapi.Client, - cfg uploadConfig, - fs file.Handler, - log *slog.Logger, +func uploadReport( + ctx context.Context, apiClient *client.Client, + cfg uploadConfig, fs file.Handler, log *slog.Logger, ) error { - if cfg.kind != snpReport { + if cfg.kind != attestationReport { return fmt.Errorf("kind %s not supported", cfg.kind) } - log.Info(fmt.Sprintf("Reading SNP report from file: %s", cfg.path)) - var report verify.Report - if err := fs.ReadJSON(cfg.path, &report); err != nil { - return fmt.Errorf("reading snp report: %w", err) - } - - inputVersion := convertTCBVersionToSNPVersion(report.SNPReport.LaunchTCB) - log.Info(fmt.Sprintf("Input report: %+v", inputVersion)) - - latestAPIVersionAPI, err := attestationconfigapi.NewFetcherWithCustomCDNAndCosignKey(cfg.url, cfg.cosignPublicKey).FetchSEVSNPVersionLatest(ctx, attestation) + apiFetcher := attestationconfigapi.NewFetcherWithCustomCDNAndCosignKey(cfg.url, cfg.cosignPublicKey) + latestVersionInAPI, err := apiFetcher.FetchLatestVersion(ctx, cfg.variant) if err != nil { - if errors.Is(err, attestationconfigapi.ErrNoVersionsFound) { + var notFoundErr *fetcher.NotFoundError + if errors.As(err, ¬FoundErr) { log.Info("No versions found in API, but assuming that we are uploading the first version.") } else { return fmt.Errorf("fetching latest version: %w", err) } } - latestAPIVersion := latestAPIVersionAPI.SEVSNPVersion - if err := client.UploadSEVSNPVersionLatest(ctx, attestation, inputVersion, latestAPIVersion, cfg.uploadDate, cfg.force); err != nil { - if errors.Is(err, attestationconfigapi.ErrNoNewerVersion) { - log.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v", inputVersion, latestAPIVersion)) - return nil + var newVersion, latestVersion any + switch cfg.variant { + case variant.AWSSEVSNP{}, variant.AzureSEVSNP{}, variant.GCPSEVSNP{}: + latestVersion = latestVersionInAPI.SEVSNPVersion + + log.Info(fmt.Sprintf("Reading SNP report from file: %s", cfg.path)) + newVersion, err = readSNPReport(cfg.path, fs) + if err != nil { + return err } + log.Info(fmt.Sprintf("Input SNP report: %+v", newVersion)) + + case variant.AzureTDX{}: + latestVersion = latestVersionInAPI.TDXVersion + + log.Info(fmt.Sprintf("Reading TDX report from file: %s", cfg.path)) + newVersion, err = readTDXReport(cfg.path, fs) + if err != nil { + return err + } + log.Info(fmt.Sprintf("Input TDX report: %+v", newVersion)) + + default: + return fmt.Errorf("variant %s not supported", cfg.variant) + } + + if err := apiClient.UploadLatestVersion( + ctx, cfg.variant, newVersion, latestVersion, cfg.uploadDate, cfg.force, + ); err != nil && !errors.Is(err, client.ErrNoNewerVersion) { return fmt.Errorf("updating latest version: %w", err) } @@ -157,8 +158,18 @@ func convertTCBVersionToSNPVersion(tcb verify.TCBVersion) attestationconfigapi.S } } +func convertQuoteToTDXVersion(quote *tdx.QuoteV4) attestationconfigapi.TDXVersion { + return attestationconfigapi.TDXVersion{ + QESVN: binary.LittleEndian.Uint16(quote.Header.QeSvn), + PCESVN: binary.LittleEndian.Uint16(quote.Header.PceSvn), + QEVendorID: [16]byte(quote.Header.QeVendorId), + XFAM: [8]byte(quote.TdQuoteBody.Xfam), + TEETCBSVN: [16]byte(quote.TdQuoteBody.TeeTcbSvn), + } +} + type uploadConfig struct { - provider cloudprovider.Provider + variant variant.Variant kind objectKind path string uploadDate time.Time @@ -178,7 +189,7 @@ func newConfig(cmd *cobra.Command, args [3]string) (uploadConfig, error) { } uploadDate := time.Now() if dateStr != "" { - uploadDate, err = time.Parse(attestationconfigapi.VersionFormat, dateStr) + uploadDate, err = time.Parse(client.VersionFormat, dateStr) if err != nil { return uploadConfig{}, fmt.Errorf("parsing date: %w", err) } @@ -210,12 +221,16 @@ func newConfig(cmd *cobra.Command, args [3]string) (uploadConfig, error) { return uploadConfig{}, fmt.Errorf("getting cache window size: %w", err) } - provider := cloudprovider.FromString(args[0]) + variant, err := variant.FromString(args[0]) + if err != nil { + return uploadConfig{}, fmt.Errorf("invalid attestation variant: %q: %w", args[0], err) + } + kind := kindFromString(args[1]) path := args[2] return uploadConfig{ - provider: provider, + variant: variant, kind: kind, path: path, uploadDate: uploadDate, diff --git a/internal/api/attestationconfigapi/cli/validargs.go b/internal/api/attestationconfigapi/cli/validargs.go index 033aaa0a3..b5366b0f9 100644 --- a/internal/api/attestationconfigapi/cli/validargs.go +++ b/internal/api/attestationconfigapi/cli/validargs.go @@ -7,26 +7,33 @@ SPDX-License-Identifier: AGPL-3.0-only package main import ( + "errors" "fmt" "strings" - "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/spf13/cobra" ) -func isCloudProvider(arg int) cobra.PositionalArgs { +func arg0isAttestationVariant() cobra.PositionalArgs { return func(_ *cobra.Command, args []string) error { - if provider := cloudprovider.FromString(args[arg]); provider == cloudprovider.Unknown { - return fmt.Errorf("argument %s isn't a valid cloud provider", args[arg]) + attestationVariant, err := variant.FromString(args[0]) + if err != nil { + return errors.New("argument 0 isn't a valid attestation variant") + } + switch attestationVariant { + case variant.AWSSEVSNP{}, variant.AzureSEVSNP{}, variant.AzureTDX{}, variant.GCPSEVSNP{}: + return nil + default: + return errors.New("argument 0 isn't a supported attestation variant") } - return nil } } func isValidKind(arg int) cobra.PositionalArgs { return func(_ *cobra.Command, args []string) error { if kind := kindFromString(args[arg]); kind == unknown { - return fmt.Errorf("argument %s isn't a valid kind", args[arg]) + return fmt.Errorf("argument %s isn't a valid kind: must be one of [%q, %q]", args[arg], attestationReport, guestFirmware) } return nil } @@ -37,15 +44,15 @@ type objectKind string const ( // unknown is the default objectKind and does nothing. - unknown objectKind = "unknown-kind" - snpReport objectKind = "snp-report" - guestFirmware objectKind = "guest-firmware" + unknown objectKind = "unknown-kind" + attestationReport objectKind = "attestation-report" + guestFirmware objectKind = "guest-firmware" ) func kindFromString(s string) objectKind { lower := strings.ToLower(s) switch objectKind(lower) { - case snpReport, guestFirmware: + case attestationReport, guestFirmware: return objectKind(lower) default: return unknown diff --git a/internal/api/attestationconfigapi/client.go b/internal/api/attestationconfigapi/client.go deleted file mode 100644 index 11b27eae0..000000000 --- a/internal/api/attestationconfigapi/client.go +++ /dev/null @@ -1,184 +0,0 @@ -/* -Copyright (c) Edgeless Systems GmbH - -SPDX-License-Identifier: AGPL-3.0-only -*/ -package attestationconfigapi - -import ( - "context" - "errors" - "fmt" - "log/slog" - "time" - - apiclient "github.com/edgelesssys/constellation/v2/internal/api/client" - "github.com/edgelesssys/constellation/v2/internal/attestation/variant" - "github.com/edgelesssys/constellation/v2/internal/sigstore" - - "github.com/edgelesssys/constellation/v2/internal/staticupload" -) - -// VersionFormat is the format of the version name in the S3 bucket. -const VersionFormat = "2006-01-02-15-04" - -// Client manages (modifies) the version information for the attestation variants. -type Client struct { - s3Client *apiclient.Client - s3ClientClose func(ctx context.Context) error - bucketID string - signer sigstore.Signer - cacheWindowSize int -} - -// NewClient returns a new Client. -func NewClient(ctx context.Context, cfg staticupload.Config, cosignPwd, privateKey []byte, dryRun bool, versionWindowSize int, log *slog.Logger) (*Client, apiclient.CloseFunc, error) { - s3Client, clientClose, err := apiclient.NewClient(ctx, cfg.Region, cfg.Bucket, cfg.DistributionID, dryRun, log) - if err != nil { - return nil, nil, fmt.Errorf("failed to create s3 storage: %w", err) - } - - repo := &Client{ - s3Client: s3Client, - s3ClientClose: clientClose, - signer: sigstore.NewSigner(cosignPwd, privateKey), - bucketID: cfg.Bucket, - cacheWindowSize: versionWindowSize, - } - return repo, clientClose, nil -} - -// uploadSEVSNPVersion uploads the latest version numbers of the SEVSNP. Then version name is the UTC timestamp of the date. The /list entry stores the version name + .json suffix. -func (a Client) uploadSEVSNPVersion(ctx context.Context, attestation variant.Variant, version SEVSNPVersion, date time.Time) error { - versions, err := a.List(ctx, attestation) - if err != nil { - return fmt.Errorf("fetch version list: %w", err) - } - ops := a.constructUploadCmd(attestation, version, versions, date) - - return executeAllCmds(ctx, a.s3Client, ops) -} - -// DeleteSEVSNPVersion deletes the given version (without .json suffix) from the API. -func (a Client) DeleteSEVSNPVersion(ctx context.Context, attestation variant.Variant, versionStr string) error { - versions, err := a.List(ctx, attestation) - if err != nil { - return fmt.Errorf("fetch version list: %w", err) - } - - ops, err := a.deleteSEVSNPVersion(versions, versionStr) - if err != nil { - return err - } - return executeAllCmds(ctx, a.s3Client, ops) -} - -// List returns the list of versions for the given attestation variant. -func (a Client) List(ctx context.Context, attestation variant.Variant) (SEVSNPVersionList, error) { - if !attestation.Equal(variant.AzureSEVSNP{}) && - !attestation.Equal(variant.AWSSEVSNP{}) && - !attestation.Equal(variant.GCPSEVSNP{}) { - return SEVSNPVersionList{}, fmt.Errorf("unsupported attestation variant: %s", attestation) - } - - versions, err := apiclient.Fetch(ctx, a.s3Client, SEVSNPVersionList{variant: attestation}) - if err != nil { - var notFoundErr *apiclient.NotFoundError - if errors.As(err, ¬FoundErr) { - return SEVSNPVersionList{variant: attestation}, nil - } - return SEVSNPVersionList{}, err - } - - versions.variant = attestation - - return versions, nil -} - -func (a Client) deleteSEVSNPVersion(versions SEVSNPVersionList, versionStr string) (ops []crudCmd, err error) { - versionStr = versionStr + ".json" - ops = append(ops, deleteCmd{ - apiObject: SEVSNPVersionAPI{ - Variant: versions.variant, - Version: versionStr, - }, - }) - - removedVersions, err := removeVersion(versions, versionStr) - if err != nil { - return nil, err - } - ops = append(ops, putCmd{ - apiObject: removedVersions, - signer: a.signer, - }) - return ops, nil -} - -func (a Client) constructUploadCmd(attestation variant.Variant, version SEVSNPVersion, versionNames SEVSNPVersionList, date time.Time) []crudCmd { - if !attestation.Equal(versionNames.variant) { - return nil - } - - dateStr := date.Format(VersionFormat) + ".json" - var res []crudCmd - - res = append(res, putCmd{ - apiObject: SEVSNPVersionAPI{Version: dateStr, Variant: attestation, SEVSNPVersion: version}, - signer: a.signer, - }) - - versionNames.addVersion(dateStr) - - res = append(res, putCmd{ - apiObject: versionNames, - signer: a.signer, - }) - - return res -} - -func removeVersion(list SEVSNPVersionList, versionStr string) (removedVersions SEVSNPVersionList, err error) { - versions := list.List() - for i, v := range versions { - if v == versionStr { - if i == len(versions)-1 { - removedVersions = SEVSNPVersionList{list: versions[:i], variant: list.variant} - } else { - removedVersions = SEVSNPVersionList{list: append(versions[:i], versions[i+1:]...), variant: list.variant} - } - return removedVersions, nil - } - } - return SEVSNPVersionList{}, fmt.Errorf("version %s not found in list %v", versionStr, versions) -} - -type crudCmd interface { - Execute(ctx context.Context, c *apiclient.Client) error -} - -type deleteCmd struct { - apiObject apiclient.APIObject -} - -func (d deleteCmd) Execute(ctx context.Context, c *apiclient.Client) error { - return apiclient.DeleteWithSignature(ctx, c, d.apiObject) -} - -type putCmd struct { - apiObject apiclient.APIObject - signer sigstore.Signer -} - -func (p putCmd) Execute(ctx context.Context, c *apiclient.Client) error { - return apiclient.SignAndUpdate(ctx, c, p.apiObject, p.signer) -} - -func executeAllCmds(ctx context.Context, client *apiclient.Client, cmds []crudCmd) error { - for _, cmd := range cmds { - if err := cmd.Execute(ctx, client); err != nil { - return fmt.Errorf("execute operation %+v: %w", cmd, err) - } - } - return nil -} diff --git a/internal/api/attestationconfigapi/client_test.go b/internal/api/attestationconfigapi/client_test.go deleted file mode 100644 index 9cae1bc5a..000000000 --- a/internal/api/attestationconfigapi/client_test.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright (c) Edgeless Systems GmbH - -SPDX-License-Identifier: AGPL-3.0-only -*/ -package attestationconfigapi - -import ( - "testing" - "time" - - "github.com/edgelesssys/constellation/v2/internal/attestation/variant" - "github.com/stretchr/testify/assert" -) - -func TestUploadAzureSEVSNP(t *testing.T) { - sut := Client{ - bucketID: "bucket", - signer: fakeSigner{}, - } - version := SEVSNPVersion{} - date := time.Date(2023, 1, 1, 1, 1, 1, 1, time.UTC) - ops := sut.constructUploadCmd(variant.AzureSEVSNP{}, version, SEVSNPVersionList{list: []string{"2021-01-01-01-01.json", "2019-01-01-01-01.json"}, variant: variant.AzureSEVSNP{}}, date) - dateStr := "2023-01-01-01-01.json" - assert := assert.New(t) - assert.Contains(ops, putCmd{ - apiObject: SEVSNPVersionAPI{ - Variant: variant.AzureSEVSNP{}, - Version: dateStr, - SEVSNPVersion: version, - }, - signer: fakeSigner{}, - }) - assert.Contains(ops, putCmd{ - apiObject: SEVSNPVersionList{variant: variant.AzureSEVSNP{}, list: []string{"2023-01-01-01-01.json", "2021-01-01-01-01.json", "2019-01-01-01-01.json"}}, - signer: fakeSigner{}, - }) -} - -func TestDeleteAzureSEVSNPVersions(t *testing.T) { - sut := Client{ - bucketID: "bucket", - } - versions := SEVSNPVersionList{list: []string{"2023-01-01.json", "2021-01-01.json", "2019-01-01.json"}} - - ops, err := sut.deleteSEVSNPVersion(versions, "2021-01-01") - - assert := assert.New(t) - assert.NoError(err) - assert.Contains(ops, deleteCmd{ - apiObject: SEVSNPVersionAPI{ - Version: "2021-01-01.json", - }, - }) - - assert.Contains(ops, putCmd{ - apiObject: SEVSNPVersionList{list: []string{"2023-01-01.json", "2019-01-01.json"}}, - }) -} - -type fakeSigner struct{} - -func (fakeSigner) Sign(_ []byte) ([]byte, error) { - return []byte("signature"), nil -} diff --git a/internal/api/attestationconfigapi/fetcher.go b/internal/api/attestationconfigapi/fetcher.go index a54e3ebc7..ca30bb554 100644 --- a/internal/api/attestationconfigapi/fetcher.go +++ b/internal/api/attestationconfigapi/fetcher.go @@ -8,7 +8,6 @@ package attestationconfigapi import ( "context" - "errors" "fmt" apifetcher "github.com/edgelesssys/constellation/v2/internal/api/fetcher" @@ -19,14 +18,9 @@ import ( const cosignPublicKey = constants.CosignPublicKeyReleases -// ErrNoVersionsFound is returned if no versions are found. -var ErrNoVersionsFound = errors.New("no versions found") - // Fetcher fetches config API resources without authentication. type Fetcher interface { - FetchSEVSNPVersion(ctx context.Context, version SEVSNPVersionAPI) (SEVSNPVersionAPI, error) - FetchSEVSNPVersionList(ctx context.Context, list SEVSNPVersionList) (SEVSNPVersionList, error) - FetchSEVSNPVersionLatest(ctx context.Context, attestation variant.Variant) (SEVSNPVersionAPI, error) + FetchLatestVersion(ctx context.Context, attestation variant.Variant) (Entry, error) } // fetcher fetches AttestationCfg API resources without authentication. @@ -65,47 +59,43 @@ func newFetcherWithClientAndVerifier(client apifetcher.HTTPClient, cosignVerifie return &fetcher{HTTPClient: client, verifier: cosignVerifier, cdnURL: url} } -// FetchSEVSNPVersionList fetches the version list information from the config API. -func (f *fetcher) FetchSEVSNPVersionList(ctx context.Context, list SEVSNPVersionList) (SEVSNPVersionList, error) { - // TODO(derpsteb): Replace with FetchAndVerify once we move to v2 of the config API. - fetchedList, err := apifetcher.Fetch(ctx, f.HTTPClient, f.cdnURL, list) +// FetchLatestVersion returns the latest versions of the given type. +func (f *fetcher) FetchLatestVersion(ctx context.Context, variant variant.Variant) (Entry, error) { + list, err := f.fetchVersionList(ctx, variant) if err != nil { - return list, fmt.Errorf("fetching version list: %w", err) + return Entry{}, err } - // Need to set this explicitly as the variant is not part of the marshalled JSON. - fetchedList.variant = list.variant + // latest version is first in list + return f.fetchVersion(ctx, list.List[0], variant) +} + +// fetchVersionList fetches the version list information from the config API. +func (f *fetcher) fetchVersionList(ctx context.Context, variant variant.Variant) (List, error) { + fetchedList, err := apifetcher.FetchAndVerify(ctx, f.HTTPClient, f.cdnURL, List{Variant: variant}, f.verifier) + if err != nil { + return List{}, fmt.Errorf("fetching version list: %w", err) + } + + // Set the attestation variant of the list as it is not part of the marshalled JSON retrieved by Fetch + fetchedList.Variant = variant return fetchedList, nil } -// FetchSEVSNPVersion fetches the version information from the config API. -func (f *fetcher) FetchSEVSNPVersion(ctx context.Context, version SEVSNPVersionAPI) (SEVSNPVersionAPI, error) { - fetchedVersion, err := apifetcher.FetchAndVerify(ctx, f.HTTPClient, f.cdnURL, version, f.verifier) +// fetchVersion fetches the version information from the config API. +func (f *fetcher) fetchVersion(ctx context.Context, version string, variant variant.Variant) (Entry, error) { + obj := Entry{ + Version: version, + Variant: variant, + } + fetchedVersion, err := apifetcher.FetchAndVerify(ctx, f.HTTPClient, f.cdnURL, obj, f.verifier) if err != nil { - return fetchedVersion, fmt.Errorf("fetching version %s: %w", version.Version, err) + return Entry{}, fmt.Errorf("fetching version %q: %w", version, err) } - // Need to set this explicitly as the variant is not part of the marshalled JSON. - fetchedVersion.Variant = version.Variant + // Set the attestation variant of the list as it is not part of the marshalled JSON retrieved by FetchAndVerify + fetchedVersion.Variant = variant return fetchedVersion, nil } - -// FetchSEVSNPVersionLatest returns the latest versions of the given type. -func (f *fetcher) FetchSEVSNPVersionLatest(ctx context.Context, attesation variant.Variant) (res SEVSNPVersionAPI, err error) { - list, err := f.FetchSEVSNPVersionList(ctx, SEVSNPVersionList{variant: attesation}) - if err != nil { - return res, ErrNoVersionsFound - } - - getVersionRequest := SEVSNPVersionAPI{ - Version: list.List()[0], // latest version is first in list - Variant: attesation, - } - res, err = f.FetchSEVSNPVersion(ctx, getVersionRequest) - if err != nil { - return res, err - } - return -} diff --git a/internal/api/attestationconfigapi/fetcher_test.go b/internal/api/attestationconfigapi/fetcher_test.go index cb9fd86eb..b3d737f54 100644 --- a/internal/api/attestationconfigapi/fetcher_test.go +++ b/internal/api/attestationconfigapi/fetcher_test.go @@ -22,87 +22,112 @@ import ( ) func TestFetchLatestSEVSNPVersion(t *testing.T) { + latestVersionSNP := Entry{ + SEVSNPVersion: SEVSNPVersion{ + Microcode: 93, + TEE: 0, + SNP: 6, + Bootloader: 2, + }, + } + olderVersionSNP := Entry{ + SEVSNPVersion: SEVSNPVersion{ + Microcode: 1, + TEE: 0, + SNP: 1, + Bootloader: 1, + }, + } + latestVersionTDX := Entry{ + TDXVersion: TDXVersion{ + QESVN: 2, + PCESVN: 3, + TEETCBSVN: [16]byte{4}, + QEVendorID: [16]byte{5}, + XFAM: [8]byte{6}, + }, + } + olderVersionTDX := Entry{ + TDXVersion: TDXVersion{ + QESVN: 1, + PCESVN: 2, + TEETCBSVN: [16]byte{3}, + QEVendorID: [16]byte{4}, + XFAM: [8]byte{5}, + }, + } + latestStr := "2023-06-11-14-09.json" olderStr := "2019-01-01-01-01.json" - testcases := map[string]struct { + testCases := map[string]struct { fetcherVersions []string timeAtTest time.Time wantErr bool attestation variant.Variant - expectedVersion func() SEVSNPVersionAPI - olderVersion func() SEVSNPVersionAPI - latestVersion func() SEVSNPVersionAPI + expectedVersion Entry + olderVersion Entry + latestVersion Entry }{ - "get latest version azure": { + "get latest version azure-sev-snp": { fetcherVersions: []string{latestStr, olderStr}, attestation: variant.AzureSEVSNP{}, - expectedVersion: func() SEVSNPVersionAPI { tmp := latestVersion; tmp.Variant = variant.AzureSEVSNP{}; return tmp }, - olderVersion: func() SEVSNPVersionAPI { tmp := olderVersion; tmp.Variant = variant.AzureSEVSNP{}; return tmp }, - latestVersion: func() SEVSNPVersionAPI { tmp := latestVersion; tmp.Variant = variant.AzureSEVSNP{}; return tmp }, + expectedVersion: func() Entry { tmp := latestVersionSNP; tmp.Variant = variant.AzureSEVSNP{}; return tmp }(), + olderVersion: func() Entry { tmp := olderVersionSNP; tmp.Variant = variant.AzureSEVSNP{}; return tmp }(), + latestVersion: func() Entry { tmp := latestVersionSNP; tmp.Variant = variant.AzureSEVSNP{}; return tmp }(), }, - "get latest version aws": { + "get latest version aws-sev-snp": { fetcherVersions: []string{latestStr, olderStr}, attestation: variant.AWSSEVSNP{}, - expectedVersion: func() SEVSNPVersionAPI { tmp := latestVersion; tmp.Variant = variant.AWSSEVSNP{}; return tmp }, - olderVersion: func() SEVSNPVersionAPI { tmp := olderVersion; tmp.Variant = variant.AWSSEVSNP{}; return tmp }, - latestVersion: func() SEVSNPVersionAPI { tmp := latestVersion; tmp.Variant = variant.AWSSEVSNP{}; return tmp }, + expectedVersion: func() Entry { tmp := latestVersionSNP; tmp.Variant = variant.AWSSEVSNP{}; return tmp }(), + olderVersion: func() Entry { tmp := olderVersionSNP; tmp.Variant = variant.AWSSEVSNP{}; return tmp }(), + latestVersion: func() Entry { tmp := latestVersionSNP; tmp.Variant = variant.AWSSEVSNP{}; return tmp }(), + }, + "get latest version azure-tdx": { + fetcherVersions: []string{latestStr, olderStr}, + attestation: variant.AzureTDX{}, + expectedVersion: func() Entry { tmp := latestVersionTDX; tmp.Variant = variant.AzureTDX{}; return tmp }(), + olderVersion: func() Entry { tmp := olderVersionTDX; tmp.Variant = variant.AzureTDX{}; return tmp }(), + latestVersion: func() Entry { tmp := latestVersionTDX; tmp.Variant = variant.AzureTDX{}; return tmp }(), }, } - for name, tc := range testcases { + for name, tc := range testCases { t.Run(name, func(t *testing.T) { client := &http.Client{ Transport: &fakeConfigAPIHandler{ attestation: tc.attestation, versions: tc.fetcherVersions, latestDate: latestStr, - latestVersion: tc.latestVersion(), + latestVersion: tc.latestVersion, olderDate: olderStr, - olderVersion: tc.olderVersion(), + olderVersion: tc.olderVersion, }, } - fetcher := newFetcherWithClientAndVerifier(client, dummyVerifier{}, constants.CDNRepositoryURL) - res, err := fetcher.FetchSEVSNPVersionLatest(context.Background(), tc.attestation) + fetcher := newFetcherWithClientAndVerifier(client, stubVerifier{}, constants.CDNRepositoryURL) + res, err := fetcher.FetchLatestVersion(context.Background(), tc.attestation) assert := assert.New(t) if tc.wantErr { assert.Error(err) } else { assert.NoError(err) - assert.Equal(tc.expectedVersion(), res) + assert.Equal(tc.expectedVersion, res) } }) } } -var latestVersion = SEVSNPVersionAPI{ - SEVSNPVersion: SEVSNPVersion{ - Microcode: 93, - TEE: 0, - SNP: 6, - Bootloader: 2, - }, -} - -var olderVersion = SEVSNPVersionAPI{ - SEVSNPVersion: SEVSNPVersion{ - Microcode: 1, - TEE: 0, - SNP: 1, - Bootloader: 1, - }, -} - type fakeConfigAPIHandler struct { attestation variant.Variant versions []string latestDate string - latestVersion SEVSNPVersionAPI + latestVersion Entry olderDate string - olderVersion SEVSNPVersionAPI + olderVersion Entry } // RoundTrip resolves the request and returns a dummy response. func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, error) { - if req.URL.Path == fmt.Sprintf("/constellation/v1/attestation/%s/list", f.attestation.String()) { + switch req.URL.Path { + case fmt.Sprintf("/constellation/v1/attestation/%s/list", f.attestation.String()): res := &http.Response{} bt, err := json.Marshal(f.versions) if err != nil { @@ -113,7 +138,14 @@ func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, err res.Header.Set("Content-Type", "application/json") res.StatusCode = http.StatusOK return res, nil - } else if req.URL.Path == fmt.Sprintf("/constellation/v1/attestation/%s/%s", f.attestation.String(), f.latestDate) { + + case fmt.Sprintf("/constellation/v1/attestation/%s/list.sig", f.attestation.String()): + res := &http.Response{} + res.Body = io.NopCloser(bytes.NewReader([]byte("null"))) + res.StatusCode = http.StatusOK + return res, nil + + case fmt.Sprintf("/constellation/v1/attestation/%s/%s", f.attestation.String(), f.latestDate): res := &http.Response{} bt, err := json.Marshal(f.latestVersion) if err != nil { @@ -123,7 +155,7 @@ func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, err res.StatusCode = http.StatusOK return res, nil - } else if req.URL.Path == fmt.Sprintf("/constellation/v1/attestation/%s/%s", f.attestation.String(), f.olderDate) { + case fmt.Sprintf("/constellation/v1/attestation/%s/%s", f.attestation.String(), f.olderDate): res := &http.Response{} bt, err := json.Marshal(f.olderVersion) if err != nil { @@ -132,13 +164,14 @@ func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, err res.Body = io.NopCloser(bytes.NewReader(bt)) res.StatusCode = http.StatusOK return res, nil - } else if req.URL.Path == fmt.Sprintf("/constellation/v1/attestation/%s/%s.sig", f.attestation.String(), f.latestDate) { + + case fmt.Sprintf("/constellation/v1/attestation/%s/%s.sig", f.attestation.String(), f.latestDate): res := &http.Response{} res.Body = io.NopCloser(bytes.NewReader([]byte("null"))) res.StatusCode = http.StatusOK return res, nil - } else if req.URL.Path == fmt.Sprintf("/constellation/v1/attestation/%s/%s.sig", f.attestation.String(), f.olderDate) { + case fmt.Sprintf("/constellation/v1/attestation/%s/%s.sig", f.attestation.String(), f.olderDate): res := &http.Response{} res.Body = io.NopCloser(bytes.NewReader([]byte("null"))) res.StatusCode = http.StatusOK @@ -148,8 +181,8 @@ func (f *fakeConfigAPIHandler) RoundTrip(req *http.Request) (*http.Response, err return nil, errors.New("no endpoint found") } -type dummyVerifier struct{} +type stubVerifier struct{} -func (s dummyVerifier) VerifySignature(_, _ []byte) error { +func (s stubVerifier) VerifySignature(_, _ []byte) error { return nil } diff --git a/internal/api/attestationconfigapi/reporter.go b/internal/api/attestationconfigapi/reporter.go deleted file mode 100644 index 72a980347..000000000 --- a/internal/api/attestationconfigapi/reporter.go +++ /dev/null @@ -1,189 +0,0 @@ -/* -Copyright (c) Edgeless Systems GmbH - -SPDX-License-Identifier: AGPL-3.0-only -*/ - -/* -The reporter contains the logic to determine a latest version for SEVSNP based on cached version values observed on CVM instances. -Some code in this file (e.g. listing cached files) does not rely on dedicated API objects and instead uses the AWS SDK directly, -for no other reason than original development speed. -*/ -package attestationconfigapi - -import ( - "context" - "errors" - "fmt" - "path" - "sort" - "strings" - "time" - - "github.com/aws/aws-sdk-go-v2/service/s3" - "github.com/aws/aws-sdk-go/aws" - - "github.com/edgelesssys/constellation/v2/internal/api/client" - "github.com/edgelesssys/constellation/v2/internal/attestation/variant" -) - -// cachedVersionsSubDir is the subdirectory in the bucket where the cached versions are stored. -const cachedVersionsSubDir = "cached-versions" - -// ErrNoNewerVersion is returned if the input version is not newer than the latest API version. -var ErrNoNewerVersion = errors.New("input version is not newer than latest API version") - -func reportVersionDir(attestation variant.Variant) string { - return path.Join(AttestationURLPath, attestation.String(), cachedVersionsSubDir) -} - -// UploadSEVSNPVersionLatest saves the given version to the cache, determines the smallest -// TCB version in the cache among the last cacheWindowSize versions and updates -// the latest version in the API if there is an update. -// force can be used to bypass the validation logic against the cached versions. -func (c Client) UploadSEVSNPVersionLatest(ctx context.Context, attestation variant.Variant, inputVersion, - latestAPIVersion SEVSNPVersion, now time.Time, force bool, -) error { - if err := c.cacheSEVSNPVersion(ctx, attestation, inputVersion, now); err != nil { - return fmt.Errorf("reporting version: %w", err) - } - if force { - return c.uploadSEVSNPVersion(ctx, attestation, inputVersion, now) - } - versionDates, err := c.listCachedVersions(ctx, attestation) - if err != nil { - return fmt.Errorf("list reported versions: %w", err) - } - if len(versionDates) < c.cacheWindowSize { - c.s3Client.Logger.Warn(fmt.Sprintf("Skipping version update, found %d, expected %d reported versions.", len(versionDates), c.cacheWindowSize)) - return nil - } - minVersion, minDate, err := c.findMinVersion(ctx, attestation, versionDates) - if err != nil { - return fmt.Errorf("get minimal version: %w", err) - } - c.s3Client.Logger.Info(fmt.Sprintf("Found minimal version: %+v with date: %s", minVersion, minDate)) - shouldUpdateAPI, err := isInputNewerThanOtherVersion(minVersion, latestAPIVersion) - if err != nil { - return ErrNoNewerVersion - } - if !shouldUpdateAPI { - c.s3Client.Logger.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v", minVersion, latestAPIVersion)) - return nil - } - c.s3Client.Logger.Info(fmt.Sprintf("Input version: %+v is newer than latest API version: %+v", minVersion, latestAPIVersion)) - t, err := time.Parse(VersionFormat, minDate) - if err != nil { - return fmt.Errorf("parsing date: %w", err) - } - if err := c.uploadSEVSNPVersion(ctx, attestation, minVersion, t); err != nil { - return fmt.Errorf("uploading version: %w", err) - } - c.s3Client.Logger.Info(fmt.Sprintf("Successfully uploaded new SEV-SNP version: %+v", minVersion)) - return nil -} - -// cacheSEVSNPVersion uploads the latest observed version numbers of the SEVSNP. This version is used to later report the latest version numbers to the API. -func (c Client) cacheSEVSNPVersion(ctx context.Context, attestation variant.Variant, version SEVSNPVersion, date time.Time) error { - dateStr := date.Format(VersionFormat) + ".json" - res := putCmd{ - apiObject: reportedSEVSNPVersionAPI{Version: dateStr, variant: attestation, SEVSNPVersion: version}, - signer: c.signer, - } - return res.Execute(ctx, c.s3Client) -} - -func (c Client) listCachedVersions(ctx context.Context, attestation variant.Variant) ([]string, error) { - list, err := c.s3Client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{ - Bucket: aws.String(c.bucketID), - Prefix: aws.String(reportVersionDir(attestation)), - }) - if err != nil { - return nil, fmt.Errorf("list objects: %w", err) - } - var dates []string - for _, obj := range list.Contents { - fileName := path.Base(*obj.Key) - if strings.HasSuffix(fileName, ".json") { - dates = append(dates, fileName[:len(fileName)-5]) - } - } - return dates, nil -} - -// findMinVersion finds the minimal version of the given version dates among the latest values in the version window size. -func (c Client) findMinVersion(ctx context.Context, attesation variant.Variant, versionDates []string) (SEVSNPVersion, string, error) { - var minimalVersion *SEVSNPVersion - var minimalDate string - sort.Sort(sort.Reverse(sort.StringSlice(versionDates))) // sort in reverse order to slice the latest versions - versionDates = versionDates[:c.cacheWindowSize] - sort.Strings(versionDates) // sort with oldest first to to take the minimal version with the oldest date - for _, date := range versionDates { - obj, err := client.Fetch(ctx, c.s3Client, reportedSEVSNPVersionAPI{Version: date + ".json", variant: attesation}) - if err != nil { - return SEVSNPVersion{}, "", fmt.Errorf("get object: %w", err) - } - // Need to set this explicitly as the variant is not part of the marshalled JSON. - obj.variant = attesation - - if minimalVersion == nil { - minimalVersion = &obj.SEVSNPVersion - minimalDate = date - } else { - shouldUpdateMinimal, err := isInputNewerThanOtherVersion(*minimalVersion, obj.SEVSNPVersion) - if err != nil { - continue - } - if shouldUpdateMinimal { - minimalVersion = &obj.SEVSNPVersion - minimalDate = date - } - } - } - return *minimalVersion, minimalDate, nil -} - -// isInputNewerThanOtherVersion compares all version fields and returns true if any input field is newer. -func isInputNewerThanOtherVersion(input, other SEVSNPVersion) (bool, error) { - if input == other { - return false, nil - } - if input.TEE < other.TEE { - return false, fmt.Errorf("input TEE version: %d is older than latest API version: %d", input.TEE, other.TEE) - } - if input.SNP < other.SNP { - return false, fmt.Errorf("input SNP version: %d is older than latest API version: %d", input.SNP, other.SNP) - } - if input.Microcode < other.Microcode { - return false, fmt.Errorf("input Microcode version: %d is older than latest API version: %d", input.Microcode, other.Microcode) - } - if input.Bootloader < other.Bootloader { - return false, fmt.Errorf("input Bootloader version: %d is older than latest API version: %d", input.Bootloader, other.Bootloader) - } - return true, nil -} - -// reportedSEVSNPVersionAPI is the request to get the version information of the specific version in the config api. -type reportedSEVSNPVersionAPI struct { - Version string `json:"-"` - variant variant.Variant `json:"-"` - SEVSNPVersion -} - -// JSONPath returns the path to the JSON file for the request to the config api. -func (i reportedSEVSNPVersionAPI) JSONPath() string { - return path.Join(reportVersionDir(i.variant), i.Version) -} - -// ValidateRequest validates the request. -func (i reportedSEVSNPVersionAPI) ValidateRequest() error { - if !strings.HasSuffix(i.Version, ".json") { - return fmt.Errorf("version has no .json suffix") - } - return nil -} - -// Validate is a No-Op at the moment. -func (i reportedSEVSNPVersionAPI) Validate() error { - return nil -} diff --git a/internal/api/attestationconfigapi/reporter_test.go b/internal/api/attestationconfigapi/reporter_test.go deleted file mode 100644 index ea37d2d2f..000000000 --- a/internal/api/attestationconfigapi/reporter_test.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright (c) Edgeless Systems GmbH -SPDX-License-Identifier: AGPL-3.0-only -*/ -package attestationconfigapi - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestIsInputNewerThanLatestAPI(t *testing.T) { - newTestCfg := func() SEVSNPVersion { - return SEVSNPVersion{ - Microcode: 93, - TEE: 0, - SNP: 6, - Bootloader: 2, - } - } - - testCases := map[string]struct { - latest SEVSNPVersion - input SEVSNPVersion - expect bool - errMsg string - }{ - "input is older than latest": { - input: func(c SEVSNPVersion) SEVSNPVersion { - c.Microcode-- - return c - }(newTestCfg()), - latest: newTestCfg(), - expect: false, - errMsg: "input Microcode version: 92 is older than latest API version: 93", - }, - "input has greater and smaller version field than latest": { - input: func(c SEVSNPVersion) SEVSNPVersion { - c.Microcode++ - c.Bootloader-- - return c - }(newTestCfg()), - latest: newTestCfg(), - expect: false, - errMsg: "input Bootloader version: 1 is older than latest API version: 2", - }, - "input is newer than latest": { - input: func(c SEVSNPVersion) SEVSNPVersion { - c.TEE++ - return c - }(newTestCfg()), - latest: newTestCfg(), - expect: true, - }, - "input is equal to latest": { - input: newTestCfg(), - latest: newTestCfg(), - expect: false, - }, - } - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - isNewer, err := isInputNewerThanOtherVersion(tc.input, tc.latest) - assert := assert.New(t) - if tc.errMsg != "" { - assert.EqualError(err, tc.errMsg) - } else { - assert.NoError(err) - assert.Equal(tc.expect, isNewer) - } - }) - } -} diff --git a/internal/api/attestationconfigapi/snp.go b/internal/api/attestationconfigapi/snp.go deleted file mode 100644 index a0f92700b..000000000 --- a/internal/api/attestationconfigapi/snp.go +++ /dev/null @@ -1,113 +0,0 @@ -/* -Copyright (c) Edgeless Systems GmbH - -SPDX-License-Identifier: AGPL-3.0-only -*/ - -package attestationconfigapi - -import ( - "encoding/json" - "fmt" - "path" - "sort" - "strings" - - "github.com/edgelesssys/constellation/v2/internal/attestation/variant" -) - -// AttestationURLPath is the URL path to the attestation versions. -const AttestationURLPath = "constellation/v1/attestation" - -// SEVSNPVersion tracks the latest version of each component of the SEVSNP. -type SEVSNPVersion struct { - // Bootloader is the latest version of the SEVSNP bootloader. - Bootloader uint8 `json:"bootloader"` - // TEE is the latest version of the SEVSNP TEE. - TEE uint8 `json:"tee"` - // SNP is the latest version of the SEVSNP SNP. - SNP uint8 `json:"snp"` - // Microcode is the latest version of the SEVSNP microcode. - Microcode uint8 `json:"microcode"` -} - -// SEVSNPVersionAPI is the request to get the version information of the specific version in the config api. -// Because variant is not part of the marshalled JSON, fetcher and client methods need to fill the variant property. -// Once we switch to v2 of the API we should embed the variant in the object. -// That would remove the possibility of some fetcher/client code forgetting to set the variant. -type SEVSNPVersionAPI struct { - Version string `json:"-"` - Variant variant.Variant `json:"-"` - SEVSNPVersion -} - -// JSONPath returns the path to the JSON file for the request to the config api. -func (i SEVSNPVersionAPI) JSONPath() string { - return path.Join(AttestationURLPath, i.Variant.String(), i.Version) -} - -// ValidateRequest validates the request. -func (i SEVSNPVersionAPI) ValidateRequest() error { - if !strings.HasSuffix(i.Version, ".json") { - return fmt.Errorf("version has no .json suffix") - } - return nil -} - -// Validate is a No-Op at the moment. -func (i SEVSNPVersionAPI) Validate() error { - return nil -} - -// SEVSNPVersionList is the request to list all versions in the config api. -// Because variant is not part of the marshalled JSON, fetcher and client methods need to fill the variant property. -// Once we switch to v2 of the API we could embed the variant in the object and remove some code from fetcher & client. -// That would remove the possibility of some fetcher/client code forgetting to set the variant. -type SEVSNPVersionList struct { - variant variant.Variant - list []string -} - -// MarshalJSON marshals the i's list property to JSON. -func (i SEVSNPVersionList) MarshalJSON() ([]byte, error) { - return json.Marshal(i.list) -} - -// UnmarshalJSON unmarshals a list of strings into i's list property. -func (i *SEVSNPVersionList) UnmarshalJSON(data []byte) error { - return json.Unmarshal(data, &i.list) -} - -// List returns i's list property. -func (i SEVSNPVersionList) List() []string { return i.list } - -// JSONPath returns the path to the JSON file for the request to the config api. -func (i SEVSNPVersionList) JSONPath() string { - return path.Join(AttestationURLPath, i.variant.String(), "list") -} - -// ValidateRequest is a NoOp as there is no input. -func (i SEVSNPVersionList) ValidateRequest() error { - return nil -} - -// SortReverse sorts the list of versions in reverse order. -func (i *SEVSNPVersionList) SortReverse() { - sort.Sort(sort.Reverse(sort.StringSlice(i.list))) -} - -// addVersion adds new to i's list and sorts the element in descending order. -func (i *SEVSNPVersionList) addVersion(new string) { - i.list = append(i.list, new) - i.list = variant.RemoveDuplicate(i.list) - - i.SortReverse() -} - -// Validate validates the response. -func (i SEVSNPVersionList) Validate() error { - if len(i.list) < 1 { - return fmt.Errorf("no versions found in /list") - } - return nil -} diff --git a/internal/api/attestationconfigapi/version.go b/internal/api/attestationconfigapi/version.go new file mode 100644 index 000000000..13dd17254 --- /dev/null +++ b/internal/api/attestationconfigapi/version.go @@ -0,0 +1,127 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package attestationconfigapi + +import ( + "encoding/json" + "fmt" + "path" + "sort" + "strings" + + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" +) + +// AttestationURLPath is the URL path to the attestation versions. +const AttestationURLPath = "constellation/v1/attestation" + +// SEVSNPVersion tracks the latest version of each component for SEV-SNP. +type SEVSNPVersion struct { + // Bootloader is the latest version of the SEV-SNP bootloader. + Bootloader uint8 `json:"bootloader"` + // TEE is the latest version of the SEV-SNP TEE. + TEE uint8 `json:"tee"` + // SNP is the latest version of the SEV-SNP SNP. + SNP uint8 `json:"snp"` + // Microcode is the latest version of the SEV-SNP microcode. + Microcode uint8 `json:"microcode"` +} + +// TDXVersion tracks the latest version of each component for TDX. +type TDXVersion struct { + // QESVN is the latest QE security version number. + QESVN uint16 `json:"qeSVN"` + // PCESVN is the latest PCE security version number. + PCESVN uint16 `json:"pceSVN"` + // TEETCBSVN are the latest component-wise security version numbers for the TEE. + TEETCBSVN [16]byte `json:"teeTCBSVN"` + // QEVendorID is the latest QE vendor ID. + QEVendorID [16]byte `json:"qeVendorID"` + // XFAM is the latest XFAM field. + XFAM [8]byte `json:"xfam"` +} + +// Entry is the request to get the version information of the specific version in the config api. +// +// TODO: Because variant is not part of the marshalled JSON, fetcher and client methods need to fill the variant property. +// In API v2 we should embed the variant in the object and remove some code from fetcher & client. +// That would remove the possibility of some fetcher/client code forgetting to set the variant. +type Entry struct { + Version string `json:"-"` + Variant variant.Variant `json:"-"` + SEVSNPVersion + TDXVersion +} + +// JSONPath returns the path to the JSON file for the request to the config api. +func (i Entry) JSONPath() string { + return path.Join(AttestationURLPath, i.Variant.String(), i.Version) +} + +// ValidateRequest validates the request. +func (i Entry) ValidateRequest() error { + if !strings.HasSuffix(i.Version, ".json") { + return fmt.Errorf("version has no .json suffix") + } + return nil +} + +// Validate is a No-Op at the moment. +func (i Entry) Validate() error { + return nil +} + +// List is the request to retrieve of all versions in the API for one attestation variant. +// +// TODO: Because variant is not part of the marshalled JSON, fetcher and client methods need to fill the variant property. +// In API v2 we should embed the variant in the object and remove some code from fetcher & client. +// That would remove the possibility of some fetcher/client code forgetting to set the variant. +type List struct { + Variant variant.Variant + List []string +} + +// MarshalJSON marshals the i's list property to JSON. +func (i List) MarshalJSON() ([]byte, error) { + return json.Marshal(i.List) +} + +// UnmarshalJSON unmarshals a list of strings into i's list property. +func (i *List) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, &i.List) +} + +// JSONPath returns the path to the JSON file for the request to the config api. +func (i List) JSONPath() string { + return path.Join(AttestationURLPath, i.Variant.String(), "list") +} + +// ValidateRequest is a NoOp as there is no input. +func (i List) ValidateRequest() error { + return nil +} + +// SortReverse sorts the list of versions in reverse order. +func (i *List) SortReverse() { + sort.Sort(sort.Reverse(sort.StringSlice(i.List))) +} + +// AddVersion adds new to i's list and sorts the element in descending order. +func (i *List) AddVersion(new string) { + i.List = append(i.List, new) + i.List = variant.RemoveDuplicate(i.List) + + i.SortReverse() +} + +// Validate validates the response. +func (i List) Validate() error { + if len(i.List) < 1 { + return fmt.Errorf("no versions found in /list") + } + return nil +} diff --git a/internal/api/attestationconfigapi/snp_test.go b/internal/api/attestationconfigapi/version_test.go similarity index 61% rename from internal/api/attestationconfigapi/snp_test.go rename to internal/api/attestationconfigapi/version_test.go index 2fe3ea8c9..1e5c51441 100644 --- a/internal/api/attestationconfigapi/snp_test.go +++ b/internal/api/attestationconfigapi/version_test.go @@ -14,23 +14,23 @@ import ( "github.com/stretchr/testify/require" ) -func TestSEVSNPVersionListMarshalUnmarshalJSON(t *testing.T) { +func TestVersionListMarshalUnmarshalJSON(t *testing.T) { tests := map[string]struct { - input SEVSNPVersionList - output SEVSNPVersionList + input List + output List wantDiff bool }{ "success": { - input: SEVSNPVersionList{list: []string{"v1", "v2"}}, - output: SEVSNPVersionList{list: []string{"v1", "v2"}}, + input: List{List: []string{"v1", "v2"}}, + output: List{List: []string{"v1", "v2"}}, }, "variant is lost": { - input: SEVSNPVersionList{list: []string{"v1", "v2"}, variant: variant.AzureSEVSNP{}}, - output: SEVSNPVersionList{list: []string{"v1", "v2"}}, + input: List{List: []string{"v1", "v2"}, Variant: variant.AzureSEVSNP{}}, + output: List{List: []string{"v1", "v2"}}, }, "wrong order": { - input: SEVSNPVersionList{list: []string{"v1", "v2"}}, - output: SEVSNPVersionList{list: []string{"v2", "v1"}}, + input: List{List: []string{"v1", "v2"}}, + output: List{List: []string{"v2", "v1"}}, wantDiff: true, }, } @@ -40,7 +40,7 @@ func TestSEVSNPVersionListMarshalUnmarshalJSON(t *testing.T) { inputRaw, err := tc.input.MarshalJSON() require.NoError(t, err) - var actual SEVSNPVersionList + var actual List err = actual.UnmarshalJSON(inputRaw) require.NoError(t, err) @@ -53,7 +53,7 @@ func TestSEVSNPVersionListMarshalUnmarshalJSON(t *testing.T) { } } -func TestSEVSNPVersionListAddVersion(t *testing.T) { +func TestVersionListAddVersion(t *testing.T) { tests := map[string]struct { versions []string new string @@ -68,10 +68,10 @@ func TestSEVSNPVersionListAddVersion(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { - v := SEVSNPVersionList{list: tc.versions} - v.addVersion(tc.new) + v := List{List: tc.versions} + v.AddVersion(tc.new) - assert.Equal(t, tc.expected, v.list) + assert.Equal(t, tc.expected, v.List) }) } } diff --git a/internal/api/client/client.go b/internal/api/client/client.go index 4929872ed..d3c0a6b75 100644 --- a/internal/api/client/client.go +++ b/internal/api/client/client.go @@ -53,7 +53,7 @@ type Client struct { dirtyPaths []string // written paths to be invalidated DryRun bool // no write operations are performed - Logger *slog.Logger + log *slog.Logger } // NewReadOnlyClient creates a new read-only client. @@ -77,7 +77,7 @@ func NewReadOnlyClient(ctx context.Context, region, bucket, distributionID strin s3ClientClose: staticUploadClientClose, bucket: bucket, DryRun: true, - Logger: log, + log: log, } clientClose := func(ctx context.Context) error { return client.Close(ctx) @@ -106,7 +106,7 @@ func NewClient(ctx context.Context, region, bucket, distributionID string, dryRu s3ClientClose: staticUploadClientClose, bucket: bucket, DryRun: dryRun, - Logger: log, + log: log, } clientClose := func(ctx context.Context) error { return client.Close(ctx) @@ -119,7 +119,7 @@ func NewClient(ctx context.Context, region, bucket, distributionID string, dryRu // It invalidates the CDN cache for all uploaded files. func (c *Client) Close(ctx context.Context) error { if c.s3ClientClose == nil { - c.Logger.Debug("Client has no s3ClientClose") + c.log.Debug("Client has no s3ClientClose") return nil } return c.s3ClientClose(ctx) @@ -131,7 +131,7 @@ func (c *Client) DeletePath(ctx context.Context, path string) error { Bucket: &c.bucket, Prefix: &path, } - c.Logger.Debug(fmt.Sprintf("Listing objects in %q", path)) + c.log.Debug(fmt.Sprintf("Listing objects in %q", path)) objs := []s3types.Object{} out := &s3.ListObjectsV2Output{IsTruncated: ptr(true)} for out.IsTruncated != nil && *out.IsTruncated { @@ -142,10 +142,10 @@ func (c *Client) DeletePath(ctx context.Context, path string) error { } objs = append(objs, out.Contents...) } - c.Logger.Debug(fmt.Sprintf("Found %d objects in %q", len(objs), path)) + c.log.Debug(fmt.Sprintf("Found %d objects in %q", len(objs), path)) if len(objs) == 0 { - c.Logger.Warn(fmt.Sprintf("Path %s is already empty", path)) + c.log.Warn(fmt.Sprintf("Path %s is already empty", path)) return nil } @@ -155,7 +155,7 @@ func (c *Client) DeletePath(ctx context.Context, path string) error { } if c.DryRun { - c.Logger.Debug(fmt.Sprintf("DryRun: Deleting %d objects with IDs %v", len(objs), objIDs)) + c.log.Debug(fmt.Sprintf("DryRun: Deleting %d objects with IDs %v", len(objs), objIDs)) return nil } @@ -167,7 +167,7 @@ func (c *Client) DeletePath(ctx context.Context, path string) error { Objects: objIDs, }, } - c.Logger.Debug(fmt.Sprintf("Deleting %d objects in %q", len(objs), path)) + c.log.Debug(fmt.Sprintf("Deleting %d objects in %q", len(objs), path)) if _, err := c.s3Client.DeleteObjects(ctx, deleteIn); err != nil { return fmt.Errorf("deleting objects in %s: %w", path, err) } @@ -197,7 +197,7 @@ func Fetch[T APIObject](ctx context.Context, c *Client, obj T) (T, error) { Key: ptr(obj.JSONPath()), } - c.Logger.Debug(fmt.Sprintf("Fetching %T from s3: %q", obj, obj.JSONPath())) + c.log.Debug(fmt.Sprintf("Fetching %T from s3: %q", obj, obj.JSONPath())) out, err := c.s3Client.GetObject(ctx, in) var noSuchkey *s3types.NoSuchKey if errors.As(err, &noSuchkey) { @@ -231,7 +231,7 @@ func Update(ctx context.Context, c *Client, obj APIObject) error { } if c.DryRun { - c.Logger.With(slog.String("bucket", c.bucket), slog.String("key", obj.JSONPath()), slog.String("body", string(rawJSON))).Debug("DryRun: s3 put object") + c.log.With(slog.String("bucket", c.bucket), slog.String("key", obj.JSONPath()), slog.String("body", string(rawJSON))).Debug("DryRun: s3 put object") return nil } @@ -243,7 +243,7 @@ func Update(ctx context.Context, c *Client, obj APIObject) error { c.dirtyPaths = append(c.dirtyPaths, "/"+obj.JSONPath()) - c.Logger.Debug(fmt.Sprintf("Uploading %T to s3: %q", obj, obj.JSONPath())) + c.log.Debug(fmt.Sprintf("Uploading %T to s3: %q", obj, obj.JSONPath())) if _, err := c.Upload(ctx, in); err != nil { return fmt.Errorf("uploading %T: %w", obj, err) } @@ -306,7 +306,7 @@ func Delete(ctx context.Context, c *Client, obj APIObject) error { Key: ptr(obj.JSONPath()), } - c.Logger.Debug(fmt.Sprintf("Deleting %T from s3: %q", obj, obj.JSONPath())) + c.log.Debug(fmt.Sprintf("Deleting %T from s3: %q", obj, obj.JSONPath())) if _, err := c.DeleteObject(ctx, in); err != nil { return fmt.Errorf("deleting s3 object at %s: %w", obj.JSONPath(), err) } diff --git a/internal/api/fetcher/fetcher.go b/internal/api/fetcher/fetcher.go index 2b18f9d15..52135aa1f 100644 --- a/internal/api/fetcher/fetcher.go +++ b/internal/api/fetcher/fetcher.go @@ -20,11 +20,10 @@ package fetcher import ( "context" "encoding/json" - "errors" "fmt" + "io" "net/http" "net/url" - "strings" "github.com/edgelesssys/constellation/v2/internal/sigstore" ) @@ -40,45 +39,12 @@ func NewHTTPClient() HTTPClient { // Fetch fetches the given apiObject from the public Constellation CDN. // Fetch does not require authentication. func Fetch[T apiObject](ctx context.Context, c HTTPClient, cdnURL string, obj T) (T, error) { - if err := obj.ValidateRequest(); err != nil { - return *new(T), fmt.Errorf("validating request for %T: %w", obj, err) - } - - urlObj, err := url.Parse(cdnURL) + rawObj, err := fetch(ctx, c, cdnURL, obj) if err != nil { - return *new(T), fmt.Errorf("parsing CDN root URL: %w", err) - } - urlObj.Path = obj.JSONPath() - url := urlObj.String() - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody) - if err != nil { - return *new(T), fmt.Errorf("creating request for %T: %w", obj, err) + return *new(T), fmt.Errorf("fetching %T: %w", obj, err) } - resp, err := c.Do(req) - if err != nil { - return *new(T), fmt.Errorf("sending request for %T: %w", obj, err) - } - defer resp.Body.Close() - switch resp.StatusCode { - case http.StatusOK: - case http.StatusNotFound: - return *new(T), &NotFoundError{fmt.Errorf("requesting resource at %s returned status code 404", url)} - default: - return *new(T), fmt.Errorf("unexpected status code %d while requesting resource", resp.StatusCode) - } - - var newObj T - if err := json.NewDecoder(resp.Body).Decode(&newObj); err != nil { - return *new(T), fmt.Errorf("decoding %T: %w", obj, err) - } - - if newObj.Validate() != nil { - return *new(T), fmt.Errorf("received invalid %T: %w", newObj, newObj.Validate()) - } - - return newObj, nil + return parseObject(rawObj, obj) } // FetchAndVerify fetches the given apiObject, checks if it can fetch an accompanying signature and verifies if the signature matches the found object. @@ -86,25 +52,70 @@ func Fetch[T apiObject](ctx context.Context, c HTTPClient, cdnURL string, obj T) // FetchAndVerify uses a generic to return a new object of type T. // Otherwise the caller would have to cast the interface type to a concrete object, which could fail. func FetchAndVerify[T apiObject](ctx context.Context, c HTTPClient, cdnURL string, obj T, cosignVerifier sigstore.Verifier) (T, error) { - fetchedObj, err := Fetch(ctx, c, cdnURL, obj) + rawObj, err := fetch(ctx, c, cdnURL, obj) if err != nil { - return fetchedObj, fmt.Errorf("fetching object: %w", err) + return *new(T), fmt.Errorf("fetching %T: %w", obj, err) } - marshalledObj, err := json.Marshal(fetchedObj) + fetchedObj, err := parseObject(rawObj, obj) if err != nil { - return fetchedObj, fmt.Errorf("marshalling object: %w", err) + return fetchedObj, fmt.Errorf("parsing %T: %w", obj, err) } + signature, err := Fetch(ctx, c, cdnURL, signature{Signed: obj.JSONPath()}) if err != nil { return fetchedObj, fmt.Errorf("fetching signature: %w", err) } - err = cosignVerifier.VerifySignature(marshalledObj, signature.Signature) + err = cosignVerifier.VerifySignature(rawObj, signature.Signature) if err != nil { return fetchedObj, fmt.Errorf("verifying signature: %w", err) } return fetchedObj, nil } +func fetch[T apiObject](ctx context.Context, c HTTPClient, cdnURL string, obj T) ([]byte, error) { + if err := obj.ValidateRequest(); err != nil { + return nil, fmt.Errorf("validating request for %T: %w", obj, err) + } + + urlObj, err := url.Parse(cdnURL) + if err != nil { + return nil, fmt.Errorf("parsing CDN root URL: %w", err) + } + urlObj.Path = obj.JSONPath() + url := urlObj.String() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody) + if err != nil { + return nil, fmt.Errorf("creating request for %T: %w", obj, err) + } + + resp, err := c.Do(req) + if err != nil { + return nil, fmt.Errorf("sending request for %T: %w", obj, err) + } + defer resp.Body.Close() + switch resp.StatusCode { + case http.StatusOK: + case http.StatusNotFound: + return nil, &NotFoundError{fmt.Errorf("requesting resource at %s returned status code 404", url)} + default: + return nil, fmt.Errorf("unexpected status code %d while requesting resource", resp.StatusCode) + } + + return io.ReadAll(resp.Body) +} + +func parseObject[T apiObject](rawObj []byte, obj T) (T, error) { + var newObj T + if err := json.Unmarshal(rawObj, &newObj); err != nil { + return *new(T), fmt.Errorf("decoding %T: %w", obj, err) + } + if newObj.Validate() != nil { + return *new(T), fmt.Errorf("received invalid %T: %w", newObj, newObj.Validate()) + } + return newObj, nil +} + // NotFoundError is an error that is returned when a resource is not found. type NotFoundError struct { err error @@ -132,7 +143,7 @@ type apiObject interface { // signature manages the signature of a object saved at location 'Signed'. type signature struct { // Signed is the object that is signed. - Signed string `json:"-"` + Signed string `json:"signed"` // Signature is the signature of `Signed`. Signature []byte `json:"signature"` } @@ -142,12 +153,8 @@ func (s signature) JSONPath() string { return s.Signed + ".sig" } -// ValidateRequest validates the request. +// ValidateRequest is a no-op. func (s signature) ValidateRequest() error { - if !strings.HasSuffix(s.Signed, ".json") { - return errors.New("signed object missing .json suffix") - } - return nil } diff --git a/internal/api/versionsapi/cli/BUILD.bazel b/internal/api/versionsapi/cli/BUILD.bazel index 411c68f38..cc720acb4 100644 --- a/internal/api/versionsapi/cli/BUILD.bazel +++ b/internal/api/versionsapi/cli/BUILD.bazel @@ -21,7 +21,7 @@ go_library( "@com_github_aws_smithy_go//:smithy-go", "@com_github_azure_azure_sdk_for_go_sdk_azcore//runtime", "@com_github_azure_azure_sdk_for_go_sdk_azidentity//:azidentity", - "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v5//:armcompute", + "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v6//:armcompute", "@com_github_googleapis_gax_go_v2//:gax-go", "@com_github_spf13_cobra//:cobra", "@com_google_cloud_go_compute//apiv1", diff --git a/internal/api/versionsapi/cli/rm.go b/internal/api/versionsapi/cli/rm.go index b5e90bb58..d25ff59a1 100644 --- a/internal/api/versionsapi/cli/rm.go +++ b/internal/api/versionsapi/cli/rm.go @@ -21,7 +21,7 @@ import ( "cloud.google.com/go/compute/apiv1/computepb" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - armcomputev5 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + armcomputev5 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" awsconfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/aws/smithy-go" diff --git a/internal/api/versionsapi/client.go b/internal/api/versionsapi/client.go index 5d14fdacd..496557102 100644 --- a/internal/api/versionsapi/client.go +++ b/internal/api/versionsapi/client.go @@ -23,6 +23,8 @@ import ( type Client struct { *apiclient.Client clientClose func(ctx context.Context) error + + log *slog.Logger } // NewClient creates a new client for the versions API. @@ -31,8 +33,9 @@ func NewClient(ctx context.Context, region, bucket, distributionID string, dryRu ) (*Client, CloseFunc, error) { genericClient, genericClientClose, err := apiclient.NewClient(ctx, region, bucket, distributionID, dryRun, log) versionsClient := &Client{ - genericClient, - genericClientClose, + Client: genericClient, + clientClose: genericClientClose, + log: log, } versionsClientClose := func(ctx context.Context) error { return versionsClient.Close(ctx) @@ -50,8 +53,9 @@ func NewReadOnlyClient(ctx context.Context, region, bucket, distributionID strin return nil, nil, err } versionsClient := &Client{ - genericClient, - genericClientClose, + Client: genericClient, + clientClose: genericClientClose, + log: log, } versionsClientClose := func(ctx context.Context) error { return versionsClient.Close(ctx) @@ -131,18 +135,18 @@ func (c *Client) DeleteRef(ctx context.Context, ref string) error { func (c *Client) DeleteVersion(ctx context.Context, ver Version) error { var retErr error - c.Client.Logger.Debug(fmt.Sprintf("Deleting version %q from minor version list", ver.version)) + c.log.Debug(fmt.Sprintf("Deleting version %q from minor version list", ver.version)) possibleNewLatest, err := c.deleteVersionFromMinorVersionList(ctx, ver) if err != nil { retErr = errors.Join(retErr, fmt.Errorf("removing from minor version list: %w", err)) } - c.Client.Logger.Debug(fmt.Sprintf("Checking latest version for %q", ver.version)) + c.log.Debug(fmt.Sprintf("Checking latest version for %q", ver.version)) if err := c.deleteVersionFromLatest(ctx, ver, possibleNewLatest); err != nil { retErr = errors.Join(retErr, fmt.Errorf("updating latest version: %w", err)) } - c.Client.Logger.Debug(fmt.Sprintf("Deleting artifact path %q for %q", ver.ArtifactPath(APIV1), ver.version)) + c.log.Debug(fmt.Sprintf("Deleting artifact path %q for %q", ver.ArtifactPath(APIV1), ver.version)) if err := c.Client.DeletePath(ctx, ver.ArtifactPath(APIV1)); err != nil { retErr = errors.Join(retErr, fmt.Errorf("deleting artifact path: %w", err)) } @@ -159,20 +163,20 @@ func (c *Client) deleteVersionFromMinorVersionList(ctx context.Context, ver Vers Base: ver.WithGranularity(GranularityMinor), Kind: VersionKindImage, } - c.Client.Logger.Debug(fmt.Sprintf("Fetching minor version list for version %q", ver.version)) + c.log.Debug(fmt.Sprintf("Fetching minor version list for version %q", ver.version)) minorList, err := c.FetchVersionList(ctx, minorList) var notFoundErr *apiclient.NotFoundError if errors.As(err, ¬FoundErr) { - c.Client.Logger.Warn(fmt.Sprintf("Minor version list for version %s not found", ver.version)) - c.Client.Logger.Warn("Skipping update of minor version list") + c.log.Warn(fmt.Sprintf("Minor version list for version %s not found", ver.version)) + c.log.Warn("Skipping update of minor version list") return nil, nil } else if err != nil { return nil, fmt.Errorf("fetching minor version list for version %s: %w", ver.version, err) } if !minorList.Contains(ver.version) { - c.Client.Logger.Warn(fmt.Sprintf("Version %s is not in minor version list %s", ver.version, minorList.JSONPath())) - c.Client.Logger.Warn("Skipping update of minor version list") + c.log.Warn(fmt.Sprintf("Version %s is not in minor version list %s", ver.version, minorList.JSONPath())) + c.log.Warn("Skipping update of minor version list") return nil, nil } @@ -192,20 +196,20 @@ func (c *Client) deleteVersionFromMinorVersionList(ctx context.Context, ver Vers Kind: VersionKindImage, Version: minorList.Versions[len(minorList.Versions)-1], } - c.Client.Logger.Debug(fmt.Sprintf("Possible latest version replacement %q", latest.Version)) + c.log.Debug(fmt.Sprintf("Possible latest version replacement %q", latest.Version)) } if c.Client.DryRun { - c.Client.Logger.Debug(fmt.Sprintf("DryRun: Updating minor version list %q to %v", minorList.JSONPath(), minorList)) + c.log.Debug(fmt.Sprintf("DryRun: Updating minor version list %q to %v", minorList.JSONPath(), minorList)) return latest, nil } - c.Client.Logger.Debug(fmt.Sprintf("Updating minor version list %q", minorList.JSONPath())) + c.log.Debug(fmt.Sprintf("Updating minor version list %q", minorList.JSONPath())) if err := c.UpdateVersionList(ctx, minorList); err != nil { return latest, fmt.Errorf("updating minor version list %s: %w", minorList.JSONPath(), err) } - c.Client.Logger.Debug(fmt.Sprintf("Removed version %q from minor version list %q", ver.version, minorList.JSONPath())) + c.log.Debug(fmt.Sprintf("Removed version %q from minor version list %q", ver.version, minorList.JSONPath())) return latest, nil } @@ -216,33 +220,33 @@ func (c *Client) deleteVersionFromLatest(ctx context.Context, ver Version, possi Stream: ver.stream, Kind: VersionKindImage, } - c.Client.Logger.Debug(fmt.Sprintf("Fetching latest version from %q", latest.JSONPath())) + c.log.Debug(fmt.Sprintf("Fetching latest version from %q", latest.JSONPath())) latest, err := c.FetchVersionLatest(ctx, latest) var notFoundErr *apiclient.NotFoundError if errors.As(err, ¬FoundErr) { - c.Client.Logger.Warn(fmt.Sprintf("Latest version for %s not found", latest.JSONPath())) + c.log.Warn(fmt.Sprintf("Latest version for %s not found", latest.JSONPath())) return nil } else if err != nil { return fmt.Errorf("fetching latest version: %w", err) } if latest.Version != ver.version { - c.Client.Logger.Debug(fmt.Sprintf("Latest version is %q, not the deleted version %q", latest.Version, ver.version)) + c.log.Debug(fmt.Sprintf("Latest version is %q, not the deleted version %q", latest.Version, ver.version)) return nil } if possibleNewLatest == nil { - c.Client.Logger.Error(fmt.Sprintf("Latest version is %s, but no new latest version was found", latest.Version)) - c.Client.Logger.Error(fmt.Sprintf("A manual update of latest at %s might be needed", latest.JSONPath())) + c.log.Error(fmt.Sprintf("Latest version is %s, but no new latest version was found", latest.Version)) + c.log.Error(fmt.Sprintf("A manual update of latest at %s might be needed", latest.JSONPath())) return fmt.Errorf("latest version is %s, but no new latest version was found", latest.Version) } if c.Client.DryRun { - c.Client.Logger.Debug(fmt.Sprintf("Would update latest version from %q to %q", latest.Version, possibleNewLatest.Version)) + c.log.Debug(fmt.Sprintf("Would update latest version from %q to %q", latest.Version, possibleNewLatest.Version)) return nil } - c.Client.Logger.Info(fmt.Sprintf("Updating latest version from %s to %s", latest.Version, possibleNewLatest.Version)) + c.log.Info(fmt.Sprintf("Updating latest version from %s to %s", latest.Version, possibleNewLatest.Version)) if err := c.UpdateVersionLatest(ctx, *possibleNewLatest); err != nil { return fmt.Errorf("updating latest version: %w", err) } diff --git a/internal/atls/atls.go b/internal/atls/atls.go index 1fff52d17..34a80bbff 100644 --- a/internal/atls/atls.go +++ b/internal/atls/atls.go @@ -70,6 +70,7 @@ func CreateAttestationClientTLSConfig(issuer Issuer, validators []Validator) (*t InsecureSkipVerify: true, // disable default verification because we use our own verify func ServerName: base64.StdEncoding.EncodeToString(clientNonce), // abuse ServerName as a channel to transmit the nonce MinVersion: tls.VersionTLS12, + NextProtos: []string{"http/1.1", "h2"}, // grpc-go requires us to advertise HTTP/2 (h2) over ALPN }, nil } @@ -114,6 +115,7 @@ func getATLSConfigForClientFunc(issuer Issuer, validators []Validator) (func(*tl VerifyPeerCertificate: serverConn.verify, GetCertificate: serverConn.getCertificate, MinVersion: tls.VersionTLS12, + NextProtos: []string{"http/1.1", "h2"}, // grpc-go requires us to advertise HTTP/2 (h2) over ALPN } // enable mutual aTLS if any validators are set diff --git a/internal/attestation/aws/snp/testdata/report.txt b/internal/attestation/aws/snp/testdata/report.txt index efd90375f..a5ed00a9b 100644 --- a/internal/attestation/aws/snp/testdata/report.txt +++ b/internal/attestation/aws/snp/testdata/report.txt @@ -1 +1 @@ -AgAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAAAAAK0QMAAAAAAAAABAAAAAAAAAADJjVhPI4zH6KeCWNxkQ/mofaTg92gLJRhQApwtm2Ho9pd2GMAJSK+Q6/DTywjOYm9bkAeNR0Q18yADW9d/PAZJayBD1xHUIkPsaFY8JeWLgTU1/tkDR0IqZgpz0pwVDpHzG+xkrvpCqcTFCNhpmFVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOsAob9aWVVnjx8VNbU/bqGewnLGnBSZbJu8smGfzcN///////////////////////////////////////////AwAAAAAACnMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAACqkBNgEAATYBAAMAAAAAAAqpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAm8z1/Oxcd+Bhdxd1okDoZ9gMiYw5Y/fp74hylcA2Eu+XPt5p+7fqqG7d7YLdJtTuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIOZBrwmRpIFfKDCywiFaiILyguTq/6vefDmdzNBKiRKtjdNiHa0hNgeQFGHspRcZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AgAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAAAAAW1QMAAAAAAAAABAAAAAAAAAADJjVhPI4zH6KeCWNxkQ/mofaTg92gLJRhQApwtm2Ho9pd2GMAJSK+Q6/DTywjOYm9bkAeNR0Q18yADW9d/PAZ8amfwHRwvrA7EzD0SJUgr48CiBh/+2YccfNcqwm+oZzZYtTy0J9aFsPDi32mvtJEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKGpDGe5jVOEMlqVJrJXkLPExDcn4NNEkTnWyr1bpRyf//////////////////////////////////////////AwAAAAAAFdEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAFdMUNwEAEjcBAAMAAAAAABXTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdtzdhdRVgTlqcv/jK6JowumHvC2VvXiZ9Zpf150hAG4Y4Zc/ypAlPoORo0uIcxPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATMdpGsLZn99jRGCI3eaEGkcNMvDnJVcVSviZtDTMpNjydn/F1cE2AKOFqCZQ4HnZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= diff --git a/internal/attestation/aws/snp/testdata/vlek.pem b/internal/attestation/aws/snp/testdata/vlek.pem index 406a84235..96a1db26d 100644 --- a/internal/attestation/aws/snp/testdata/vlek.pem +++ b/internal/attestation/aws/snp/testdata/vlek.pem @@ -1,30 +1,30 @@ -----BEGIN CERTIFICATE----- -MIIFLDCCAtugAwIBAgIBADBGBgkqhkiG9w0BAQowOaAPMA0GCWCGSAFlAwQCAgUA +MIIFLTCCAtygAwIBAgIBADBGBgkqhkiG9w0BAQowOaAPMA0GCWCGSAFlAwQCAgUA oRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAgUAogMCATCjAwIBATCBgDEUMBIG A1UECwwLRW5naW5lZXJpbmcxCzAJBgNVBAYTAlVTMRQwEgYDVQQHDAtTYW50YSBD bGFyYTELMAkGA1UECAwCQ0ExHzAdBgNVBAoMFkFkdmFuY2VkIE1pY3JvIERldmlj -ZXMxFzAVBgNVBAMMDlNFVi1WTEVLLU1pbGFuMB4XDTIzMDcxOTA4MjkyOFoXDTI0 -MDcxOTA4MjkyOFowejEUMBIGA1UECwwLRW5naW5lZXJpbmcxCzAJBgNVBAYTAlVT +ZXMxFzAVBgNVBAMMDlNFVi1WTEVLLU1pbGFuMB4XDTI0MDUwNTIxNDUyNloXDTI1 +MDUwNTIxNDUyNlowejEUMBIGA1UECwwLRW5naW5lZXJpbmcxCzAJBgNVBAYTAlVT MRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExHzAdBgNVBAoMFkFk dmFuY2VkIE1pY3JvIERldmljZXMxETAPBgNVBAMMCFNFVi1WTEVLMHYwEAYHKoZI -zj0CAQYFK4EEACIDYgAEXFl4NHpiQCuZXIrehIEk/5XNIdMvo24wyaezN+0FouYB -9Z23nL523gpJUlT+mvb5ZMybh5tO1nBGFMOKwzP9dnSBwTs0qn57Ts9OTpW57EAo -Mx4SI7g1yz/mt4e6hma4o4HxMIHuMBAGCSsGAQQBnHgBAQQDAgEAMBQGCSsGAQQB +zj0CAQYFK4EEACIDYgAEHCsA6v0QwdgijkHV1KnV+1wMqjVaITbdleQV40cnL6ZT +Pq3IsXeFGI9tq2a2EoDksTTqeo5a1ZDq2BiNA2cue0PlZhHkv2MK1cNPMDGAOddc +k7VNaqrRLUo84kn6tRXpo4HyMIHvMBAGCSsGAQQBnHgBAQQDAgEAMBQGCSsGAQQB nHgBAgQHFgVNaWxhbjARBgorBgEEAZx4AQMBBAMCAQMwEQYKKwYBBAGceAEDAgQD AgEAMBEGCisGAQQBnHgBAwQEAwIBADARBgorBgEEAZx4AQMFBAMCAQAwEQYKKwYB BAGceAEDBgQDAgEAMBEGCisGAQQBnHgBAwcEAwIBADARBgorBgEEAZx4AQMDBAMC -AQowEQYKKwYBBAGceAEDCAQDAgFzMCwGCSsGAQQBnHgBBQQfFh1DTj1jYy11cy1l -YXN0LTIuYW1hem9uYXdzLmNvbTBGBgkqhkiG9w0BAQowOaAPMA0GCWCGSAFlAwQC -AgUAoRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAgUAogMCATCjAwIBAQOCAgEA -E2CR10QkVTofcjmQbuu787J+H+OjzQLPIi/dUbP/LvZdYi/eWglYQPRbYxhxnIi1 -PB9R9c7LLhbNRhroog+TzrxyKLibEAW3rwn2iygPnsIemyL89wqtPNqEKNjhBXsb -s/0bmf0rNJ3lugssCAzrIStkx8at0K/099BEs4FuUM5u97HVy+jqLdRa2XOHMgGa -K7sNdR4swuLhfts9gOOX8ntJ+XkxtUx2mz449fXn8KN70mKa2YShhNd2JWJmv1jW -K0I1UxVVwIOHBn/W8fQL5a061oRQQaW5+wPRTys0iEMmLU7+plC8LNWeEq93TfFY -eUZ9EzinZ5S7z+c8J1FVWYNHGJauWj4lkjf+XGUZqXwTCPzou6tYJqqwWQEUUxXC -M3QKgbkIGWg4WKHIAXGChbM86JLY0W6VueOHyu4S1Z4i81IcDp4cs83WxYWfCpKH -Fq3Si2BhzZ0YGgK25JCkomh5Yf7dlsByyuQssf3TCqNmOfSFOTLvxfwTvLD5Omlm -O1mPI0YaoZya4WcPxbpWS+2Em23/5inQvT+ZhvMNkljD2NVbhLVGP1v4YR+T2zaC -0qJ4YYJ2ERQTnEUlKnlF9bm6PwZSRHupK6ecsGjH+Bz5hBPbT09nEpJf0bWkzVSA -AY8POFt3zBJiqONQuOlBpXzqKRKvFYQVEaX2EXQ+W6s= +ARUwEgYKKwYBBAGceAEDCAQEAgIA0TAsBgkrBgEEAZx4AQUEHxYdQ049Y2MtZXUt +d2VzdC0xLmFtYXpvbmF3cy5jb20wRgYJKoZIhvcNAQEKMDmgDzANBglghkgBZQME +AgIFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgIFAKIDAgEwowMCAQEDggIB +ACeJ78s9Nrdz+WtvsNAecT7+ztE8jpxLZdgacsPtf3xU/JfcQHhVUuy/Lp5rIQ7B +h1HalTrmuY7goRO1kTp/lobXyntWkit0d5nR6iNjzp/uHr8+qEym2WbYX1Jesang +BQX06XxXTmEphrHElTrp8BovYIsPejdY2nNUYV6fhrdTXEh+qLDGQmwjK12FG+hu +4AS+rev2V7H9uE1XKXsM4TTqvI1hT3E2ocN4KjfUBi7yL/BF97kXfdqZH48pPD4y +i7TbZ7S89UikrAv0ZtgGyXY8yR094YVjfbnUvyYTyh4fgV8a8Mxsb4yhPoOOxkUI +8tNBhM4LkTPkR/4+Y2Dg6maglZJ5Hb2WWWNkd0CZchZC80T7HIgHztINMnHULiYi +sNRtKeUAqUNtwy0d2YehX+v9HzueTfKtvxIy2oBfT1LCykvTQTibE3aCvFMkEiw8 +4CunpWfPAoZEzzJUTxLQ6PkdE4MVRTTuuOAVHTrtkIUOB6tlkgMzijqAdwzTDdIj +NGQxTm0Vd2h+zvZl2HnSCi6PMoZml5RwZHiZXKRC90bPn0Vk1XlYW1wMEFHTWQqo +tFH44eWyGIoTwSqcqATR/HklCoUP0wMe2sSsMemJMPwAXWW4fZxmee72OR4p6c+w +TGzR0J5WFdJ0g2Ix+NobBydNaJnQz4H5Y+/gZFUCRrWh -----END CERTIFICATE----- diff --git a/internal/attestation/azure/tdx/issuer.go b/internal/attestation/azure/tdx/issuer.go index e04b066a6..082616635 100644 --- a/internal/attestation/azure/tdx/issuer.go +++ b/internal/attestation/azure/tdx/issuer.go @@ -90,7 +90,7 @@ func (i *Issuer) getInstanceInfo(ctx context.Context, tpm io.ReadWriteCloser, _ return nil, fmt.Errorf("getting quote: %w", err) } - instanceInfo := instanceInfo{ + instanceInfo := InstanceInfo{ AttestationReport: quote, RuntimeData: runtimeData, } diff --git a/internal/attestation/azure/tdx/tdx.go b/internal/attestation/azure/tdx/tdx.go index 815a43ae2..eaee6161a 100644 --- a/internal/attestation/azure/tdx/tdx.go +++ b/internal/attestation/azure/tdx/tdx.go @@ -19,7 +19,8 @@ More specifically: */ package tdx -type instanceInfo struct { +// InstanceInfo wraps the TDX report with additional Azure specific runtime data. +type InstanceInfo struct { AttestationReport []byte RuntimeData []byte } diff --git a/internal/attestation/azure/tdx/validator.go b/internal/attestation/azure/tdx/validator.go index da8dc0eee..6a496f2bb 100644 --- a/internal/attestation/azure/tdx/validator.go +++ b/internal/attestation/azure/tdx/validator.go @@ -58,7 +58,7 @@ func NewValidator(cfg *config.AzureTDX, log attestation.Logger) *Validator { } func (v *Validator) getTrustedTPMKey(_ context.Context, attDoc vtpm.AttestationDocument, _ []byte) (crypto.PublicKey, error) { - var instanceInfo instanceInfo + var instanceInfo InstanceInfo if err := json.Unmarshal(attDoc.InstanceInfo, &instanceInfo); err != nil { return nil, err } @@ -93,25 +93,24 @@ func (v *Validator) validateQuote(tdxQuote *tdx.QuoteV4) error { roots.AddCert((*x509.Certificate)(&v.cfg.IntelRootKey)) if err := verify.TdxQuote(tdxQuote, &verify.Options{ - // TODO: Re-enable CRL checking once issues on Azure's side are resolved. - // CheckRevocations: true, - // GetCollateral: true, - TrustedRoots: roots, - Getter: v.getter, + CheckRevocations: true, + GetCollateral: true, + TrustedRoots: roots, + Getter: v.getter, }); err != nil { return err } if err := validate.TdxQuote(tdxQuote, &validate.Options{ HeaderOptions: validate.HeaderOptions{ - MinimumQeSvn: v.cfg.QESVN, - MinimumPceSvn: v.cfg.PCESVN, - QeVendorID: v.cfg.QEVendorID, + MinimumQeSvn: v.cfg.QESVN.Value, + MinimumPceSvn: v.cfg.PCESVN.Value, + QeVendorID: v.cfg.QEVendorID.Value, }, TdQuoteBodyOptions: validate.TdQuoteBodyOptions{ - MinimumTeeTcbSvn: v.cfg.TEETCBSVN, + MinimumTeeTcbSvn: v.cfg.TEETCBSVN.Value, MrSeam: v.cfg.MRSeam, - Xfam: v.cfg.XFAM, + Xfam: v.cfg.XFAM.Value, }, }); err != nil { return err diff --git a/internal/attestation/gcp/es/issuer_test.go b/internal/attestation/gcp/es/issuer_test.go index 483662855..d8d0075de 100644 --- a/internal/attestation/gcp/es/issuer_test.go +++ b/internal/attestation/gcp/es/issuer_test.go @@ -91,14 +91,14 @@ type fakeMetadataClient struct { zoneErr error } -func (c fakeMetadataClient) ProjectID() (string, error) { +func (c fakeMetadataClient) ProjectID(_ context.Context) (string, error) { return c.projectIDString, c.projecIDErr } -func (c fakeMetadataClient) InstanceName() (string, error) { +func (c fakeMetadataClient) InstanceName(_ context.Context) (string, error) { return c.instanceNameString, c.instanceNameErr } -func (c fakeMetadataClient) Zone() (string, error) { +func (c fakeMetadataClient) Zone(_ context.Context) (string, error) { return c.zoneString, c.zoneErr } diff --git a/internal/attestation/gcp/metadata.go b/internal/attestation/gcp/metadata.go index 5fdd7046b..471eceb99 100644 --- a/internal/attestation/gcp/metadata.go +++ b/internal/attestation/gcp/metadata.go @@ -21,17 +21,17 @@ func GCEInstanceInfo(client gcpMetadataClient) func(context.Context, io.ReadWrit // Ideally we would want to use the endorsement public key certificate // However, this is not available on GCE instances // Workaround: Provide ShieldedVM instance info - // The attestating party can request the VMs signing key using Google's API - return func(context.Context, io.ReadWriteCloser, []byte) ([]byte, error) { - projectID, err := client.ProjectID() + // The attesting party can request the VMs signing key using Google's API + return func(ctx context.Context, _ io.ReadWriteCloser, _ []byte) ([]byte, error) { + projectID, err := client.ProjectID(ctx) if err != nil { return nil, errors.New("unable to fetch projectID") } - zone, err := client.Zone() + zone, err := client.Zone(ctx) if err != nil { return nil, errors.New("unable to fetch zone") } - instanceName, err := client.InstanceName() + instanceName, err := client.InstanceName(ctx) if err != nil { return nil, errors.New("unable to fetch instance name") } @@ -45,25 +45,25 @@ func GCEInstanceInfo(client gcpMetadataClient) func(context.Context, io.ReadWrit } type gcpMetadataClient interface { - ProjectID() (string, error) - InstanceName() (string, error) - Zone() (string, error) + ProjectID(context.Context) (string, error) + InstanceName(context.Context) (string, error) + Zone(context.Context) (string, error) } // A MetadataClient fetches metadata from the GCE Metadata API. type MetadataClient struct{} // ProjectID returns the project ID of the GCE instance. -func (c MetadataClient) ProjectID() (string, error) { - return metadata.ProjectID() +func (c MetadataClient) ProjectID(ctx context.Context) (string, error) { + return metadata.ProjectIDWithContext(ctx) } // InstanceName returns the instance name of the GCE instance. -func (c MetadataClient) InstanceName() (string, error) { - return metadata.InstanceName() +func (c MetadataClient) InstanceName(ctx context.Context) (string, error) { + return metadata.InstanceNameWithContext(ctx) } // Zone returns the zone the GCE instance is located in. -func (c MetadataClient) Zone() (string, error) { - return metadata.Zone() +func (c MetadataClient) Zone(ctx context.Context) (string, error) { + return metadata.ZoneWithContext(ctx) } diff --git a/internal/attestation/gcp/snp/issuer.go b/internal/attestation/gcp/snp/issuer.go index ff5b2fd16..215b21c8d 100644 --- a/internal/attestation/gcp/snp/issuer.go +++ b/internal/attestation/gcp/snp/issuer.go @@ -57,7 +57,7 @@ func getAttestationKey(tpm io.ReadWriter) (*tpmclient.Key, error) { // getInstanceInfo generates an extended SNP report, i.e. the report and any loaded certificates. // Report generation is triggered by sending ioctl syscalls to the SNP guest device, the AMD PSP generates the report. // The returned bytes will be written into the attestation document. -func getInstanceInfo(_ context.Context, _ io.ReadWriteCloser, extraData []byte) ([]byte, error) { +func getInstanceInfo(ctx context.Context, _ io.ReadWriteCloser, extraData []byte) ([]byte, error) { if len(extraData) > 64 { return nil, fmt.Errorf("extra data too long: %d, should be 64 bytes at most", len(extraData)) } @@ -74,7 +74,7 @@ func getInstanceInfo(_ context.Context, _ io.ReadWriteCloser, extraData []byte) return nil, fmt.Errorf("parsing vcek: %w", err) } - gceInstanceInfo, err := gceInstanceInfo() + gceInstanceInfo, err := gceInstanceInfo(ctx) if err != nil { return nil, fmt.Errorf("getting GCE instance info: %w", err) } @@ -93,20 +93,20 @@ func getInstanceInfo(_ context.Context, _ io.ReadWriteCloser, extraData []byte) } // gceInstanceInfo returns the instance info for a GCE instance from the metadata API. -func gceInstanceInfo() (*attest.GCEInstanceInfo, error) { +func gceInstanceInfo(ctx context.Context) (*attest.GCEInstanceInfo, error) { c := gcp.MetadataClient{} - instanceName, err := c.InstanceName() + instanceName, err := c.InstanceName(ctx) if err != nil { return nil, fmt.Errorf("getting instance name: %w", err) } - projectID, err := c.ProjectID() + projectID, err := c.ProjectID(ctx) if err != nil { return nil, fmt.Errorf("getting project ID: %w", err) } - zone, err := c.Zone() + zone, err := c.Zone(ctx) if err != nil { return nil, fmt.Errorf("getting zone: %w", err) } diff --git a/internal/attestation/measurements/measurements_enterprise.go b/internal/attestation/measurements/measurements_enterprise.go index 5e1f43510..ba732512d 100644 --- a/internal/attestation/measurements/measurements_enterprise.go +++ b/internal/attestation/measurements/measurements_enterprise.go @@ -19,14 +19,14 @@ package measurements // revive:disable:var-naming var ( - aws_AWSNitroTPM = M{0: {Expected: []byte{0x73, 0x7f, 0x76, 0x7a, 0x12, 0xf5, 0x4e, 0x70, 0xee, 0xcb, 0xc8, 0x68, 0x40, 0x11, 0x32, 0x3a, 0xe2, 0xfe, 0x2d, 0xd9, 0xf9, 0x07, 0x85, 0x57, 0x79, 0x69, 0xd7, 0xa2, 0x01, 0x3e, 0x8c, 0x12}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0x31, 0x46, 0x1d, 0x3a, 0xe0, 0x2c, 0x58, 0xff, 0x6d, 0x8a, 0x2c, 0x68, 0x18, 0x52, 0x01, 0xf5, 0x4d, 0x98, 0x7f, 0x1c, 0xbc, 0x95, 0x96, 0xc3, 0x70, 0xc7, 0xad, 0xbd, 0x12, 0x3d, 0x2c, 0x8d}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x41, 0xaa, 0x16, 0x69, 0xaa, 0xdf, 0xc9, 0x2c, 0xc7, 0x3b, 0x4e, 0x00, 0xf3, 0x15, 0x4e, 0xb7, 0x5c, 0x13, 0x80, 0x92, 0x03, 0x76, 0xe4, 0x4f, 0xdf, 0x7a, 0x06, 0x82, 0xac, 0x68, 0x07, 0x3e}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xd3, 0x75, 0x20, 0x27, 0x8f, 0x9f, 0x8e, 0x92, 0xd4, 0x25, 0xed, 0xbd, 0x5a, 0x9f, 0x6a, 0xec, 0xea, 0xee, 0xf3, 0xc6, 0xb6, 0xa9, 0x53, 0x93, 0x60, 0xe9, 0x7c, 0x12, 0xda, 0x8b, 0x5c, 0xcf}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} - aws_AWSSEVSNP = M{0: {Expected: []byte{0x7b, 0x06, 0x8c, 0x0c, 0x3a, 0xc2, 0x9a, 0xfe, 0x26, 0x41, 0x34, 0x53, 0x6b, 0x9b, 0xe2, 0x6f, 0x1d, 0x4c, 0xcd, 0x57, 0x5b, 0x88, 0xd3, 0xc3, 0xce, 0xab, 0xf3, 0x6a, 0xc9, 0x9c, 0x02, 0x78}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0xc0, 0x5b, 0xce, 0x0b, 0xd7, 0x74, 0x0c, 0x7b, 0xd0, 0x24, 0xfc, 0x75, 0x52, 0x02, 0xd5, 0x78, 0x14, 0x5b, 0xe3, 0x3d, 0xb2, 0xa3, 0xac, 0xbe, 0xf1, 0x1e, 0x5b, 0x1d, 0xc9, 0x33, 0xaa, 0x01}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x3c, 0x45, 0x80, 0xb4, 0x21, 0x26, 0x65, 0x78, 0x2c, 0x9a, 0x88, 0x8e, 0x8e, 0xcb, 0x70, 0x06, 0x3b, 0x6e, 0x80, 0x63, 0xbd, 0xa5, 0x8a, 0xe0, 0x23, 0xd3, 0x15, 0xa4, 0x2d, 0x6c, 0xe8, 0x61}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xec, 0xe7, 0xe2, 0x71, 0x45, 0xb1, 0x78, 0x5b, 0x62, 0xbb, 0x7d, 0xff, 0x29, 0xde, 0xef, 0xa9, 0xc6, 0x51, 0x9a, 0x18, 0x3f, 0x05, 0xb3, 0x6d, 0xa9, 0xb9, 0x8a, 0xdd, 0xe7, 0xe9, 0xf0, 0x81}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} - azure_AzureSEVSNP = M{1: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0x3f, 0x5f, 0x9f, 0x59, 0x2f, 0xfe, 0x84, 0x26, 0x26, 0x3d, 0x8a, 0x48, 0xa1, 0xe0, 0x27, 0x21, 0x83, 0x8f, 0xb7, 0x38, 0x4d, 0xa7, 0xcf, 0xfd, 0xe1, 0x07, 0xab, 0x92, 0xfd, 0xd8, 0xe8, 0x3f}, ValidationOpt: Enforce}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0xd1, 0x87, 0x6b, 0xdb, 0x55, 0xbe, 0x63, 0x18, 0x82, 0x9e, 0xe0, 0xf6, 0x55, 0x99, 0xd5, 0xde, 0xfa, 0x73, 0x57, 0xd9, 0x92, 0x10, 0x8e, 0x5b, 0xc1, 0xd3, 0x87, 0xa8, 0x6b, 0x01, 0x6e, 0x02}, ValidationOpt: Enforce}, 11: {Expected: []byte{0x87, 0x59, 0xdb, 0xd5, 0x32, 0x91, 0x3f, 0x45, 0x00, 0xbc, 0x02, 0x0d, 0x81, 0x1d, 0x27, 0x83, 0x16, 0x5b, 0x21, 0xa4, 0xf4, 0x89, 0xf7, 0x0f, 0x56, 0x53, 0xd5, 0x37, 0xac, 0xf9, 0xed, 0xa3}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} - azure_AzureTDX = M{1: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0x6c, 0x84, 0xf7, 0xbb, 0x26, 0x3b, 0x9d, 0x84, 0x53, 0xed, 0xd3, 0x53, 0x2c, 0x71, 0xfc, 0x60, 0xec, 0x77, 0x9e, 0x07, 0x8f, 0xc4, 0xd4, 0xca, 0x51, 0xc1, 0xb3, 0xb2, 0x17, 0x7c, 0xc7, 0x61}, ValidationOpt: Enforce}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x33, 0x58, 0x7b, 0x29, 0xb4, 0xc3, 0x16, 0x78, 0xe1, 0xc9, 0xfd, 0xff, 0x77, 0x3e, 0xb8, 0x52, 0x86, 0xfc, 0x05, 0x28, 0x71, 0xa7, 0x20, 0xe7, 0x88, 0xa3, 0xc3, 0xd3, 0x2f, 0x2e, 0x12, 0x64}, ValidationOpt: Enforce}, 11: {Expected: []byte{0x98, 0xdf, 0x21, 0xb0, 0xb0, 0xc6, 0xd2, 0x43, 0x6f, 0x81, 0xf7, 0x04, 0x98, 0x63, 0x8a, 0x99, 0x16, 0x80, 0xed, 0x69, 0xac, 0x78, 0x56, 0xbe, 0x7f, 0xde, 0x77, 0xf2, 0xae, 0x04, 0xd5, 0x5e}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} + aws_AWSNitroTPM = M{0: {Expected: []byte{0x73, 0x7f, 0x76, 0x7a, 0x12, 0xf5, 0x4e, 0x70, 0xee, 0xcb, 0xc8, 0x68, 0x40, 0x11, 0x32, 0x3a, 0xe2, 0xfe, 0x2d, 0xd9, 0xf9, 0x07, 0x85, 0x57, 0x79, 0x69, 0xd7, 0xa2, 0x01, 0x3e, 0x8c, 0x12}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0x52, 0x4e, 0xb1, 0x3d, 0x5e, 0x3e, 0x0f, 0x7c, 0x80, 0xa3, 0x25, 0x33, 0x8d, 0xec, 0x99, 0xc5, 0x02, 0x71, 0xb0, 0x8b, 0xd7, 0x10, 0x38, 0x6f, 0xce, 0x65, 0x19, 0x9f, 0xef, 0x92, 0x14, 0x61}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x87, 0xac, 0x51, 0xf1, 0xb5, 0x4e, 0x67, 0xfb, 0x58, 0xb1, 0x48, 0xe0, 0xa5, 0x93, 0x52, 0x06, 0x21, 0x1b, 0xf6, 0x79, 0x5e, 0xb5, 0x03, 0x49, 0x9d, 0x47, 0x2b, 0x4c, 0x79, 0x4d, 0x9d, 0x74}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xa2, 0xe0, 0x94, 0xad, 0x2f, 0x1f, 0xc8, 0xb5, 0x14, 0x65, 0xfd, 0x68, 0xec, 0x9c, 0xe3, 0xb5, 0xf8, 0x46, 0x7a, 0xa0, 0x31, 0xae, 0x20, 0x56, 0x8a, 0x82, 0xdd, 0xdd, 0x12, 0x9a, 0x10, 0xe7}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} + aws_AWSSEVSNP = M{0: {Expected: []byte{0x7b, 0x06, 0x8c, 0x0c, 0x3a, 0xc2, 0x9a, 0xfe, 0x26, 0x41, 0x34, 0x53, 0x6b, 0x9b, 0xe2, 0x6f, 0x1d, 0x4c, 0xcd, 0x57, 0x5b, 0x88, 0xd3, 0xc3, 0xce, 0xab, 0xf3, 0x6a, 0xc9, 0x9c, 0x02, 0x78}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0x1f, 0xb0, 0xd4, 0x6b, 0x77, 0x91, 0xe8, 0x51, 0xf9, 0x22, 0xe7, 0xb7, 0x93, 0x99, 0x0a, 0x92, 0x1c, 0xcc, 0x8e, 0xe1, 0xc6, 0x17, 0x20, 0x9e, 0x25, 0xf0, 0x53, 0x8d, 0x38, 0xb7, 0xf8, 0x3f}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0xd3, 0xbc, 0xd3, 0xcc, 0x12, 0x2a, 0xc5, 0x1b, 0xb0, 0x71, 0x4a, 0xac, 0x95, 0x4d, 0x8c, 0x95, 0x9e, 0xf1, 0x96, 0x8f, 0x4c, 0x67, 0xce, 0xce, 0x05, 0xdb, 0xfb, 0xb1, 0xda, 0xdc, 0xb9, 0xaf}, ValidationOpt: Enforce}, 11: {Expected: []byte{0x1c, 0xcd, 0x6c, 0x28, 0x4b, 0x3c, 0x7a, 0x0d, 0x59, 0x31, 0x63, 0x7f, 0x60, 0x7c, 0x06, 0x00, 0xec, 0x64, 0x46, 0x26, 0x1d, 0x3e, 0xe5, 0x78, 0xb5, 0x93, 0x25, 0x78, 0xdb, 0xb8, 0x8a, 0xf8}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} + azure_AzureSEVSNP = M{1: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0x85, 0xb8, 0x95, 0x18, 0x35, 0x3a, 0x65, 0x29, 0xe9, 0xb3, 0x55, 0xb2, 0xc4, 0x2a, 0x3b, 0xd9, 0x02, 0x54, 0x59, 0x1a, 0x51, 0xc5, 0x12, 0x8b, 0x90, 0xc3, 0x9a, 0xcb, 0x46, 0x93, 0x91, 0xd1}, ValidationOpt: Enforce}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x5e, 0x05, 0xc8, 0xe4, 0xea, 0x69, 0x9a, 0x0d, 0xff, 0xe0, 0x5a, 0xe1, 0x0b, 0x0c, 0xe3, 0x92, 0x4c, 0xbe, 0xe5, 0xdd, 0xfe, 0xe5, 0x05, 0x54, 0x18, 0x35, 0x0b, 0x3e, 0x5f, 0x37, 0x21, 0xd9}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xba, 0x3f, 0x88, 0x34, 0xeb, 0xbc, 0x5e, 0xe1, 0xb7, 0x5b, 0x82, 0xa6, 0x77, 0x8f, 0x81, 0xe3, 0x58, 0xa0, 0x0e, 0x04, 0xca, 0xcd, 0xfb, 0xbe, 0x28, 0x7e, 0x95, 0x15, 0x79, 0x2e, 0xc2, 0x76}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} + azure_AzureTDX = M{1: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0xd7, 0xa4, 0x27, 0x21, 0x96, 0x85, 0xf9, 0xa9, 0x4d, 0x9f, 0x5b, 0xcb, 0xb1, 0x97, 0xf1, 0x5b, 0x90, 0x49, 0xe3, 0xea, 0xaa, 0xf7, 0xa6, 0x98, 0xf6, 0x9e, 0x5c, 0x84, 0x20, 0x3e, 0xc8, 0xa6}, ValidationOpt: Enforce}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x8f, 0x94, 0x38, 0x33, 0x1d, 0xf2, 0x1a, 0x0b, 0x4e, 0x54, 0xf9, 0xd2, 0xea, 0x85, 0x09, 0x86, 0x7a, 0x7e, 0x92, 0x79, 0x6f, 0x7d, 0x29, 0xa6, 0x59, 0x23, 0xd0, 0x81, 0x94, 0xaa, 0xff, 0x0b}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xfb, 0x6e, 0xc9, 0x39, 0xca, 0xa8, 0x0d, 0xa7, 0xd7, 0x3b, 0x12, 0xf0, 0x88, 0x32, 0x8e, 0x2e, 0x56, 0xa6, 0x0a, 0xcc, 0x77, 0xa3, 0x15, 0xb6, 0x28, 0x2d, 0x7a, 0x85, 0xa2, 0xe3, 0x00, 0xd5}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} azure_AzureTrustedLaunch M - gcp_GCPSEVES = M{1: {Expected: []byte{0x36, 0x95, 0xdc, 0xc5, 0x5e, 0x3a, 0xa3, 0x40, 0x27, 0xc2, 0x77, 0x93, 0xc8, 0x5c, 0x72, 0x3c, 0x69, 0x7d, 0x70, 0x8c, 0x42, 0xd1, 0xf7, 0x3b, 0xd6, 0xfa, 0x4f, 0x26, 0x60, 0x8a, 0x5b, 0x24}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0xee, 0xfe, 0xd3, 0xca, 0x1d, 0x5e, 0xe3, 0x51, 0x60, 0x78, 0x20, 0x26, 0xd6, 0xad, 0x2c, 0xfc, 0x07, 0xba, 0xfc, 0xce, 0xcd, 0x56, 0xa6, 0x14, 0x35, 0x1b, 0xf9, 0x2b, 0x30, 0x09, 0x66, 0x37}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0xd8, 0xf1, 0x45, 0x7f, 0xb4, 0x82, 0xc8, 0xbd, 0xd1, 0xf1, 0xac, 0x99, 0xcd, 0xa5, 0x12, 0x6e, 0xca, 0x85, 0xfc, 0x0d, 0xd7, 0x31, 0xee, 0x3e, 0x5c, 0xd2, 0xef, 0xef, 0xbc, 0x2f, 0xdc, 0x83}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xc4, 0x1a, 0x00, 0xd8, 0x94, 0xfa, 0xc8, 0x72, 0x0a, 0x10, 0xd7, 0xec, 0xa1, 0xb2, 0x9e, 0x3d, 0xcf, 0x20, 0x3d, 0x79, 0x20, 0x40, 0x53, 0xb2, 0x99, 0xec, 0xb4, 0x04, 0xe9, 0xd6, 0x15, 0x81}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} - gcp_GCPSEVSNP = M{1: {Expected: []byte{0x36, 0x95, 0xdc, 0xc5, 0x5e, 0x3a, 0xa3, 0x40, 0x27, 0xc2, 0x77, 0x93, 0xc8, 0x5c, 0x72, 0x3c, 0x69, 0x7d, 0x70, 0x8c, 0x42, 0xd1, 0xf7, 0x3b, 0xd6, 0xfa, 0x4f, 0x26, 0x60, 0x8a, 0x5b, 0x24}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0x0e, 0xed, 0x02, 0x90, 0xb7, 0xbd, 0xaa, 0x2a, 0x25, 0xfc, 0x5f, 0xb2, 0x93, 0x9b, 0xa5, 0x5c, 0xb3, 0x93, 0x29, 0xb8, 0x22, 0xd1, 0xf7, 0x79, 0xdb, 0x31, 0xef, 0x28, 0x90, 0xd1, 0x22, 0x2d}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x4d, 0x99, 0x8b, 0xba, 0x91, 0x7b, 0x99, 0x8a, 0xc5, 0xf8, 0xc8, 0x39, 0x01, 0x33, 0x49, 0x54, 0x1f, 0xb4, 0xf6, 0x08, 0x2d, 0x18, 0x0f, 0x91, 0x34, 0x6f, 0x7c, 0xcb, 0x9d, 0xea, 0xed, 0xce}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xf3, 0x4b, 0x4f, 0xfa, 0xb7, 0x5a, 0x74, 0x8e, 0xbd, 0xb6, 0x72, 0xe0, 0x8e, 0xa4, 0x0c, 0x29, 0x6e, 0x7a, 0x82, 0x45, 0xf0, 0x5c, 0x29, 0xf8, 0x59, 0xa0, 0x1b, 0x22, 0x45, 0x3d, 0xcf, 0xaa}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} - openstack_QEMUVTPM = M{4: {Expected: []byte{0xdc, 0x08, 0xc8, 0xc3, 0x0e, 0xb3, 0x3a, 0xee, 0xb0, 0xac, 0x63, 0xe4, 0x16, 0xf3, 0x0d, 0x8b, 0xa1, 0xc3, 0x6b, 0xc3, 0xf3, 0xbd, 0xdc, 0x77, 0x98, 0xe1, 0x49, 0xe3, 0xeb, 0xea, 0x35, 0x05}, ValidationOpt: Enforce}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0xd8, 0x7f, 0x62, 0x14, 0x0b, 0xb3, 0xf7, 0x85, 0x4e, 0x0d, 0x2d, 0xc3, 0xdd, 0xd6, 0x0e, 0x2e, 0xbd, 0xbd, 0x8a, 0x39, 0x6a, 0x61, 0x8b, 0x63, 0x71, 0x3e, 0xc9, 0x52, 0x4a, 0xf4, 0x5a, 0xad}, ValidationOpt: Enforce}, 11: {Expected: []byte{0x28, 0x1c, 0xdc, 0x82, 0xf9, 0xa7, 0xb6, 0x6a, 0x39, 0xba, 0xff, 0x29, 0xe2, 0x53, 0x9b, 0xc7, 0x7f, 0x47, 0x93, 0x0f, 0x60, 0x79, 0x34, 0x7f, 0xbe, 0xd0, 0x3b, 0xa6, 0x72, 0xc8, 0x1b, 0xb9}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} + gcp_GCPSEVES = M{1: {Expected: []byte{0x36, 0x95, 0xdc, 0xc5, 0x5e, 0x3a, 0xa3, 0x40, 0x27, 0xc2, 0x77, 0x93, 0xc8, 0x5c, 0x72, 0x3c, 0x69, 0x7d, 0x70, 0x8c, 0x42, 0xd1, 0xf7, 0x3b, 0xd6, 0xfa, 0x4f, 0x26, 0x60, 0x8a, 0x5b, 0x24}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0x78, 0x2f, 0xa5, 0xdf, 0x53, 0x65, 0x67, 0x4f, 0x56, 0x16, 0x87, 0x36, 0xff, 0x01, 0x04, 0xe6, 0x04, 0xc3, 0x8c, 0xb6, 0x97, 0xde, 0x62, 0x25, 0xc8, 0xab, 0x6a, 0xe2, 0xab, 0xe8, 0x2b, 0x84}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0xd5, 0x2b, 0x7a, 0xce, 0xf7, 0x34, 0xf3, 0x3e, 0x15, 0x88, 0x51, 0x36, 0x3d, 0xd9, 0xfc, 0xcf, 0x25, 0xb0, 0x95, 0x0f, 0x7a, 0x49, 0x78, 0xfb, 0x5c, 0x74, 0x93, 0x9b, 0x95, 0x9f, 0x2d, 0x37}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xd3, 0x46, 0x24, 0x85, 0xb0, 0xac, 0x6e, 0x84, 0x13, 0x53, 0xb3, 0x77, 0x8c, 0x51, 0x50, 0x0c, 0x8f, 0xb3, 0x37, 0x70, 0xe7, 0x0c, 0x83, 0xc5, 0x42, 0x47, 0x3f, 0x99, 0x56, 0x58, 0x95, 0x83}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} + gcp_GCPSEVSNP = M{1: {Expected: []byte{0x36, 0x95, 0xdc, 0xc5, 0x5e, 0x3a, 0xa3, 0x40, 0x27, 0xc2, 0x77, 0x93, 0xc8, 0x5c, 0x72, 0x3c, 0x69, 0x7d, 0x70, 0x8c, 0x42, 0xd1, 0xf7, 0x3b, 0xd6, 0xfa, 0x4f, 0x26, 0x60, 0x8a, 0x5b, 0x24}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0x40, 0xab, 0xeb, 0xaf, 0x92, 0x65, 0x20, 0x4d, 0x1e, 0x4c, 0x43, 0x78, 0x76, 0xe4, 0xfc, 0xff, 0x22, 0x66, 0x1b, 0x15, 0x29, 0x1c, 0x64, 0xe8, 0xd1, 0x3e, 0x1b, 0x60, 0xa5, 0x7e, 0x9f, 0x8c}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x4a, 0x0b, 0xc5, 0xe6, 0x15, 0x3b, 0xf4, 0x81, 0x01, 0x07, 0xbe, 0x65, 0xf7, 0x3b, 0x25, 0x1b, 0x85, 0x90, 0x45, 0xd6, 0x88, 0xce, 0xc4, 0x22, 0x08, 0x56, 0x91, 0x3d, 0x06, 0x00, 0xfd, 0x9e}, ValidationOpt: Enforce}, 11: {Expected: []byte{0x12, 0x6e, 0x0b, 0xc8, 0x0c, 0x69, 0x29, 0x18, 0x8e, 0xd1, 0x29, 0x72, 0x4b, 0x6c, 0xba, 0x8c, 0xf4, 0xb5, 0x06, 0x5e, 0xa8, 0x0c, 0x49, 0xa1, 0xce, 0xb9, 0xd5, 0xdc, 0x67, 0xf0, 0x1f, 0xb6}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} + openstack_QEMUVTPM = M{4: {Expected: []byte{0x9f, 0x95, 0x8f, 0x98, 0xa5, 0xe6, 0x30, 0x94, 0xcb, 0x32, 0xff, 0x52, 0x52, 0x81, 0xcd, 0x3f, 0x70, 0x3e, 0xa2, 0x66, 0xff, 0x0c, 0x8d, 0xea, 0x66, 0xfa, 0x78, 0xa0, 0x5e, 0x26, 0x62, 0x06}, ValidationOpt: Enforce}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0xce, 0x63, 0xd7, 0x7b, 0x6d, 0xe0, 0xc2, 0xc8, 0xcb, 0xbb, 0xe0, 0xa3, 0x31, 0xab, 0xff, 0xfa, 0x42, 0x65, 0xdf, 0x36, 0x7b, 0xbc, 0xb1, 0x54, 0x11, 0xeb, 0xc5, 0xa2, 0x44, 0xc9, 0x18, 0x67}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xe8, 0xad, 0xba, 0x5a, 0x0a, 0xa4, 0x5e, 0xfb, 0x60, 0xa1, 0x31, 0x96, 0x55, 0xf8, 0xd6, 0xd3, 0x5e, 0x81, 0xc8, 0xf7, 0xf9, 0x20, 0xb2, 0x90, 0x2a, 0xd0, 0x3f, 0x4d, 0xf6, 0x3d, 0x02, 0xaa}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} qemu_QEMUTDX M - qemu_QEMUVTPM = M{4: {Expected: []byte{0xfd, 0xc3, 0x29, 0xe4, 0x31, 0x94, 0x3e, 0x62, 0xd5, 0xc7, 0x45, 0x83, 0xea, 0x70, 0x2c, 0x74, 0x00, 0x8a, 0xf6, 0x66, 0x3d, 0x60, 0x51, 0x38, 0x6b, 0xc7, 0xb5, 0xfb, 0x5d, 0x59, 0xda, 0x41}, ValidationOpt: Enforce}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0xca, 0x32, 0xf1, 0xb8, 0x1f, 0x63, 0x4c, 0x56, 0x19, 0xd7, 0xd4, 0xfb, 0x56, 0x84, 0x65, 0xdc, 0x00, 0x11, 0x01, 0xd2, 0x28, 0xb9, 0xb1, 0xb1, 0xb2, 0x01, 0x48, 0xa6, 0xec, 0x80, 0xc8, 0x5b}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xc4, 0xbc, 0x5b, 0x0b, 0x0f, 0xfd, 0x8b, 0xa5, 0xc0, 0x27, 0xe8, 0x2a, 0x33, 0x93, 0xb0, 0x52, 0x3a, 0x01, 0xe0, 0x5a, 0xfe, 0xeb, 0x92, 0xb5, 0x7d, 0x37, 0x83, 0x7d, 0xec, 0x9b, 0x79, 0xea}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} + qemu_QEMUVTPM = M{4: {Expected: []byte{0x74, 0x41, 0x6d, 0x97, 0x76, 0x56, 0x22, 0xdc, 0xdb, 0x71, 0xab, 0x99, 0x11, 0xe1, 0x99, 0x98, 0x5b, 0x9d, 0x75, 0xc0, 0x9e, 0x56, 0xdb, 0xdb, 0x10, 0x7e, 0x1e, 0xbf, 0x89, 0x33, 0x0f, 0x17}, ValidationOpt: Enforce}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0xf4, 0xa0, 0x26, 0xb1, 0x77, 0xf5, 0xa9, 0x93, 0x13, 0xbf, 0x68, 0x72, 0xa7, 0x45, 0xf3, 0xd8, 0x4a, 0xbb, 0x44, 0x29, 0xd7, 0x5d, 0xf6, 0x7d, 0x42, 0x3e, 0x3b, 0x36, 0xfa, 0x7e, 0x75, 0x63}, ValidationOpt: Enforce}, 11: {Expected: []byte{0xd1, 0x5e, 0xb9, 0xb4, 0xd5, 0xff, 0x6f, 0x60, 0xaa, 0x1c, 0x93, 0xe4, 0x45, 0x8b, 0x76, 0xd6, 0xe3, 0x8f, 0x90, 0x06, 0xb4, 0x1b, 0xe5, 0xed, 0x8e, 0x0a, 0x37, 0xec, 0xde, 0x84, 0xd8, 0xc8}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} ) diff --git a/internal/attestation/variant/variant.go b/internal/attestation/variant/variant.go index e71a51480..abe70fcaf 100644 --- a/internal/attestation/variant/variant.go +++ b/internal/attestation/variant/variant.go @@ -55,7 +55,7 @@ const ( var providerAttestationMapping = map[cloudprovider.Provider][]Variant{ cloudprovider.AWS: {AWSSEVSNP{}, AWSNitroTPM{}}, cloudprovider.Azure: {AzureSEVSNP{}, AzureTDX{}, AzureTrustedLaunch{}}, - cloudprovider.GCP: {GCPSEVES{}, GCPSEVSNP{}}, + cloudprovider.GCP: {GCPSEVSNP{}, GCPSEVES{}}, cloudprovider.QEMU: {QEMUVTPM{}}, cloudprovider.OpenStack: {QEMUVTPM{}}, } diff --git a/internal/cloud/azure/BUILD.bazel b/internal/cloud/azure/BUILD.bazel index d157af807..e91e22cb3 100644 --- a/internal/cloud/azure/BUILD.bazel +++ b/internal/cloud/azure/BUILD.bazel @@ -20,8 +20,8 @@ go_library( "//internal/role", "@com_github_azure_azure_sdk_for_go_sdk_azcore//runtime", "@com_github_azure_azure_sdk_for_go_sdk_azidentity//:azidentity", - "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v5//:armcompute", - "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_network_armnetwork_v5//:armnetwork", + "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v6//:armcompute", + "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_network_armnetwork_v6//:armnetwork", ] + select({ "@io_bazel_rules_go//go/platform:android": [ "@io_k8s_kubernetes//pkg/util/iptables", @@ -48,8 +48,8 @@ go_test( "//internal/role", "@com_github_azure_azure_sdk_for_go_sdk_azcore//runtime", "@com_github_azure_azure_sdk_for_go_sdk_azcore//to", - "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v5//:armcompute", - "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_network_armnetwork_v5//:armnetwork", + "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v6//:armcompute", + "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_network_armnetwork_v6//:armnetwork", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", "@org_golang_google_grpc//test/bufconn", diff --git a/internal/cloud/azure/azure.go b/internal/cloud/azure/azure.go index 85f718026..e0ee19750 100644 --- a/internal/cloud/azure/azure.go +++ b/internal/cloud/azure/azure.go @@ -23,8 +23,8 @@ import ( "strconv" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6" "github.com/edgelesssys/constellation/v2/internal/cloud" "github.com/edgelesssys/constellation/v2/internal/cloud/azureshared" "github.com/edgelesssys/constellation/v2/internal/cloud/metadata" diff --git a/internal/cloud/azure/azure_test.go b/internal/cloud/azure/azure_test.go index f364f3f2f..2b1daaab7 100644 --- a/internal/cloud/azure/azure_test.go +++ b/internal/cloud/azure/azure_test.go @@ -13,8 +13,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6" "github.com/edgelesssys/constellation/v2/internal/cloud" "github.com/edgelesssys/constellation/v2/internal/cloud/metadata" "github.com/edgelesssys/constellation/v2/internal/role" diff --git a/internal/cloud/azure/interface.go b/internal/cloud/azure/interface.go index fc61e09b2..e2b44ad6d 100644 --- a/internal/cloud/azure/interface.go +++ b/internal/cloud/azure/interface.go @@ -10,8 +10,8 @@ import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6" ) type imdsAPI interface { diff --git a/internal/cloud/azure/iptables_cross.go b/internal/cloud/azure/iptables_cross.go index f1caf3321..901b92c1d 100644 --- a/internal/cloud/azure/iptables_cross.go +++ b/internal/cloud/azure/iptables_cross.go @@ -13,6 +13,7 @@ import ( "log/slog" ) +// PrepareControlPlaneNode is only supported on Linux. func (c *Cloud) PrepareControlPlaneNode(_ context.Context, _ *slog.Logger) error { panic("azure.*Cloud.PrepareControlPlaneNode is only supported on Linux") } diff --git a/internal/cloud/openstack/BUILD.bazel b/internal/cloud/openstack/BUILD.bazel index b42e5a6a5..719f3fe02 100644 --- a/internal/cloud/openstack/BUILD.bazel +++ b/internal/cloud/openstack/BUILD.bazel @@ -18,12 +18,12 @@ go_library( "//internal/cloud/metadata", "//internal/constants", "//internal/role", - "@com_github_gophercloud_gophercloud//:gophercloud", - "@com_github_gophercloud_gophercloud//openstack/compute/v2/servers", - "@com_github_gophercloud_gophercloud//openstack/networking/v2/networks", - "@com_github_gophercloud_gophercloud//openstack/networking/v2/subnets", - "@com_github_gophercloud_gophercloud//pagination", - "@com_github_gophercloud_utils//openstack/clientconfig", + "@com_github_gophercloud_gophercloud_v2//:gophercloud", + "@com_github_gophercloud_gophercloud_v2//openstack/compute/v2/servers", + "@com_github_gophercloud_gophercloud_v2//openstack/networking/v2/networks", + "@com_github_gophercloud_gophercloud_v2//openstack/networking/v2/subnets", + "@com_github_gophercloud_gophercloud_v2//pagination", + "@com_github_gophercloud_utils_v2//openstack/clientconfig", ], ) @@ -40,11 +40,11 @@ go_test( deps = [ "//internal/cloud/metadata", "//internal/role", - "@com_github_gophercloud_gophercloud//:gophercloud", - "@com_github_gophercloud_gophercloud//openstack/compute/v2/servers", - "@com_github_gophercloud_gophercloud//openstack/networking/v2/networks", - "@com_github_gophercloud_gophercloud//openstack/networking/v2/subnets", - "@com_github_gophercloud_gophercloud//pagination", + "@com_github_gophercloud_gophercloud_v2//:gophercloud", + "@com_github_gophercloud_gophercloud_v2//openstack/compute/v2/servers", + "@com_github_gophercloud_gophercloud_v2//openstack/networking/v2/networks", + "@com_github_gophercloud_gophercloud_v2//openstack/networking/v2/subnets", + "@com_github_gophercloud_gophercloud_v2//pagination", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", ], diff --git a/internal/cloud/openstack/api.go b/internal/cloud/openstack/api.go index b133d2a47..f81e51e67 100644 --- a/internal/cloud/openstack/api.go +++ b/internal/cloud/openstack/api.go @@ -10,10 +10,10 @@ import ( "context" "github.com/edgelesssys/constellation/v2/internal/role" - "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" - "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" - "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" - "github.com/gophercloud/gophercloud/pagination" + "github.com/gophercloud/gophercloud/v2/openstack/compute/v2/servers" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/networks" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/subnets" + "github.com/gophercloud/gophercloud/v2/pagination" ) type imdsAPI interface { @@ -34,5 +34,5 @@ type serversAPI interface { } type pagerAPI interface { - AllPages() (pagination.Page, error) + AllPages(context.Context) (pagination.Page, error) } diff --git a/internal/cloud/openstack/api_test.go b/internal/cloud/openstack/api_test.go index 44c26c4ba..11479d233 100644 --- a/internal/cloud/openstack/api_test.go +++ b/internal/cloud/openstack/api_test.go @@ -10,10 +10,10 @@ import ( "context" "github.com/edgelesssys/constellation/v2/internal/role" - "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" - "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" - "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" - "github.com/gophercloud/gophercloud/pagination" + "github.com/gophercloud/gophercloud/v2/openstack/compute/v2/servers" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/networks" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/subnets" + "github.com/gophercloud/gophercloud/v2/pagination" ) type stubIMDSClient struct { @@ -90,6 +90,6 @@ type stubPager struct { allPagesErr error } -func (p *stubPager) AllPages() (pagination.Page, error) { +func (p *stubPager) AllPages(_ context.Context) (pagination.Page, error) { return p.page, p.allPagesErr } diff --git a/internal/cloud/openstack/imds.go b/internal/cloud/openstack/imds.go index 792a0d881..101808a37 100644 --- a/internal/cloud/openstack/imds.go +++ b/internal/cloud/openstack/imds.go @@ -172,6 +172,20 @@ func (c *imdsClient) userDomainName(ctx context.Context) (string, error) { return c.userDataCache.UserDomainName, nil } +func (c *imdsClient) regionName(ctx context.Context) (string, error) { + if c.timeForUpdate(c.cacheTime) || c.userDataCache.RegionName == "" { + if err := c.update(ctx); err != nil { + return "", err + } + } + + if c.userDataCache.RegionName == "" { + return "", errors.New("unable to get user domain name") + } + + return c.userDataCache.RegionName, nil +} + func (c *imdsClient) username(ctx context.Context) (string, error) { if c.timeForUpdate(c.cacheTime) || c.userDataCache.Username == "" { if err := c.update(ctx); err != nil { @@ -295,6 +309,7 @@ type metadataTags struct { type userDataResponse struct { AuthURL string `json:"openstack-auth-url,omitempty"` UserDomainName string `json:"openstack-user-domain-name,omitempty"` + RegionName string `json:"openstack-region-name,omitempty"` Username string `json:"openstack-username,omitempty"` Password string `json:"openstack-password,omitempty"` LoadBalancerEndpoint string `json:"openstack-load-balancer-endpoint,omitempty"` diff --git a/internal/cloud/openstack/openstack.go b/internal/cloud/openstack/openstack.go index 9472b3068..4ff3b2b32 100644 --- a/internal/cloud/openstack/openstack.go +++ b/internal/cloud/openstack/openstack.go @@ -17,10 +17,10 @@ import ( "github.com/edgelesssys/constellation/v2/internal/cloud/metadata" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/role" - "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" - "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" - "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" - "github.com/gophercloud/utils/openstack/clientconfig" + "github.com/gophercloud/gophercloud/v2/openstack/compute/v2/servers" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/networks" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/subnets" + "github.com/gophercloud/utils/v2/openstack/clientconfig" ) const ( @@ -54,6 +54,10 @@ func New(ctx context.Context) (*MetadataClient, error) { if err != nil { return nil, fmt.Errorf("getting user domain name: %w", err) } + regionName, err := imds.regionName(ctx) + if err != nil { + return nil, fmt.Errorf("getting region name: %w", err) + } clientOpts := &clientconfig.ClientOpts{ AuthType: clientconfig.AuthV3Password, @@ -63,15 +67,16 @@ func New(ctx context.Context) (*MetadataClient, error) { Username: username, Password: password, }, + RegionName: regionName, } - serversClient, err := clientconfig.NewServiceClient("compute", clientOpts) + serversClient, err := clientconfig.NewServiceClient(ctx, "compute", clientOpts) if err != nil { return nil, fmt.Errorf("creating compute client: %w", err) } serversClient.Microversion = microversion - networksClient, err := clientconfig.NewServiceClient("network", clientOpts) + networksClient, err := clientconfig.NewServiceClient(ctx, "network", clientOpts) if err != nil { return nil, fmt.Errorf("creating network client: %w", err) } @@ -122,12 +127,12 @@ func (c *MetadataClient) List(ctx context.Context) ([]metadata.InstanceMetadata, uidTag := fmt.Sprintf("constellation-uid-%s", uid) - subnet, err := c.getSubnetCIDR(uidTag) + subnet, err := c.getSubnetCIDR(ctx, uidTag) if err != nil { return nil, err } - srvs, err := c.getServers(uidTag) + srvs, err := c.getServers(ctx, uidTag) if err != nil { return nil, err } @@ -240,9 +245,9 @@ func (c *MetadataClient) GetLoadBalancerEndpoint(ctx context.Context) (host, por return host, strconv.FormatInt(constants.KubernetesPort, 10), nil } -func (c *MetadataClient) getSubnetCIDR(uidTag string) (netip.Prefix, error) { +func (c *MetadataClient) getSubnetCIDR(ctx context.Context, uidTag string) (netip.Prefix, error) { listNetworksOpts := networks.ListOpts{Tags: uidTag} - networksPage, err := c.api.ListNetworks(listNetworksOpts).AllPages() + networksPage, err := c.api.ListNetworks(listNetworksOpts).AllPages(ctx) if err != nil { return netip.Prefix{}, fmt.Errorf("listing networks: %w", err) } @@ -255,7 +260,7 @@ func (c *MetadataClient) getSubnetCIDR(uidTag string) (netip.Prefix, error) { } listSubnetsOpts := subnets.ListOpts{Tags: uidTag} - subnetsPage, err := c.api.ListSubnets(listSubnetsOpts).AllPages() + subnetsPage, err := c.api.ListSubnets(listSubnetsOpts).AllPages(ctx) if err != nil { return netip.Prefix{}, fmt.Errorf("listing subnets: %w", err) } @@ -285,9 +290,9 @@ func (c *MetadataClient) getSubnetCIDR(uidTag string) (netip.Prefix, error) { return cidr, nil } -func (c *MetadataClient) getServers(uidTag string) ([]servers.Server, error) { +func (c *MetadataClient) getServers(ctx context.Context, uidTag string) ([]servers.Server, error) { listServersOpts := servers.ListOpts{Tags: uidTag} - serversPage, err := c.api.ListServers(listServersOpts).AllPages() + serversPage, err := c.api.ListServers(listServersOpts).AllPages(ctx) if err != nil { return nil, fmt.Errorf("listing servers: %w", err) } diff --git a/internal/cloud/openstack/openstack_test.go b/internal/cloud/openstack/openstack_test.go index da8ed9d6b..33835b243 100644 --- a/internal/cloud/openstack/openstack_test.go +++ b/internal/cloud/openstack/openstack_test.go @@ -14,11 +14,11 @@ import ( "github.com/edgelesssys/constellation/v2/internal/cloud/metadata" "github.com/edgelesssys/constellation/v2/internal/role" - "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" - "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" - "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" - "github.com/gophercloud/gophercloud/pagination" + "github.com/gophercloud/gophercloud/v2" + "github.com/gophercloud/gophercloud/v2/openstack/compute/v2/servers" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/networks" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/subnets" + "github.com/gophercloud/gophercloud/v2/pagination" "github.com/stretchr/testify/assert" ) diff --git a/internal/cloud/openstack/wrappers.go b/internal/cloud/openstack/wrappers.go index c2c732698..6a0cb7aaf 100644 --- a/internal/cloud/openstack/wrappers.go +++ b/internal/cloud/openstack/wrappers.go @@ -7,10 +7,10 @@ SPDX-License-Identifier: AGPL-3.0-only package openstack import ( - "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" - "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" - "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" + "github.com/gophercloud/gophercloud/v2" + "github.com/gophercloud/gophercloud/v2/openstack/compute/v2/servers" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/networks" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/subnets" ) type apiClient struct { diff --git a/internal/config/BUILD.bazel b/internal/config/BUILD.bazel index 8ea071ae8..8a96864c5 100644 --- a/internal/config/BUILD.bazel +++ b/internal/config/BUILD.bazel @@ -63,6 +63,7 @@ go_test( "//internal/cloud/cloudprovider", "//internal/config/instancetypes", "//internal/constants", + "//internal/encoding", "//internal/file", "//internal/semver", "//internal/versions", diff --git a/internal/config/attestationversion.go b/internal/config/attestationversion.go index a7949c5c3..e2e5a12a5 100644 --- a/internal/config/attestationversion.go +++ b/internal/config/attestationversion.go @@ -9,47 +9,49 @@ package config import ( "encoding/json" "fmt" - "math" - "strconv" "strings" + + "github.com/edgelesssys/constellation/v2/internal/encoding" ) -const placeholderVersionValue = 0 +type versionValue interface { + encoding.HexBytes | uint8 | uint16 +} + +func placeholderVersionValue[T versionValue]() T { + var placeholder T + return placeholder +} // NewLatestPlaceholderVersion returns the latest version with a placeholder version value. -func NewLatestPlaceholderVersion() AttestationVersion { - return AttestationVersion{ - Value: placeholderVersionValue, +func NewLatestPlaceholderVersion[T versionValue]() AttestationVersion[T] { + return AttestationVersion[T]{ + Value: placeholderVersionValue[T](), WantLatest: true, } } -// AttestationVersion is a type that represents a version of a SNP. -type AttestationVersion struct { - Value uint8 +// AttestationVersion holds version information. +type AttestationVersion[T versionValue] struct { + Value T WantLatest bool } -// MarshalYAML implements a custom marshaller to resolve "latest" values. -func (v AttestationVersion) MarshalYAML() (any, error) { +// MarshalYAML implements a custom marshaller to write "latest" as the type's value, if set. +func (v AttestationVersion[T]) MarshalYAML() (any, error) { if v.WantLatest { return "latest", nil } return v.Value, nil } -// UnmarshalYAML implements a custom unmarshaller to resolve "atest" values. -func (v *AttestationVersion) UnmarshalYAML(unmarshal func(any) error) error { - var rawUnmarshal string - if err := unmarshal(&rawUnmarshal); err != nil { - return fmt.Errorf("raw unmarshal: %w", err) - } - - return v.parseRawUnmarshal(rawUnmarshal) +// UnmarshalYAML implements a custom unmarshaller to resolve "latest" values. +func (v *AttestationVersion[T]) UnmarshalYAML(unmarshal func(any) error) error { + return v.unmarshal(unmarshal) } -// MarshalJSON implements a custom marshaller to resolve "latest" values. -func (v AttestationVersion) MarshalJSON() ([]byte, error) { +// MarshalJSON implements a custom marshaller to write "latest" as the type's value, if set. +func (v AttestationVersion[T]) MarshalJSON() ([]byte, error) { if v.WantLatest { return json.Marshal("latest") } @@ -57,39 +59,31 @@ func (v AttestationVersion) MarshalJSON() ([]byte, error) { } // UnmarshalJSON implements a custom unmarshaller to resolve "latest" values. -func (v *AttestationVersion) UnmarshalJSON(data []byte) (err error) { - // JSON has two distinct ways to represent numbers and strings. - // This means we cannot simply unmarshal to string, like with YAML. - // Unmarshalling to `any` causes Go to unmarshal numbers to float64. - // Therefore, try to unmarshal to string, and then to int, instead of using type assertions. +func (v *AttestationVersion[T]) UnmarshalJSON(data []byte) (err error) { + return v.unmarshal(func(a any) error { + return json.Unmarshal(data, a) + }) +} + +// unmarshal takes care of unmarshalling the value from YAML or JSON. +func (v *AttestationVersion[T]) unmarshal(unmarshal func(any) error) error { + // Start by trying to unmarshal to the distinct type + var distinctType T + if err := unmarshal(&distinctType); err == nil { + v.Value = distinctType + return nil + } + var unmarshalString string - if err := json.Unmarshal(data, &unmarshalString); err != nil { - var unmarshalInt int64 - if err := json.Unmarshal(data, &unmarshalInt); err != nil { - return fmt.Errorf("unable to unmarshal to string or int: %w", err) - } - unmarshalString = strconv.FormatInt(unmarshalInt, 10) + if err := unmarshal(&unmarshalString); err != nil { + return fmt.Errorf("failed unmarshalling to %T or string: %w", distinctType, err) } - return v.parseRawUnmarshal(unmarshalString) -} - -func (v *AttestationVersion) parseRawUnmarshal(str string) error { - if strings.HasPrefix(str, "0") && len(str) != 1 { - return fmt.Errorf("no format with prefixed 0 (octal, hexadecimal) allowed: %s", str) - } - if strings.ToLower(str) == "latest" { + if strings.ToLower(unmarshalString) == "latest" { v.WantLatest = true - v.Value = placeholderVersionValue - } else { - ui, err := strconv.ParseUint(str, 10, 8) - if err != nil { - return fmt.Errorf("invalid version value: %s", str) - } - if ui > math.MaxUint8 { - return fmt.Errorf("integer value is out ouf uint8 range: %d", ui) - } - v.Value = uint8(ui) + v.Value = placeholderVersionValue[T]() + return nil } - return nil + + return fmt.Errorf("failed unmarshalling to %T or string: invalid value: %s", distinctType, unmarshalString) } diff --git a/internal/config/attestationversion_test.go b/internal/config/attestationversion_test.go index 52d68e2a8..45a401216 100644 --- a/internal/config/attestationversion_test.go +++ b/internal/config/attestationversion_test.go @@ -7,204 +7,307 @@ SPDX-License-Identifier: AGPL-3.0-only package config import ( + "bytes" "encoding/json" "testing" - "github.com/stretchr/testify/require" + "github.com/edgelesssys/constellation/v2/internal/encoding" + "github.com/stretchr/testify/assert" "gopkg.in/yaml.v3" ) func TestVersionMarshalYAML(t *testing.T) { - tests := map[string]struct { - sut AttestationVersion + testCasesUint8 := map[string]struct { + sut AttestationVersion[uint8] want string }{ - "isLatest resolves to latest": { - sut: AttestationVersion{ + "version with latest writes latest": { + sut: AttestationVersion[uint8]{ Value: 1, WantLatest: true, }, want: "latest\n", }, - "value 5 resolves to 5": { - sut: AttestationVersion{ + "value 5 writes 5": { + sut: AttestationVersion[uint8]{ Value: 5, WantLatest: false, }, want: "5\n", }, } - for name, tc := range tests { + for name, tc := range testCasesUint8 { t.Run(name, func(t *testing.T) { - require := require.New(t) + assert := assert.New(t) bt, err := yaml.Marshal(tc.sut) - require.NoError(err) - require.Equal(tc.want, string(bt)) + assert.NoError(err) + assert.Equal(tc.want, string(bt)) + }) + } + + testCasesUint16 := map[string]struct { + sut AttestationVersion[uint16] + want string + }{ + "version with latest writes latest": { + sut: AttestationVersion[uint16]{ + Value: 1, + WantLatest: true, + }, + want: "latest\n", + }, + "value 5 writes 5": { + sut: AttestationVersion[uint16]{ + Value: 5, + WantLatest: false, + }, + want: "5\n", + }, + } + for name, tc := range testCasesUint16 { + t.Run(name, func(t *testing.T) { + assert := assert.New(t) + + bt, err := yaml.Marshal(tc.sut) + assert.NoError(err) + assert.Equal(tc.want, string(bt)) + }) + } + + testCasesHexBytes := map[string]struct { + sut AttestationVersion[encoding.HexBytes] + want string + }{ + "version with latest writes latest": { + sut: AttestationVersion[encoding.HexBytes]{ + Value: encoding.HexBytes(bytes.Repeat([]byte("0"), 16)), + WantLatest: true, + }, + want: "latest\n", + }, + "value 5 writes 5": { + sut: AttestationVersion[encoding.HexBytes]{ + Value: encoding.HexBytes(bytes.Repeat([]byte("A"), 16)), + WantLatest: false, + }, + want: "\"41414141414141414141414141414141\"\n", + }, + } + for name, tc := range testCasesHexBytes { + t.Run(name, func(t *testing.T) { + assert := assert.New(t) + + bt, err := yaml.Marshal(tc.sut) + assert.NoError(err) + assert.Equal(tc.want, string(bt)) }) } } -func TestVersionUnmarshalYAML(t *testing.T) { - tests := map[string]struct { - sut string - want AttestationVersion - wantErr bool +func TestVersionUnmarshal(t *testing.T) { + testCasesUint8 := map[string]struct { + yamlData string + jsonData string + want AttestationVersion[uint8] + wantErr bool }{ "latest resolves to isLatest": { - sut: "latest", - want: AttestationVersion{ + yamlData: "latest", + jsonData: "\"latest\"", + want: AttestationVersion[uint8]{ Value: 0, WantLatest: true, }, wantErr: false, }, "1 resolves to value 1": { - sut: "1", - want: AttestationVersion{ + yamlData: "1", + jsonData: "1", + want: AttestationVersion[uint8]{ Value: 1, WantLatest: false, }, wantErr: false, }, "max uint8+1 errors": { - sut: "256", - wantErr: true, + yamlData: "256", + jsonData: "256", + wantErr: true, }, "-1 errors": { - sut: "-1", - wantErr: true, - }, - "2.6 errors": { - sut: "2.6", - wantErr: true, - }, - "2.0 errors": { - sut: "2.0", - wantErr: true, - }, - "hex format is invalid": { - sut: "0x10", - wantErr: true, - }, - "octal format is invalid": { - sut: "010", - wantErr: true, + yamlData: "-1", + jsonData: "-1", + wantErr: true, }, "0 resolves to value 0": { - sut: "0", - want: AttestationVersion{ + yamlData: "0", + jsonData: "0", + want: AttestationVersion[uint8]{ Value: 0, WantLatest: false, }, }, - "00 errors": { - sut: "00", - wantErr: true, - }, } - for name, tc := range tests { + for name, tc := range testCasesUint8 { t.Run(name, func(t *testing.T) { - require := require.New(t) + assert := assert.New(t) - var sut AttestationVersion - err := yaml.Unmarshal([]byte(tc.sut), &sut) - if tc.wantErr { - require.Error(err) - return + { + var sut AttestationVersion[uint8] + err := yaml.Unmarshal([]byte(tc.yamlData), &sut) + if tc.wantErr { + assert.Error(err) + } else { + assert.NoError(err) + assert.Equal(tc.want, sut) + } + } + + { + var sut AttestationVersion[uint8] + err := json.Unmarshal([]byte(tc.jsonData), &sut) + if tc.wantErr { + assert.Error(err) + } else { + assert.NoError(err) + assert.Equal(tc.want, sut) + } } - require.NoError(err) - require.Equal(tc.want, sut) }) } -} -func TestVersionUnmarshalJSON(t *testing.T) { - tests := map[string]struct { - sut string - want AttestationVersion - wantErr bool + testCasesUint16 := map[string]struct { + yamlData string + jsonData string + want AttestationVersion[uint16] + wantErr bool }{ "latest resolves to isLatest": { - sut: `"latest"`, - want: AttestationVersion{ + yamlData: "latest", + jsonData: "\"latest\"", + want: AttestationVersion[uint16]{ Value: 0, WantLatest: true, }, + wantErr: false, }, "1 resolves to value 1": { - sut: "1", - want: AttestationVersion{ + yamlData: "1", + jsonData: "1", + want: AttestationVersion[uint16]{ Value: 1, WantLatest: false, }, + wantErr: false, }, - "quoted number resolves to value": { - sut: `"1"`, - want: AttestationVersion{ - Value: 1, - WantLatest: false, - }, - }, - "quoted float errors": { - sut: `"1.0"`, - wantErr: true, - }, - "max uint8+1 errors": { - sut: "256", - wantErr: true, + "max uint16+1 errors": { + yamlData: "65536", + jsonData: "65536", + wantErr: true, }, "-1 errors": { - sut: "-1", - wantErr: true, - }, - "2.6 errors": { - sut: "2.6", - wantErr: true, - }, - "2.0 errors": { - sut: "2.0", - wantErr: true, - }, - "hex format is invalid": { - sut: "0x10", - wantErr: true, - }, - "octal format is invalid": { - sut: "010", - wantErr: true, + yamlData: "-1", + jsonData: "-1", + wantErr: true, }, "0 resolves to value 0": { - sut: "0", - want: AttestationVersion{ + yamlData: "0", + jsonData: "0", + want: AttestationVersion[uint16]{ Value: 0, WantLatest: false, }, }, - "quoted 0 resolves to value 0": { - sut: `"0"`, - want: AttestationVersion{ - Value: 0, - WantLatest: false, - }, - }, - "00 errors": { - sut: "00", - wantErr: true, - }, } - for name, tc := range tests { + for name, tc := range testCasesUint16 { t.Run(name, func(t *testing.T) { - require := require.New(t) + assert := assert.New(t) - var sut AttestationVersion - err := json.Unmarshal([]byte(tc.sut), &sut) - if tc.wantErr { - require.Error(err) - return + { + var sut AttestationVersion[uint16] + err := yaml.Unmarshal([]byte(tc.yamlData), &sut) + if tc.wantErr { + assert.Error(err) + } else { + assert.NoError(err) + assert.Equal(tc.want, sut) + } + } + + { + var sut AttestationVersion[uint16] + err := json.Unmarshal([]byte(tc.jsonData), &sut) + if tc.wantErr { + assert.Error(err) + } else { + assert.NoError(err) + assert.Equal(tc.want, sut) + } + } + }) + } + + testCasesHexBytes := map[string]struct { + yamlData string + jsonData string + want AttestationVersion[encoding.HexBytes] + wantErr bool + }{ + "latest resolves to isLatest": { + yamlData: "latest", + jsonData: "\"latest\"", + want: AttestationVersion[encoding.HexBytes]{ + Value: encoding.HexBytes(nil), + WantLatest: true, + }, + wantErr: false, + }, + "hex string resolves to correctly": { + yamlData: "41414141414141414141414141414141", + jsonData: "\"41414141414141414141414141414141\"", + want: AttestationVersion[encoding.HexBytes]{ + Value: encoding.HexBytes(bytes.Repeat([]byte("A"), 16)), + WantLatest: false, + }, + wantErr: false, + }, + "invalid hex string": { + yamlData: "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG", + jsonData: "\"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\"", + wantErr: true, + }, + "non hex data": { + yamlData: "-15", + jsonData: "-15", + wantErr: true, + }, + } + for name, tc := range testCasesHexBytes { + t.Run(name, func(t *testing.T) { + assert := assert.New(t) + + { + var sut AttestationVersion[encoding.HexBytes] + err := yaml.Unmarshal([]byte(tc.yamlData), &sut) + if tc.wantErr { + assert.Error(err) + } else { + assert.NoError(err) + assert.Equal(tc.want, sut) + } + } + + { + var sut AttestationVersion[encoding.HexBytes] + err := json.Unmarshal([]byte(tc.jsonData), &sut) + if tc.wantErr { + assert.Error(err) + } else { + assert.NoError(err) + assert.Equal(tc.want, sut) + } } - require.NoError(err) - require.Equal(tc.want, sut) }) } } diff --git a/internal/config/aws.go b/internal/config/aws.go index 53b11e69f..10dc449e2 100644 --- a/internal/config/aws.go +++ b/internal/config/aws.go @@ -22,10 +22,10 @@ var _ svnResolveMarshaller = &AWSSEVSNP{} func DefaultForAWSSEVSNP() *AWSSEVSNP { return &AWSSEVSNP{ Measurements: measurements.DefaultsFor(cloudprovider.AWS, variant.AWSSEVSNP{}), - BootloaderVersion: NewLatestPlaceholderVersion(), - TEEVersion: NewLatestPlaceholderVersion(), - SNPVersion: NewLatestPlaceholderVersion(), - MicrocodeVersion: NewLatestPlaceholderVersion(), + BootloaderVersion: NewLatestPlaceholderVersion[uint8](), + TEEVersion: NewLatestPlaceholderVersion[uint8](), + SNPVersion: NewLatestPlaceholderVersion[uint8](), + MicrocodeVersion: NewLatestPlaceholderVersion[uint8](), AMDRootKey: mustParsePEM(arkPEM), } } @@ -79,7 +79,7 @@ func (c *AWSSEVSNP) FetchAndSetLatestVersionNumbers(ctx context.Context, fetcher return nil } - versions, err := fetcher.FetchSEVSNPVersionLatest(ctx, variant.AWSSEVSNP{}) + versions, err := fetcher.FetchLatestVersion(ctx, variant.AWSSEVSNP{}) if err != nil { return fmt.Errorf("fetching latest TCB versions from configapi: %w", err) } diff --git a/internal/config/azure.go b/internal/config/azure.go index 79a414f53..273f54381 100644 --- a/internal/config/azure.go +++ b/internal/config/azure.go @@ -28,10 +28,10 @@ var ( func DefaultForAzureSEVSNP() *AzureSEVSNP { return &AzureSEVSNP{ Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureSEVSNP{}), - BootloaderVersion: NewLatestPlaceholderVersion(), - TEEVersion: NewLatestPlaceholderVersion(), - SNPVersion: NewLatestPlaceholderVersion(), - MicrocodeVersion: NewLatestPlaceholderVersion(), + BootloaderVersion: NewLatestPlaceholderVersion[uint8](), + TEEVersion: NewLatestPlaceholderVersion[uint8](), + SNPVersion: NewLatestPlaceholderVersion[uint8](), + MicrocodeVersion: NewLatestPlaceholderVersion[uint8](), FirmwareSignerConfig: SNPFirmwareSignerConfig{ AcceptedKeyDigests: idkeydigest.DefaultList(), EnforcementPolicy: idkeydigest.MAAFallback, @@ -80,7 +80,7 @@ func (c *AzureSEVSNP) FetchAndSetLatestVersionNumbers(ctx context.Context, fetch return nil } - versions, err := fetcher.FetchSEVSNPVersionLatest(ctx, variant.AzureSEVSNP{}) + versions, err := fetcher.FetchLatestVersion(ctx, variant.AzureSEVSNP{}) if err != nil { return fmt.Errorf("fetching latest TCB versions from configapi: %w", err) } @@ -142,14 +142,14 @@ func DefaultForAzureTDX() *AzureTDX { return &AzureTDX{ Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureTDX{}), // TODO(AB#3798): Enable latest versioning for Azure TDX - QESVN: 0, - PCESVN: 0, - TEETCBSVN: encoding.HexBytes{0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - QEVendorID: encoding.HexBytes{0x93, 0x9a, 0x72, 0x33, 0xf7, 0x9c, 0x4c, 0xa9, 0x94, 0x0a, 0x0d, 0xb3, 0x95, 0x7f, 0x06, 0x07}, + QESVN: NewLatestPlaceholderVersion[uint16](), + PCESVN: NewLatestPlaceholderVersion[uint16](), + TEETCBSVN: NewLatestPlaceholderVersion[encoding.HexBytes](), + QEVendorID: NewLatestPlaceholderVersion[encoding.HexBytes](), // Don't set a default for MRSEAM as it effectively prevents upgrading the SEAM module // Quote verification still makes sure the module comes from Intel (through MRSIGNERSEAM), and is not of a lower version than expected // MRSeam: nil, - XFAM: encoding.HexBytes{0xe7, 0x18, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, + XFAM: NewLatestPlaceholderVersion[encoding.HexBytes](), IntelRootKey: mustParsePEM(tdxRootPEM), } @@ -179,9 +179,43 @@ func (c AzureTDX) EqualTo(other AttestationCfg) (bool, error) { return c.Measurements.EqualTo(otherCfg.Measurements), nil } +// FetchAndSetLatestVersionNumbers fetches the latest version numbers from the configapi and sets them. +func (c *AzureTDX) FetchAndSetLatestVersionNumbers(ctx context.Context, fetcher attestationconfigapi.Fetcher) error { + // Only talk to the API if at least one version number is set to latest. + if !(c.PCESVN.WantLatest || c.QESVN.WantLatest || c.TEETCBSVN.WantLatest || c.QEVendorID.WantLatest || c.XFAM.WantLatest) { + return nil + } + + versions, err := fetcher.FetchLatestVersion(ctx, variant.AzureTDX{}) + if err != nil { + return fmt.Errorf("fetching latest TCB versions from configapi: %w", err) + } + + // set values and keep WantLatest flag + if c.PCESVN.WantLatest { + c.PCESVN.Value = versions.PCESVN + } + if c.QESVN.WantLatest { + c.QESVN.Value = versions.QESVN + } + if c.TEETCBSVN.WantLatest { + c.TEETCBSVN.Value = versions.TEETCBSVN[:] + } + if c.QEVendorID.WantLatest { + c.QEVendorID.Value = versions.QEVendorID[:] + } + if c.XFAM.WantLatest { + c.XFAM.Value = versions.XFAM[:] + } + return nil +} + func (c *AzureTDX) getToMarshallLatestWithResolvedVersions() AttestationCfg { cp := *c - // TODO: We probably want to support "latest" pseudo versioning for Azure TDX - // But we should decide on which claims can be reliably used for attestation first + cp.PCESVN.WantLatest = false + cp.QESVN.WantLatest = false + cp.TEETCBSVN.WantLatest = false + cp.QEVendorID.WantLatest = false + cp.XFAM.WantLatest = false return &cp } diff --git a/internal/config/config.go b/internal/config/config.go index e4b1fa765..5aefb05b3 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -281,7 +281,7 @@ type AttestationConfig struct { // GCP SEV-ES attestation. GCPSEVES *GCPSEVES `yaml:"gcpSEVES,omitempty" validate:"omitempty"` // description: | - // GCP SEV-SNP attestation. + // GCP SEV-SNP attestation. GCPSEVSNP *GCPSEVSNP `yaml:"gcpSEVSNP,omitempty" validate:"omitempty"` // description: | // QEMU tdx attestation. @@ -468,18 +468,22 @@ func New(fileHandler file.Handler, name string, fetcher attestationconfigapi.Fet return nil, err } + // Replace "latest" placeholders for attestation version numbers with the actual latest version numbers from config API if azure := c.Attestation.AzureSEVSNP; azure != nil { if err := azure.FetchAndSetLatestVersionNumbers(context.Background(), fetcher); err != nil { return c, err } } - + if azure := c.Attestation.AzureTDX; azure != nil { + if err := azure.FetchAndSetLatestVersionNumbers(context.Background(), fetcher); err != nil { + return c, err + } + } if aws := c.Attestation.AWSSEVSNP; aws != nil { if err := aws.FetchAndSetLatestVersionNumbers(context.Background(), fetcher); err != nil { return c, err } } - if gcp := c.Attestation.GCPSEVSNP; gcp != nil { if err := gcp.FetchAndSetLatestVersionNumbers(context.Background(), fetcher); err != nil { return c, err @@ -993,16 +997,16 @@ type GCPSEVSNP struct { Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"` // description: | // Lowest acceptable bootloader version. - BootloaderVersion AttestationVersion `json:"bootloaderVersion" yaml:"bootloaderVersion"` + BootloaderVersion AttestationVersion[uint8] `json:"bootloaderVersion" yaml:"bootloaderVersion"` // description: | // Lowest acceptable TEE version. - TEEVersion AttestationVersion `json:"teeVersion" yaml:"teeVersion"` + TEEVersion AttestationVersion[uint8] `json:"teeVersion" yaml:"teeVersion"` // description: | // Lowest acceptable SEV-SNP version. - SNPVersion AttestationVersion `json:"snpVersion" yaml:"snpVersion"` + SNPVersion AttestationVersion[uint8] `json:"snpVersion" yaml:"snpVersion"` // description: | // Lowest acceptable microcode version. - MicrocodeVersion AttestationVersion `json:"microcodeVersion" yaml:"microcodeVersion"` + MicrocodeVersion AttestationVersion[uint8] `json:"microcodeVersion" yaml:"microcodeVersion"` // description: | // AMD Root Key certificate used to verify the SEV-SNP certificate chain. AMDRootKey Certificate `json:"amdRootKey" yaml:"amdRootKey"` @@ -1080,16 +1084,16 @@ type AWSSEVSNP struct { Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"` // description: | // Lowest acceptable bootloader version. - BootloaderVersion AttestationVersion `json:"bootloaderVersion" yaml:"bootloaderVersion"` + BootloaderVersion AttestationVersion[uint8] `json:"bootloaderVersion" yaml:"bootloaderVersion"` // description: | // Lowest acceptable TEE version. - TEEVersion AttestationVersion `json:"teeVersion" yaml:"teeVersion"` + TEEVersion AttestationVersion[uint8] `json:"teeVersion" yaml:"teeVersion"` // description: | // Lowest acceptable SEV-SNP version. - SNPVersion AttestationVersion `json:"snpVersion" yaml:"snpVersion"` + SNPVersion AttestationVersion[uint8] `json:"snpVersion" yaml:"snpVersion"` // description: | // Lowest acceptable microcode version. - MicrocodeVersion AttestationVersion `json:"microcodeVersion" yaml:"microcodeVersion"` + MicrocodeVersion AttestationVersion[uint8] `json:"microcodeVersion" yaml:"microcodeVersion"` // description: | // AMD Root Key certificate used to verify the SEV-SNP certificate chain. AMDRootKey Certificate `json:"amdRootKey" yaml:"amdRootKey"` @@ -1112,16 +1116,16 @@ type AzureSEVSNP struct { Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"` // description: | // Lowest acceptable bootloader version. - BootloaderVersion AttestationVersion `json:"bootloaderVersion" yaml:"bootloaderVersion"` + BootloaderVersion AttestationVersion[uint8] `json:"bootloaderVersion" yaml:"bootloaderVersion"` // description: | // Lowest acceptable TEE version. - TEEVersion AttestationVersion `json:"teeVersion" yaml:"teeVersion"` + TEEVersion AttestationVersion[uint8] `json:"teeVersion" yaml:"teeVersion"` // description: | // Lowest acceptable SEV-SNP version. - SNPVersion AttestationVersion `json:"snpVersion" yaml:"snpVersion"` + SNPVersion AttestationVersion[uint8] `json:"snpVersion" yaml:"snpVersion"` // description: | // Lowest acceptable microcode version. - MicrocodeVersion AttestationVersion `json:"microcodeVersion" yaml:"microcodeVersion"` + MicrocodeVersion AttestationVersion[uint8] `json:"microcodeVersion" yaml:"microcodeVersion"` // description: | // Configuration for validating the firmware signature. FirmwareSignerConfig SNPFirmwareSignerConfig `json:"firmwareSignerConfig" yaml:"firmwareSignerConfig"` @@ -1147,22 +1151,22 @@ type AzureTDX struct { Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"` // description: | // Minimum required QE security version number (SVN). - QESVN uint16 `json:"qeSVN" yaml:"qeSVN"` + QESVN AttestationVersion[uint16] `json:"qeSVN" yaml:"qeSVN"` // description: | // Minimum required PCE security version number (SVN). - PCESVN uint16 `json:"pceSVN" yaml:"pceSVN"` + PCESVN AttestationVersion[uint16] `json:"pceSVN" yaml:"pceSVN"` // description: | // Component-wise minimum required 16 byte hex-encoded TEE_TCB security version number (SVN). - TEETCBSVN encoding.HexBytes `json:"teeTCBSVN" yaml:"teeTCBSVN"` + TEETCBSVN AttestationVersion[encoding.HexBytes] `json:"teeTCBSVN" yaml:"teeTCBSVN"` // description: | // Expected 16 byte hex-encoded QE_VENDOR_ID field. - QEVendorID encoding.HexBytes `json:"qeVendorID" yaml:"qeVendorID"` + QEVendorID AttestationVersion[encoding.HexBytes] `json:"qeVendorID" yaml:"qeVendorID"` // description: | // Expected 48 byte hex-encoded MR_SEAM value. MRSeam encoding.HexBytes `json:"mrSeam,omitempty" yaml:"mrSeam,omitempty"` // description: | - // Expected 8 byte hex-encoded XFAM field. - XFAM encoding.HexBytes `json:"xfam" yaml:"xfam"` + // Expected 8 byte hex-encoded eXtended Features Available Mask (XFAM) field. Defaults to the latest available XFAM on Azure VMs. Unset to disable validation. + XFAM AttestationVersion[encoding.HexBytes] `json:"xfam" yaml:"xfam"` // description: | // Intel Root Key certificate used to verify the TDX certificate chain. IntelRootKey Certificate `json:"intelRootKey" yaml:"intelRootKey"` diff --git a/internal/config/config_doc.go b/internal/config/config_doc.go index f155db5c2..d26af1643 100644 --- a/internal/config/config_doc.go +++ b/internal/config/config_doc.go @@ -428,8 +428,8 @@ func init() { AttestationConfigDoc.Fields[6].Name = "gcpSEVSNP" AttestationConfigDoc.Fields[6].Type = "GCPSEVSNP" AttestationConfigDoc.Fields[6].Note = "" - AttestationConfigDoc.Fields[6].Description = "description: |\n GCP SEV-SNP attestation.\n" - AttestationConfigDoc.Fields[6].Comments[encoder.LineComment] = "description: |" + AttestationConfigDoc.Fields[6].Description = "GCP SEV-SNP attestation." + AttestationConfigDoc.Fields[6].Comments[encoder.LineComment] = "GCP SEV-SNP attestation." AttestationConfigDoc.Fields[7].Name = "qemuTDX" AttestationConfigDoc.Fields[7].Type = "QEMUTDX" AttestationConfigDoc.Fields[7].Note = "" @@ -545,22 +545,22 @@ func init() { GCPSEVSNPDoc.Fields[0].Description = "Expected TPM measurements." GCPSEVSNPDoc.Fields[0].Comments[encoder.LineComment] = "Expected TPM measurements." GCPSEVSNPDoc.Fields[1].Name = "bootloaderVersion" - GCPSEVSNPDoc.Fields[1].Type = "AttestationVersion" + GCPSEVSNPDoc.Fields[1].Type = "" GCPSEVSNPDoc.Fields[1].Note = "" GCPSEVSNPDoc.Fields[1].Description = "Lowest acceptable bootloader version." GCPSEVSNPDoc.Fields[1].Comments[encoder.LineComment] = "Lowest acceptable bootloader version." GCPSEVSNPDoc.Fields[2].Name = "teeVersion" - GCPSEVSNPDoc.Fields[2].Type = "AttestationVersion" + GCPSEVSNPDoc.Fields[2].Type = "" GCPSEVSNPDoc.Fields[2].Note = "" GCPSEVSNPDoc.Fields[2].Description = "Lowest acceptable TEE version." GCPSEVSNPDoc.Fields[2].Comments[encoder.LineComment] = "Lowest acceptable TEE version." GCPSEVSNPDoc.Fields[3].Name = "snpVersion" - GCPSEVSNPDoc.Fields[3].Type = "AttestationVersion" + GCPSEVSNPDoc.Fields[3].Type = "" GCPSEVSNPDoc.Fields[3].Note = "" GCPSEVSNPDoc.Fields[3].Description = "Lowest acceptable SEV-SNP version." GCPSEVSNPDoc.Fields[3].Comments[encoder.LineComment] = "Lowest acceptable SEV-SNP version." GCPSEVSNPDoc.Fields[4].Name = "microcodeVersion" - GCPSEVSNPDoc.Fields[4].Type = "AttestationVersion" + GCPSEVSNPDoc.Fields[4].Type = "" GCPSEVSNPDoc.Fields[4].Note = "" GCPSEVSNPDoc.Fields[4].Description = "Lowest acceptable microcode version." GCPSEVSNPDoc.Fields[4].Comments[encoder.LineComment] = "Lowest acceptable microcode version." @@ -623,22 +623,22 @@ func init() { AWSSEVSNPDoc.Fields[0].Description = "Expected TPM measurements." AWSSEVSNPDoc.Fields[0].Comments[encoder.LineComment] = "Expected TPM measurements." AWSSEVSNPDoc.Fields[1].Name = "bootloaderVersion" - AWSSEVSNPDoc.Fields[1].Type = "AttestationVersion" + AWSSEVSNPDoc.Fields[1].Type = "" AWSSEVSNPDoc.Fields[1].Note = "" AWSSEVSNPDoc.Fields[1].Description = "Lowest acceptable bootloader version." AWSSEVSNPDoc.Fields[1].Comments[encoder.LineComment] = "Lowest acceptable bootloader version." AWSSEVSNPDoc.Fields[2].Name = "teeVersion" - AWSSEVSNPDoc.Fields[2].Type = "AttestationVersion" + AWSSEVSNPDoc.Fields[2].Type = "" AWSSEVSNPDoc.Fields[2].Note = "" AWSSEVSNPDoc.Fields[2].Description = "Lowest acceptable TEE version." AWSSEVSNPDoc.Fields[2].Comments[encoder.LineComment] = "Lowest acceptable TEE version." AWSSEVSNPDoc.Fields[3].Name = "snpVersion" - AWSSEVSNPDoc.Fields[3].Type = "AttestationVersion" + AWSSEVSNPDoc.Fields[3].Type = "" AWSSEVSNPDoc.Fields[3].Note = "" AWSSEVSNPDoc.Fields[3].Description = "Lowest acceptable SEV-SNP version." AWSSEVSNPDoc.Fields[3].Comments[encoder.LineComment] = "Lowest acceptable SEV-SNP version." AWSSEVSNPDoc.Fields[4].Name = "microcodeVersion" - AWSSEVSNPDoc.Fields[4].Type = "AttestationVersion" + AWSSEVSNPDoc.Fields[4].Type = "" AWSSEVSNPDoc.Fields[4].Note = "" AWSSEVSNPDoc.Fields[4].Description = "Lowest acceptable microcode version." AWSSEVSNPDoc.Fields[4].Comments[encoder.LineComment] = "Lowest acceptable microcode version." @@ -685,22 +685,22 @@ func init() { AzureSEVSNPDoc.Fields[0].Description = "Expected TPM measurements." AzureSEVSNPDoc.Fields[0].Comments[encoder.LineComment] = "Expected TPM measurements." AzureSEVSNPDoc.Fields[1].Name = "bootloaderVersion" - AzureSEVSNPDoc.Fields[1].Type = "AttestationVersion" + AzureSEVSNPDoc.Fields[1].Type = "" AzureSEVSNPDoc.Fields[1].Note = "" AzureSEVSNPDoc.Fields[1].Description = "Lowest acceptable bootloader version." AzureSEVSNPDoc.Fields[1].Comments[encoder.LineComment] = "Lowest acceptable bootloader version." AzureSEVSNPDoc.Fields[2].Name = "teeVersion" - AzureSEVSNPDoc.Fields[2].Type = "AttestationVersion" + AzureSEVSNPDoc.Fields[2].Type = "" AzureSEVSNPDoc.Fields[2].Note = "" AzureSEVSNPDoc.Fields[2].Description = "Lowest acceptable TEE version." AzureSEVSNPDoc.Fields[2].Comments[encoder.LineComment] = "Lowest acceptable TEE version." AzureSEVSNPDoc.Fields[3].Name = "snpVersion" - AzureSEVSNPDoc.Fields[3].Type = "AttestationVersion" + AzureSEVSNPDoc.Fields[3].Type = "" AzureSEVSNPDoc.Fields[3].Note = "" AzureSEVSNPDoc.Fields[3].Description = "Lowest acceptable SEV-SNP version." AzureSEVSNPDoc.Fields[3].Comments[encoder.LineComment] = "Lowest acceptable SEV-SNP version." AzureSEVSNPDoc.Fields[4].Name = "microcodeVersion" - AzureSEVSNPDoc.Fields[4].Type = "AttestationVersion" + AzureSEVSNPDoc.Fields[4].Type = "" AzureSEVSNPDoc.Fields[4].Note = "" AzureSEVSNPDoc.Fields[4].Description = "Lowest acceptable microcode version." AzureSEVSNPDoc.Fields[4].Comments[encoder.LineComment] = "Lowest acceptable microcode version." @@ -752,22 +752,22 @@ func init() { AzureTDXDoc.Fields[0].Description = "Expected TPM measurements." AzureTDXDoc.Fields[0].Comments[encoder.LineComment] = "Expected TPM measurements." AzureTDXDoc.Fields[1].Name = "qeSVN" - AzureTDXDoc.Fields[1].Type = "uint16" + AzureTDXDoc.Fields[1].Type = "" AzureTDXDoc.Fields[1].Note = "" AzureTDXDoc.Fields[1].Description = "Minimum required QE security version number (SVN)." AzureTDXDoc.Fields[1].Comments[encoder.LineComment] = "Minimum required QE security version number (SVN)." AzureTDXDoc.Fields[2].Name = "pceSVN" - AzureTDXDoc.Fields[2].Type = "uint16" + AzureTDXDoc.Fields[2].Type = "" AzureTDXDoc.Fields[2].Note = "" AzureTDXDoc.Fields[2].Description = "Minimum required PCE security version number (SVN)." AzureTDXDoc.Fields[2].Comments[encoder.LineComment] = "Minimum required PCE security version number (SVN)." AzureTDXDoc.Fields[3].Name = "teeTCBSVN" - AzureTDXDoc.Fields[3].Type = "HexBytes" + AzureTDXDoc.Fields[3].Type = "" AzureTDXDoc.Fields[3].Note = "" AzureTDXDoc.Fields[3].Description = "Component-wise minimum required 16 byte hex-encoded TEE_TCB security version number (SVN)." AzureTDXDoc.Fields[3].Comments[encoder.LineComment] = "Component-wise minimum required 16 byte hex-encoded TEE_TCB security version number (SVN)." AzureTDXDoc.Fields[4].Name = "qeVendorID" - AzureTDXDoc.Fields[4].Type = "HexBytes" + AzureTDXDoc.Fields[4].Type = "" AzureTDXDoc.Fields[4].Note = "" AzureTDXDoc.Fields[4].Description = "Expected 16 byte hex-encoded QE_VENDOR_ID field." AzureTDXDoc.Fields[4].Comments[encoder.LineComment] = "Expected 16 byte hex-encoded QE_VENDOR_ID field." @@ -777,10 +777,10 @@ func init() { AzureTDXDoc.Fields[5].Description = "Expected 48 byte hex-encoded MR_SEAM value." AzureTDXDoc.Fields[5].Comments[encoder.LineComment] = "Expected 48 byte hex-encoded MR_SEAM value." AzureTDXDoc.Fields[6].Name = "xfam" - AzureTDXDoc.Fields[6].Type = "HexBytes" + AzureTDXDoc.Fields[6].Type = "" AzureTDXDoc.Fields[6].Note = "" - AzureTDXDoc.Fields[6].Description = "Expected 8 byte hex-encoded XFAM field." - AzureTDXDoc.Fields[6].Comments[encoder.LineComment] = "Expected 8 byte hex-encoded XFAM field." + AzureTDXDoc.Fields[6].Description = "Expected 8 byte hex-encoded eXtended Features Available Mask (XFAM) field. Defaults to the latest available XFAM on Azure VMs. Unset to disable validation." + AzureTDXDoc.Fields[6].Comments[encoder.LineComment] = "Expected 8 byte hex-encoded eXtended Features Available Mask (XFAM) field. Defaults to the latest available XFAM on Azure VMs. Unset to disable validation." AzureTDXDoc.Fields[7].Name = "intelRootKey" AzureTDXDoc.Fields[7].Type = "Certificate" AzureTDXDoc.Fields[7].Note = "" diff --git a/internal/config/config_test.go b/internal/config/config_test.go index fa9c0c2d0..5c60b26dc 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -70,10 +70,10 @@ func TestGetAttestationConfigMarshalsNumericalVersion(t *testing.T) { var mp map[string]interface{} require.NoError(yaml.Unmarshal(bt, &mp)) assert := assert.New(t) - assert.Equal(placeholderVersionValue, mp["microcodeVersion"]) - assert.Equal(placeholderVersionValue, mp["teeVersion"]) - assert.Equal(placeholderVersionValue, mp["snpVersion"]) - assert.Equal(placeholderVersionValue, mp["bootloaderVersion"]) + assert.EqualValues(placeholderVersionValue[uint8](), mp["microcodeVersion"]) + assert.EqualValues(placeholderVersionValue[uint8](), mp["teeVersion"]) + assert.EqualValues(placeholderVersionValue[uint8](), mp["snpVersion"]) + assert.EqualValues(placeholderVersionValue[uint8](), mp["bootloaderVersion"]) } func TestNew(t *testing.T) { @@ -99,19 +99,19 @@ func TestNew(t *testing.T) { wantResult: func() *Config { conf := Default() modifyConfigForAzureToPassValidate(conf) - conf.Attestation.AzureSEVSNP.MicrocodeVersion = AttestationVersion{ + conf.Attestation.AzureSEVSNP.MicrocodeVersion = AttestationVersion[uint8]{ Value: testCfg.Microcode, WantLatest: true, } - conf.Attestation.AzureSEVSNP.TEEVersion = AttestationVersion{ + conf.Attestation.AzureSEVSNP.TEEVersion = AttestationVersion[uint8]{ Value: 2, WantLatest: false, } - conf.Attestation.AzureSEVSNP.BootloaderVersion = AttestationVersion{ + conf.Attestation.AzureSEVSNP.BootloaderVersion = AttestationVersion[uint8]{ Value: 1, WantLatest: false, } - conf.Attestation.AzureSEVSNP.SNPVersion = AttestationVersion{ + conf.Attestation.AzureSEVSNP.SNPVersion = AttestationVersion[uint8]{ Value: testCfg.SNP, WantLatest: true, } @@ -466,7 +466,7 @@ func TestValidate(t *testing.T) { gcp.ServiceAccountKeyPath = "test-key-path" cnf.Provider = ProviderConfig{} cnf.Provider.GCP = gcp - cnf.Attestation.GCPSEVES.Measurements = measurements.M{ + cnf.Attestation.GCPSEVSNP.Measurements = measurements.M{ 0: measurements.WithAllBytes(0x00, measurements.Enforce, measurements.PCRMeasurementLength), } cnf.NodeGroups = map[string]NodeGroup{ @@ -624,11 +624,11 @@ func TestConfig_UpdateMeasurements(t *testing.T) { { // GCP conf := Default() conf.RemoveProviderAndAttestationExcept(cloudprovider.GCP) - for k := range conf.Attestation.GCPSEVES.Measurements { - delete(conf.Attestation.GCPSEVES.Measurements, k) + for k := range conf.Attestation.GCPSEVSNP.Measurements { + delete(conf.Attestation.GCPSEVSNP.Measurements, k) } conf.UpdateMeasurements(newMeasurements) - assert.Equal(newMeasurements, conf.Attestation.GCPSEVES.Measurements) + assert.Equal(newMeasurements, conf.Attestation.GCPSEVSNP.Measurements) } { // QEMU conf := Default() @@ -688,67 +688,80 @@ func TestValidInstanceTypeForProvider(t *testing.T) { testCases := map[string]struct { variant variant.Variant instanceTypes []string + providerConfig ProviderConfig expectedResult bool }{ "empty all": { variant: variant.Dummy{}, instanceTypes: []string{}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "empty aws": { variant: variant.AWSSEVSNP{}, instanceTypes: []string{}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "empty azure only CVMs": { variant: variant.AzureSEVSNP{}, instanceTypes: []string{}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "empty azure with non-CVMs": { variant: variant.AzureTrustedLaunch{}, instanceTypes: []string{}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "empty gcp": { variant: variant.GCPSEVES{}, instanceTypes: []string{}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "azure only CVMs (SNP)": { variant: variant.AzureSEVSNP{}, instanceTypes: instancetypes.AzureSNPInstanceTypes, expectedResult: true, + providerConfig: ProviderConfig{}, }, "azure only CVMs (TDX)": { variant: variant.AzureTDX{}, instanceTypes: instancetypes.AzureTDXInstanceTypes, expectedResult: true, + providerConfig: ProviderConfig{}, }, "azure trusted launch VMs": { variant: variant.AzureTrustedLaunch{}, instanceTypes: instancetypes.AzureTrustedLaunchInstanceTypes, expectedResult: true, + providerConfig: ProviderConfig{}, }, "gcp": { variant: variant.GCPSEVES{}, instanceTypes: instancetypes.GCPInstanceTypes, expectedResult: true, + providerConfig: ProviderConfig{}, }, "gcp sev-snp": { variant: variant.GCPSEVSNP{}, instanceTypes: instancetypes.GCPInstanceTypes, expectedResult: true, + providerConfig: ProviderConfig{}, }, "put gcp when azure is set": { variant: variant.AzureSEVSNP{}, instanceTypes: instancetypes.GCPInstanceTypes, expectedResult: false, + providerConfig: ProviderConfig{}, }, "put azure when gcp is set": { variant: variant.GCPSEVES{}, instanceTypes: instancetypes.AzureSNPInstanceTypes, expectedResult: false, + providerConfig: ProviderConfig{}, }, // Testing every possible instance type for AWS is not feasible, so we just test a few based on known supported / unsupported families // Also serves as a test for checkIfInstanceInValidAWSFamilys @@ -756,31 +769,79 @@ func TestValidInstanceTypeForProvider(t *testing.T) { variant: variant.AWSSEVSNP{}, instanceTypes: []string{"c5.xlarge", "c5a.2xlarge", "c5a.16xlarge", "u-12tb1.112xlarge"}, expectedResult: false, // False because 2 two of the instances are not valid + providerConfig: ProviderConfig{}, }, "aws one valid instance one with too little vCPUs": { variant: variant.AWSSEVSNP{}, instanceTypes: []string{"c5.medium"}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "aws graviton sub-family unsupported": { variant: variant.AWSSEVSNP{}, instanceTypes: []string{"m6g.xlarge", "r6g.2xlarge", "x2gd.xlarge", "g5g.8xlarge"}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "aws combined two valid instances as one string": { variant: variant.AWSSEVSNP{}, instanceTypes: []string{"c5.xlarge, c5a.2xlarge"}, expectedResult: false, + providerConfig: ProviderConfig{}, }, "aws only CVMs": { variant: variant.AWSSEVSNP{}, instanceTypes: []string{"c6a.xlarge", "m6a.xlarge", "r6a.xlarge"}, expectedResult: true, + providerConfig: ProviderConfig{}, }, "aws nitroTPM VMs": { variant: variant.AWSNitroTPM{}, instanceTypes: []string{"c5.xlarge", "c5a.2xlarge", "c5a.16xlarge", "u-12tb1.112xlarge"}, expectedResult: true, + providerConfig: ProviderConfig{}, + }, + "stackit valid flavors": { + variant: variant.QEMUVTPM{}, + instanceTypes: []string{ + "m1a.2cd", + "m1a.4cd", + "m1a.8cd", + "m1a.16cd", + "m1a.30cd", + }, + expectedResult: true, + providerConfig: ProviderConfig{OpenStack: &OpenStackConfig{Cloud: "stackit"}}, + }, + "stackit not valid flavors": { + variant: variant.QEMUVTPM{}, + instanceTypes: []string{ + // removed the c which indicates a confidential flavor + "m1a.2d", + "m1a.4d", + "m1a.8d", + "m1a.16d", + "m1a.30d", + }, + expectedResult: false, + providerConfig: ProviderConfig{OpenStack: &OpenStackConfig{Cloud: "stackit"}}, + }, + "openstack cloud named test": { + variant: variant.QEMUVTPM{}, + instanceTypes: []string{ + "foo.bar", + "foo.bar1", + }, + expectedResult: true, + providerConfig: ProviderConfig{OpenStack: &OpenStackConfig{Cloud: "test"}}, + }, + "Qemutdx valid instance type": { + variant: variant.QEMUTDX{}, + instanceTypes: []string{ + "foo.bar", + }, + expectedResult: true, + providerConfig: ProviderConfig{QEMU: &QEMUConfig{}}, }, } for name, tc := range testCases { @@ -788,7 +849,7 @@ func TestValidInstanceTypeForProvider(t *testing.T) { assert := assert.New(t) for _, instanceType := range tc.instanceTypes { assert.Equal( - tc.expectedResult, validInstanceTypeForProvider(instanceType, tc.variant), + tc.expectedResult, validInstanceTypeForProvider(instanceType, tc.variant, tc.providerConfig), instanceType, ) } @@ -1051,18 +1112,8 @@ func getConfigAsMap(conf *Config, t *testing.T) (res configMap) { type stubAttestationFetcher struct{} -func (f stubAttestationFetcher) FetchSEVSNPVersionList(_ context.Context, _ attestationconfigapi.SEVSNPVersionList) (attestationconfigapi.SEVSNPVersionList, error) { - return attestationconfigapi.SEVSNPVersionList{}, nil -} - -func (f stubAttestationFetcher) FetchSEVSNPVersion(_ context.Context, _ attestationconfigapi.SEVSNPVersionAPI) (attestationconfigapi.SEVSNPVersionAPI, error) { - return attestationconfigapi.SEVSNPVersionAPI{ - SEVSNPVersion: testCfg, - }, nil -} - -func (f stubAttestationFetcher) FetchSEVSNPVersionLatest(_ context.Context, _ variant.Variant) (attestationconfigapi.SEVSNPVersionAPI, error) { - return attestationconfigapi.SEVSNPVersionAPI{ +func (f stubAttestationFetcher) FetchLatestVersion(_ context.Context, _ variant.Variant) (attestationconfigapi.Entry, error) { + return attestationconfigapi.Entry{ SEVSNPVersion: testCfg, }, nil } diff --git a/internal/config/gcp.go b/internal/config/gcp.go index 847474f05..20f8eaac5 100644 --- a/internal/config/gcp.go +++ b/internal/config/gcp.go @@ -22,10 +22,10 @@ var _ svnResolveMarshaller = &GCPSEVSNP{} func DefaultForGCPSEVSNP() *GCPSEVSNP { return &GCPSEVSNP{ Measurements: measurements.DefaultsFor(cloudprovider.GCP, variant.GCPSEVSNP{}), - BootloaderVersion: NewLatestPlaceholderVersion(), - TEEVersion: NewLatestPlaceholderVersion(), - SNPVersion: NewLatestPlaceholderVersion(), - MicrocodeVersion: NewLatestPlaceholderVersion(), + BootloaderVersion: NewLatestPlaceholderVersion[uint8](), + TEEVersion: NewLatestPlaceholderVersion[uint8](), + SNPVersion: NewLatestPlaceholderVersion[uint8](), + MicrocodeVersion: NewLatestPlaceholderVersion[uint8](), AMDRootKey: mustParsePEM(arkPEM), } } @@ -79,7 +79,7 @@ func (c *GCPSEVSNP) FetchAndSetLatestVersionNumbers(ctx context.Context, fetcher return nil } - versions, err := fetcher.FetchSEVSNPVersionLatest(ctx, variant.GCPSEVSNP{}) + versions, err := fetcher.FetchLatestVersion(ctx, variant.GCPSEVSNP{}) if err != nil { return fmt.Errorf("fetching latest TCB versions from configapi: %w", err) } diff --git a/internal/config/image_enterprise.go b/internal/config/image_enterprise.go index ffe0ac0ec..9bd6dd0fd 100644 --- a/internal/config/image_enterprise.go +++ b/internal/config/image_enterprise.go @@ -10,5 +10,5 @@ package config const ( // defaultImage is the default image to use. - defaultImage = "ref/main/stream/nightly/v2.17.0-pre.0.20240516182331-5fb2a2cb89f2" + defaultImage = "ref/main/stream/nightly/v2.20.0-pre.0.20241128194937-5977f0f5b1d3" ) diff --git a/internal/config/migration/migration.go b/internal/config/migration/migration.go index 54ca54335..d8fdd659c 100644 --- a/internal/config/migration/migration.go +++ b/internal/config/migration/migration.go @@ -415,19 +415,19 @@ func V3ToV4(path string, fileHandler file.Handler) error { case cfgV3.Attestation.AzureSEVSNP != nil: cfgV4.Attestation.AzureSEVSNP = &config.AzureSEVSNP{ Measurements: cfgV3.Attestation.AzureSEVSNP.Measurements, - BootloaderVersion: config.AttestationVersion{ + BootloaderVersion: config.AttestationVersion[uint8]{ Value: cfgV3.Attestation.AzureSEVSNP.BootloaderVersion.Value, WantLatest: cfgV3.Attestation.AzureSEVSNP.BootloaderVersion.WantLatest, }, - TEEVersion: config.AttestationVersion{ + TEEVersion: config.AttestationVersion[uint8]{ Value: cfgV3.Attestation.AzureSEVSNP.TEEVersion.Value, WantLatest: cfgV3.Attestation.AzureSEVSNP.TEEVersion.WantLatest, }, - SNPVersion: config.AttestationVersion{ + SNPVersion: config.AttestationVersion[uint8]{ Value: cfgV3.Attestation.AzureSEVSNP.SNPVersion.Value, WantLatest: cfgV3.Attestation.AzureSEVSNP.SNPVersion.WantLatest, }, - MicrocodeVersion: config.AttestationVersion{ + MicrocodeVersion: config.AttestationVersion[uint8]{ Value: cfgV3.Attestation.AzureSEVSNP.MicrocodeVersion.Value, WantLatest: cfgV3.Attestation.AzureSEVSNP.MicrocodeVersion.WantLatest, }, diff --git a/internal/config/validation.go b/internal/config/validation.go index fab69ff29..ebd39512f 100644 --- a/internal/config/validation.go +++ b/internal/config/validation.go @@ -250,7 +250,7 @@ func translateNoAttestationError(ut ut.Translator, fe validator.FieldError) stri } func registerNoAttestationError(ut ut.Translator) error { - return ut.Add("no_attestation", "{0}: No attestation has been defined (requires either awsSEVSNP, awsNitroTPM, azureSEVSNP, azureTDX, azureTrustedLaunch, gcpSEVES, or qemuVTPM)", true) + return ut.Add("no_attestation", "{0}: No attestation has been defined (requires either awsSEVSNP, awsNitroTPM, azureSEVSNP, azureTDX, azureTrustedLaunch, gcpSEVES, gcpSEVSNP, or qemuVTPM)", true) } func translateNoDefaultControlPlaneGroupError(ut ut.Translator, fe validator.FieldError) string { @@ -520,7 +520,7 @@ func (c *Config) translateMoreThanOneProviderError(ut ut.Translator, fe validato return t } -func validInstanceTypeForProvider(insType string, attestation variant.Variant) bool { +func validInstanceTypeForProvider(insType string, attestation variant.Variant, provider ProviderConfig) bool { switch attestation { case variant.AWSSEVSNP{}, variant.AWSNitroTPM{}: return isSupportedAWSInstanceType(insType, attestation.Equal(variant.AWSNitroTPM{})) @@ -549,6 +549,17 @@ func validInstanceTypeForProvider(insType string, attestation variant.Variant) b } } case variant.QEMUVTPM{}, variant.QEMUTDX{}: + // only allow confidential instances on stackit cloud using QEMU vTPM + if provider.OpenStack != nil { + if cloud := provider.OpenStack.Cloud; strings.ToLower(cloud) == "stackit" { + for _, instanceType := range instancetypes.STACKITInstanceTypes { + if insType == instanceType { + return true + } + } + return false + } + } return true } return false @@ -789,7 +800,7 @@ func (c *Config) validateNodeGroupZoneField(fl validator.FieldLevel) bool { } func (c *Config) validateInstanceType(fl validator.FieldLevel) bool { - return validInstanceTypeForProvider(fl.Field().String(), c.GetAttestationConfig().GetVariant()) + return validInstanceTypeForProvider(fl.Field().String(), c.GetAttestationConfig().GetVariant(), c.Provider) } func (c *Config) validateStateDiskTypeField(fl validator.FieldLevel) bool { diff --git a/internal/constellation/BUILD.bazel b/internal/constellation/BUILD.bazel index 58bd5d235..02afff0e9 100644 --- a/internal/constellation/BUILD.bazel +++ b/internal/constellation/BUILD.bazel @@ -37,8 +37,13 @@ go_library( "//internal/semver", "//internal/versions", "@io_k8s_apiextensions_apiserver//pkg/apis/apiextensions/v1:apiextensions", + "@io_k8s_apimachinery//pkg/api/errors", + "@io_k8s_apimachinery//pkg/apis/meta/v1:meta", + "@io_k8s_apimachinery//pkg/runtime/schema", + "@io_k8s_apimachinery//pkg/types", + "@io_k8s_client_go//dynamic", "@io_k8s_client_go//tools/clientcmd", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", ], ) @@ -69,6 +74,6 @@ go_test( "@com_github_stretchr_testify//require", "@io_k8s_client_go//tools/clientcmd", "@io_k8s_client_go//tools/clientcmd/api", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", ], ) diff --git a/internal/constellation/apply.go b/internal/constellation/apply.go index c9844b435..a9f9228dd 100644 --- a/internal/constellation/apply.go +++ b/internal/constellation/apply.go @@ -18,6 +18,8 @@ import ( "github.com/edgelesssys/constellation/v2/internal/grpc/dialer" "github.com/edgelesssys/constellation/v2/internal/kms/uri" "github.com/edgelesssys/constellation/v2/internal/license" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/tools/clientcmd" ) // ApplyContext denotes the context in which the apply command is run. @@ -44,6 +46,7 @@ type Applier struct { newDialer func(validator atls.Validator) *dialer.Dialer kubecmdClient kubecmdClient helmClient helmApplier + dynamicClient dynamic.Interface } type licenseChecker interface { @@ -79,8 +82,17 @@ func (a *Applier) SetKubeConfig(kubeConfig []byte) error { if err != nil { return err } + restConfig, err := clientcmd.RESTConfigFromKubeConfig(kubeConfig) + if err != nil { + return err + } + dynamicClient, err := dynamic.NewForConfig(restConfig) + if err != nil { + return err + } a.kubecmdClient = kubecmdClient a.helmClient = helmClient + a.dynamicClient = dynamicClient return nil } diff --git a/internal/constellation/applyinit.go b/internal/constellation/applyinit.go index 9b34abf77..bfc7ac085 100644 --- a/internal/constellation/applyinit.go +++ b/internal/constellation/applyinit.go @@ -42,7 +42,7 @@ type InitPayload struct { // GrpcDialer dials a gRPC server. type GrpcDialer interface { - Dial(ctx context.Context, target string) (*grpc.ClientConn, error) + Dial(target string) (*grpc.ClientConn, error) } // Init performs the init RPC. @@ -173,7 +173,7 @@ func (d *initDoer) Do(ctx context.Context) error { } } - conn, err := d.dialer.Dial(ctx, d.endpoint) + conn, err := d.dialer.Dial(d.endpoint) if err != nil { d.log.Debug(fmt.Sprintf("Dialing init server failed: %q. Retrying...", err)) return fmt.Errorf("dialing init server: %w", err) diff --git a/internal/constellation/helm.go b/internal/constellation/helm.go index 1378ce3a0..ed1345459 100644 --- a/internal/constellation/helm.go +++ b/internal/constellation/helm.go @@ -7,13 +7,74 @@ SPDX-License-Identifier: AGPL-3.0-only package constellation import ( + "context" "errors" + "fmt" "github.com/edgelesssys/constellation/v2/internal/constellation/helm" "github.com/edgelesssys/constellation/v2/internal/constellation/state" "github.com/edgelesssys/constellation/v2/internal/kms/uri" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" ) +var patch = []byte(fmt.Sprintf(`{"metadata": {"labels": {%q: %q}, "annotations": {%q: %q, %q: %q}}}`, + "app.kubernetes.io/managed-by", "Helm", + "meta.helm.sh/release-name", "coredns", + "meta.helm.sh/release-namespace", "kube-system")) + +var namespacedCoreDNSResources = map[schema.GroupVersionResource]string{ + {Group: "apps", Version: "v1", Resource: "deployments"}: "coredns", + {Group: "", Version: "v1", Resource: "services"}: "kube-dns", + {Group: "", Version: "v1", Resource: "configmaps"}: "coredns", + {Group: "", Version: "v1", Resource: "serviceaccounts"}: "coredns", + {Group: "apps", Version: "v1", Resource: "statefulsets"}: "foobarbax", +} + +var coreDNSResources = map[schema.GroupVersionResource]string{ + {Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterroles"}: "system:coredns", + {Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterrolebindings"}: "system:coredns", +} + +// AnnotateCoreDNSResources imports existing CoreDNS resources into the Helm release. +// +// This is only required when CoreDNS was installed by kubeadm directly. +// TODO(burgerdev): remove after v2.19 is released. +func (a *Applier) AnnotateCoreDNSResources(ctx context.Context) error { + for gvk, name := range coreDNSResources { + _, err := a.dynamicClient.Resource(gvk).Patch(ctx, name, types.StrategicMergePatchType, patch, v1.PatchOptions{}) + if err != nil && !k8serrors.IsNotFound(err) { + return err + } + } + + for gvk, name := range namespacedCoreDNSResources { + _, err := a.dynamicClient.Resource(gvk).Namespace("kube-system").Patch(ctx, name, types.StrategicMergePatchType, patch, v1.PatchOptions{}) + if err != nil && !k8serrors.IsNotFound(err) { + return err + } + } + + return nil +} + +// CleanupCoreDNSResources removes CoreDNS resources that are not managed by Helm. +// +// This is only required when CoreDNS was installed by kubeadm directly. +// TODO(burgerdev): remove after v2.19 is released. +func (a *Applier) CleanupCoreDNSResources(ctx context.Context) error { + err := a.dynamicClient. + Resource(schema.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"}). + Namespace("kube-system"). + Delete(ctx, "coredns", v1.DeleteOptions{}) + if !k8serrors.IsNotFound(err) { + return err + } + return nil +} + // PrepareHelmCharts loads Helm charts for Constellation and returns an executor to apply them. func (a *Applier) PrepareHelmCharts( flags helm.Options, state *state.State, serviceAccURI string, masterSecret uri.MasterSecret, diff --git a/internal/constellation/helm/BUILD.bazel b/internal/constellation/helm/BUILD.bazel index 6e3c5eee7..928681b90 100644 --- a/internal/constellation/helm/BUILD.bazel +++ b/internal/constellation/helm/BUILD.bazel @@ -457,6 +457,22 @@ go_library( "charts/yawol/charts/yawol-controller/values.yaml", "charts/yawol/templates/.gitkeep", "charts/yawol/values.yaml", + "charts/edgeless/csi/charts/aws-csi-driver/templates/_node-windows.tpl", + "charts/edgeless/csi/charts/aws-csi-driver/templates/_node.tpl", + "charts/edgeless/csi/charts/aws-csi-driver/templates/ebs-csi-default-sc.yaml", + "charts/edgeless/csi/charts/aws-csi-driver/templates/role-leases.yaml", + "charts/edgeless/csi/charts/aws-csi-driver/templates/rolebinding-leases.yaml", + "charts/cert-manager/templates/cainjector-config.yaml", + "charts/cert-manager/templates/extras-objects.yaml", + "charts/cert-manager/templates/podmonitor.yaml", + "charts/coredns/Chart.yaml", + "charts/coredns/values.yaml", + "charts/coredns/templates/clusterrole.yaml", + "charts/coredns/templates/clusterrolebinding.yaml", + "charts/coredns/templates/configmap.yaml", + "charts/coredns/templates/deployment.yaml", + "charts/coredns/templates/service.yaml", + "charts/coredns/templates/serviceaccount.yaml", ], importpath = "github.com/edgelesssys/constellation/v2/internal/constellation/helm", visibility = ["//:__subpackages__"], @@ -484,11 +500,12 @@ go_library( "@io_k8s_client_go//restmapper", "@io_k8s_client_go//tools/clientcmd", "@io_k8s_client_go//util/retry", - "@sh_helm_helm//pkg/ignore", + "@io_k8s_kubernetes//cmd/kubeadm/app/constants", "@sh_helm_helm_v3//pkg/action", "@sh_helm_helm_v3//pkg/chart", "@sh_helm_helm_v3//pkg/chart/loader", "@sh_helm_helm_v3//pkg/chartutil", + "@sh_helm_helm_v3//pkg/ignore", "@sh_helm_helm_v3//pkg/release", ], ) diff --git a/internal/constellation/helm/charts/cert-manager/Chart.yaml b/internal/constellation/helm/charts/cert-manager/Chart.yaml index 7a8e8043b..aea96934f 100644 --- a/internal/constellation/helm/charts/cert-manager/Chart.yaml +++ b/internal/constellation/helm/charts/cert-manager/Chart.yaml @@ -1,13 +1,15 @@ annotations: + artifacthub.io/category: security + artifacthub.io/license: Apache-2.0 artifacthub.io/prerelease: "false" artifacthub.io/signKey: | fingerprint: 1020CF3C033D4F35BAE1C19E1226061C665DF13E url: https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg -apiVersion: v1 -appVersion: v1.12.6 +apiVersion: v2 +appVersion: v1.15.0 description: A Helm chart for cert-manager -home: https://github.com/cert-manager/cert-manager -icon: https://raw.githubusercontent.com/cert-manager/cert-manager/d53c0b9270f8cd90d908460d69502694e1838f5f/logo/logo-small.png +home: https://cert-manager.io +icon: https://raw.githubusercontent.com/cert-manager/community/4d35a69437d21b76322157e6284be4cd64e6d2b7/logo/logo-small.png keywords: - cert-manager - kube-lego @@ -21,4 +23,4 @@ maintainers: name: cert-manager sources: - https://github.com/cert-manager/cert-manager -version: v1.12.6 +version: v1.15.0 diff --git a/internal/constellation/helm/charts/cert-manager/templates/NOTES.txt b/internal/constellation/helm/charts/cert-manager/templates/NOTES.txt index 102535460..341d10123 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/NOTES.txt +++ b/internal/constellation/helm/charts/cert-manager/templates/NOTES.txt @@ -1,3 +1,6 @@ +{{- if .Values.installCRDs }} +⚠️ WARNING: `installCRDs` is deprecated, use `crds.enabled` instead. +{{- end }} cert-manager {{ .Chart.AppVersion }} has been deployed successfully! In order to begin issuing certificates, you will need to set up a ClusterIssuer diff --git a/internal/constellation/helm/charts/cert-manager/templates/_helpers.tpl b/internal/constellation/helm/charts/cert-manager/templates/_helpers.tpl index 90db4af26..9902c089f 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/_helpers.tpl +++ b/internal/constellation/helm/charts/cert-manager/templates/_helpers.tpl @@ -172,3 +172,31 @@ https://github.com/helm/helm/issues/5358 {{- define "cert-manager.namespace" -}} {{ .Values.namespace | default .Release.Namespace }} {{- end -}} + +{{/* +Util function for generating the image URL based on the provided options. +IMPORTANT: This function is standarized across all charts in the cert-manager GH organization. +Any changes to this function should also be made in cert-manager, trust-manager, approver-policy, ... +See https://github.com/cert-manager/cert-manager/issues/6329 for a list of linked PRs. +*/}} +{{- define "image" -}} +{{- $defaultTag := index . 1 -}} +{{- with index . 0 -}} +{{- if .registry -}}{{ printf "%s/%s" .registry .repository }}{{- else -}}{{- .repository -}}{{- end -}} +{{- if .digest -}}{{ printf "@%s" .digest }}{{- else -}}{{ printf ":%s" (default $defaultTag .tag) }}{{- end -}} +{{- end }} +{{- end }} + +{{/* +Check that the user has not set both .installCRDs and .crds.enabled or +set .installCRDs and disabled .crds.keep. +.installCRDs is deprecated and users should use .crds.enabled and .crds.keep instead. +*/}} +{{- define "cert-manager.crd-check" -}} + {{- if and (.Values.installCRDs) (.Values.crds.enabled) }} + {{- fail "ERROR: the deprecated .installCRDs option cannot be enabled at the same time as its replacement .crds.enabled" }} + {{- end }} + {{- if and (.Values.installCRDs) (not .Values.crds.keep) }} + {{- fail "ERROR: .crds.keep is not compatible with .installCRDs, please use .crds.enabled and .crds.keep instead" }} + {{- end }} +{{- end -}} diff --git a/internal/constellation/helm/charts/cert-manager/templates/cainjector-config.yaml b/internal/constellation/helm/charts/cert-manager/templates/cainjector-config.yaml new file mode 100644 index 000000000..82399cc1a --- /dev/null +++ b/internal/constellation/helm/charts/cert-manager/templates/cainjector-config.yaml @@ -0,0 +1,18 @@ +{{- if .Values.cainjector.config -}} +{{- $_ := .Values.cainjector.config.apiVersion | required ".Values.cainjector.config.apiVersion must be set !" -}} +{{- $_ := .Values.cainjector.config.kind | required ".Values.cainjector.config.kind must be set !" -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "cainjector.fullname" . }} + namespace: {{ include "cert-manager.namespace" . }} + labels: + app: {{ include "cainjector.name" . }} + app.kubernetes.io/name: {{ include "cainjector.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "cainjector" + {{- include "labels" . | nindent 4 }} +data: + config.yaml: | + {{- .Values.cainjector.config | toYaml | nindent 4 }} +{{- end -}} \ No newline at end of file diff --git a/internal/constellation/helm/charts/cert-manager/templates/cainjector-deployment.yaml b/internal/constellation/helm/charts/cert-manager/templates/cainjector-deployment.yaml index 122017374..8f9f7f331 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/cainjector-deployment.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/cainjector-deployment.yaml @@ -16,6 +16,10 @@ metadata: {{- end }} spec: replicas: {{ .Values.cainjector.replicaCount }} + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.revisionHistoryLimit) (list "" (quote ""))) }} + revisionHistoryLimit: {{ .Values.global.revisionHistoryLimit }} + {{- end }} selector: matchLabels: app.kubernetes.io/name: {{ include "cainjector.name" . }} @@ -45,6 +49,7 @@ spec: {{- if hasKey .Values.cainjector "automountServiceAccountToken" }} automountServiceAccountToken: {{ .Values.cainjector.automountServiceAccountToken }} {{- end }} + enableServiceLinks: {{ .Values.cainjector.enableServiceLinks }} {{- with .Values.global.priorityClassName }} priorityClassName: {{ . | quote }} {{- end }} @@ -54,14 +59,16 @@ spec: {{- end }} containers: - name: {{ .Chart.Name }}-cainjector - {{- with .Values.cainjector.image }} - image: "{{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}}" - {{- end }} + image: "{{ template "image" (tuple .Values.cainjector.image $.Chart.AppVersion) }}" imagePullPolicy: {{ .Values.cainjector.image.pullPolicy }} args: - {{- if .Values.global.logLevel }} + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.logLevel) (list "" (quote ""))) }} - --v={{ .Values.global.logLevel }} {{- end }} + {{- if .Values.cainjector.config }} + - --config=/var/cert-manager/config/config.yaml + {{- end }} {{- with .Values.global.leaderElection }} - --leader-election-namespace={{ .namespace }} {{- if .leaseDuration }} @@ -74,6 +81,9 @@ spec: - --leader-election-retry-period={{ .retryPeriod }} {{- end }} {{- end }} + {{- with .Values.cainjector.featureGates}} + - --feature-gates={{ . }} + {{- end}} {{- with .Values.cainjector.extraArgs }} {{- toYaml . | nindent 10 }} {{- end }} @@ -90,9 +100,15 @@ spec: resources: {{- toYaml . | nindent 12 }} {{- end }} - {{- with .Values.cainjector.volumeMounts }} + {{- if or .Values.cainjector.config .Values.cainjector.volumeMounts }} volumeMounts: + {{- if .Values.cainjector.config }} + - name: config + mountPath: /var/cert-manager/config + {{- end }} + {{- with .Values.cainjector.volumeMounts }} {{- toYaml . | nindent 12 }} + {{- end }} {{- end }} {{- with .Values.cainjector.nodeSelector }} nodeSelector: @@ -110,8 +126,15 @@ spec: topologySpreadConstraints: {{- toYaml . | nindent 8 }} {{- end }} - {{- with .Values.cainjector.volumes }} + {{- if or .Values.cainjector.volumes .Values.cainjector.config }} volumes: + {{- if .Values.cainjector.config }} + - name: config + configMap: + name: {{ include "cainjector.fullname" . }} + {{- end }} + {{ with .Values.cainjector.volumes }} {{- toYaml . | nindent 8 }} + {{- end }} {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/cainjector-poddisruptionbudget.yaml b/internal/constellation/helm/charts/cert-manager/templates/cainjector-poddisruptionbudget.yaml index f080b753a..6a7d60913 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/cainjector-poddisruptionbudget.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/cainjector-poddisruptionbudget.yaml @@ -17,10 +17,13 @@ spec: app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/component: "cainjector" - {{- with .Values.cainjector.podDisruptionBudget.minAvailable }} - minAvailable: {{ . }} + {{- if not (or (hasKey .Values.cainjector.podDisruptionBudget "minAvailable") (hasKey .Values.cainjector.podDisruptionBudget "maxUnavailable")) }} + minAvailable: 1 # Default value because minAvailable and maxUnavailable are not set {{- end }} - {{- with .Values.cainjector.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ . }} + {{- if hasKey .Values.cainjector.podDisruptionBudget "minAvailable" }} + minAvailable: {{ .Values.cainjector.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if hasKey .Values.cainjector.podDisruptionBudget "maxUnavailable" }} + maxUnavailable: {{ .Values.cainjector.podDisruptionBudget.maxUnavailable }} {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/controller-config.yaml b/internal/constellation/helm/charts/cert-manager/templates/controller-config.yaml index a1b337572..25f62ef1d 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/controller-config.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/controller-config.yaml @@ -1,12 +1,6 @@ {{- if .Values.config -}} - {{- if not .Values.config.apiVersion -}} - {{- fail "config.apiVersion must be set" -}} - {{- end -}} - - {{- if not .Values.config.kind -}} - {{- fail "config.kind must be set" -}} - {{- end -}} -{{- end -}} +{{- $_ := .Values.config.apiVersion | required ".Values.config.apiVersion must be set !" -}} +{{- $_ := .Values.config.kind | required ".Values.config.kind must be set !" -}} apiVersion: v1 kind: ConfigMap metadata: @@ -19,7 +13,6 @@ metadata: app.kubernetes.io/component: "controller" {{- include "labels" . | nindent 4 }} data: - {{- if .Values.config }} config.yaml: | - {{ .Values.config | toYaml | nindent 4 }} - {{- end }} + {{- .Values.config | toYaml | nindent 4 }} +{{- end -}} \ No newline at end of file diff --git a/internal/constellation/helm/charts/cert-manager/templates/crds.yaml b/internal/constellation/helm/charts/cert-manager/templates/crds.yaml index 820698742..2c70ca34c 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/crds.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/crds.yaml @@ -1,8 +1,13 @@ -{{- if .Values.installCRDs }} +# {{- include "cert-manager.crd-check" . }} +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: certificaterequests.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} labels: app: '{{ template "cert-manager.name" . }}' app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' @@ -51,47 +56,91 @@ spec: type: date schema: openAPIV3Schema: - description: "A CertificateRequest is used to request a signed certificate from one of the configured issuers. \n All fields within the CertificateRequest's `spec` are immutable after creation. A CertificateRequest will either succeed or fail, as denoted by its `status.state` field. \n A CertificateRequest is a one-shot resource, meaning it represents a single point in time request for a certificate and cannot be re-used." + description: |- + A CertificateRequest is used to request a signed certificate from one of the + configured issuers. + + + All fields within the CertificateRequest's `spec` are immutable after creation. + A CertificateRequest will either succeed or fail, as denoted by its `Ready` status + condition and its `status.failureTime` field. + + + A CertificateRequest is a one-shot resource, meaning it represents a single + point in time request for a certificate and cannot be re-used. type: object - required: - - spec properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: Desired state of the CertificateRequest resource. + description: |- + Specification of the desired state of the CertificateRequest resource. + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status type: object required: - issuerRef - request properties: duration: - description: The requested 'duration' (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types. + description: |- + Requested 'duration' (i.e. lifetime) of the Certificate. Note that the + issuer may choose to ignore the requested duration, just like any other + requested attribute. type: string extra: - description: Extra contains extra attributes of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + description: |- + Extra contains extra attributes of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. type: object additionalProperties: type: array items: type: string groups: - description: Groups contains group membership of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + description: |- + Groups contains group membership of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. type: array items: type: string x-kubernetes-list-type: atomic isCA: - description: IsCA will request to mark the certificate as valid for certificate signing when submitting to the issuer. This will automatically add the `cert sign` usage to the list of `usages`. + description: |- + Requested basic constraints isCA value. Note that the issuer may choose + to ignore the requested isCA value, just like any other requested attribute. + + + NOTE: If the CSR in the `Request` field has a BasicConstraints extension, + it must have the same isCA value as specified here. + + + If true, this will automatically add the `cert sign` usage to the list + of requested `usages`. type: boolean issuerRef: - description: IssuerRef is a reference to the issuer for this CertificateRequest. If the `kind` field is not set, or set to `Issuer`, an Issuer resource with the given name in the same namespace as the CertificateRequest will be used. If the `kind` field is set to `ClusterIssuer`, a ClusterIssuer with the provided name will be used. The `name` field in this stanza is required at all times. The group field refers to the API group of the issuer which defaults to `cert-manager.io` if empty. + description: |- + Reference to the issuer responsible for issuing the certificate. + If the issuer is namespace-scoped, it must be in the same namespace + as the Certificate. If the issuer is cluster-scoped, it can be used + from any namespace. + + + The `name` field of the reference must always be specified. type: object required: - name @@ -106,17 +155,69 @@ spec: description: Name of the resource being referred to. type: string request: - description: The PEM-encoded x509 certificate signing request to be submitted to the CA for signing. + description: |- + The PEM-encoded X.509 certificate signing request to be submitted to the + issuer for signing. + + + If the CSR has a BasicConstraints extension, its isCA attribute must + match the `isCA` value of this CertificateRequest. + If the CSR has a KeyUsage extension, its key usages must match the + key usages in the `usages` field of this CertificateRequest. + If the CSR has a ExtKeyUsage extension, its extended key usages + must match the extended key usages in the `usages` field of this + CertificateRequest. type: string format: byte uid: - description: UID contains the uid of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + description: |- + UID contains the uid of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. type: string usages: - description: Usages is the set of x509 usages that are requested for the certificate. If usages are set they SHOULD be encoded inside the CSR spec Defaults to `digital signature` and `key encipherment` if not specified. + description: |- + Requested key usages and extended key usages. + + + NOTE: If the CSR in the `Request` field has uses the KeyUsage or + ExtKeyUsage extension, these extensions must have the same values + as specified here without any additional values. + + + If unset, defaults to `digital signature` and `key encipherment`. type: array items: - description: "KeyUsage specifies valid usage contexts for keys. See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 \n Valid KeyUsage values are as follows: \"signing\", \"digital signature\", \"content commitment\", \"key encipherment\", \"key agreement\", \"data encipherment\", \"cert sign\", \"crl sign\", \"encipher only\", \"decipher only\", \"any\", \"server auth\", \"client auth\", \"code signing\", \"email protection\", \"s/mime\", \"ipsec end system\", \"ipsec tunnel\", \"ipsec user\", \"timestamping\", \"ocsp signing\", \"microsoft sgc\", \"netscape sgc\"" + description: |- + KeyUsage specifies valid usage contexts for keys. + See: + https://tools.ietf.org/html/rfc5280#section-4.2.1.3 + https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + + + Valid KeyUsage values are as follows: + "signing", + "digital signature", + "content commitment", + "key encipherment", + "key agreement", + "data encipherment", + "cert sign", + "crl sign", + "encipher only", + "decipher only", + "any", + "server auth", + "client auth", + "code signing", + "email protection", + "s/mime", + "ipsec end system", + "ipsec tunnel", + "ipsec user", + "timestamping", + "ocsp signing", + "microsoft sgc", + "netscape sgc" type: string enum: - signing @@ -143,22 +244,39 @@ spec: - microsoft sgc - netscape sgc username: - description: Username contains the name of the user that created the CertificateRequest. Populated by the cert-manager webhook on creation and immutable. + description: |- + Username contains the name of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. type: string status: - description: Status of the CertificateRequest. This is set and managed automatically. + description: |- + Status of the CertificateRequest. + This is set and managed automatically. + Read-only. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status type: object properties: ca: - description: The PEM encoded x509 certificate of the signer, also known as the CA (Certificate Authority). This is set on a best-effort basis by different issuers. If not set, the CA is assumed to be unknown/not available. + description: |- + The PEM encoded X.509 certificate of the signer, also known as the CA + (Certificate Authority). + This is set on a best-effort basis by different issuers. + If not set, the CA is assumed to be unknown/not available. type: string format: byte certificate: - description: The PEM encoded x509 certificate resulting from the certificate signing request. If not set, the CertificateRequest has either not been completed or has failed. More information on failure can be found by checking the `conditions` field. + description: |- + The PEM encoded X.509 certificate resulting from the certificate + signing request. + If not set, the CertificateRequest has either not been completed or has + failed. More information on failure can be found by checking the + `conditions` field. type: string format: byte conditions: - description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready` and `InvalidRequest`. + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`, `InvalidRequest`, `Approved` and `Denied`. type: array items: description: CertificateRequestCondition contains condition information for a CertificateRequest. @@ -168,14 +286,20 @@ spec: - type properties: lastTransitionTime: - description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. type: string format: date-time message: - description: Message is a human readable description of the details of the last transition, complementing reason. + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. type: string reason: - description: Reason is a brief machine readable explanation for the condition's last transition. + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. type: string status: description: Status of the condition, one of (`True`, `False`, `Unknown`). @@ -185,22 +309,34 @@ spec: - "False" - Unknown type: - description: Type of the condition, known values are (`Ready`, `InvalidRequest`, `Approved`, `Denied`). + description: |- + Type of the condition, known values are (`Ready`, `InvalidRequest`, + `Approved`, `Denied`). type: string x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map failureTime: - description: FailureTime stores the time that this CertificateRequest failed. This is used to influence garbage collection and back-off. + description: |- + FailureTime stores the time that this CertificateRequest failed. This is + used to influence garbage collection and back-off. type: string format: date-time served: true storage: true + +# END crd {{- end }} + --- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: certificates.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} labels: app: '{{ template "cert-manager.name" . }}' app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' @@ -244,70 +380,132 @@ spec: type: date schema: openAPIV3Schema: - description: "A Certificate resource should be created to ensure an up to date and signed x509 certificate is stored in the Kubernetes Secret resource named in `spec.secretName`. \n The stored certificate will be renewed before it expires (as configured by `spec.renewBefore`)." + description: |- + A Certificate resource should be created to ensure an up to date and signed + X.509 certificate is stored in the Kubernetes Secret resource named in `spec.secretName`. + + + The stored certificate will be renewed before it expires (as configured by `spec.renewBefore`). type: object - required: - - spec properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: Desired state of the Certificate resource. + description: |- + Specification of the desired state of the Certificate resource. + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status type: object required: - issuerRef - secretName properties: additionalOutputFormats: - description: AdditionalOutputFormats defines extra output formats of the private key and signed certificate chain to be written to this Certificate's target Secret. This is an Alpha Feature and is only enabled with the `--feature-gates=AdditionalCertificateOutputFormats=true` option on both the controller and webhook components. + description: |- + Defines extra output formats of the private key and signed certificate chain + to be written to this Certificate's target Secret. + + + This is a Beta Feature enabled by default. It can be disabled with the + `--feature-gates=AdditionalCertificateOutputFormats=false` option set on both + the controller and webhook components. type: array items: - description: CertificateAdditionalOutputFormat defines an additional output format of a Certificate resource. These contain supplementary data formats of the signed certificate chain and paired private key. + description: |- + CertificateAdditionalOutputFormat defines an additional output format of a + Certificate resource. These contain supplementary data formats of the signed + certificate chain and paired private key. type: object required: - type properties: type: - description: Type is the name of the format type that should be written to the Certificate's target Secret. + description: |- + Type is the name of the format type that should be written to the + Certificate's target Secret. type: string enum: - DER - CombinedPEM commonName: - description: 'CommonName is a common name to be used on the Certificate. The CommonName should have a length of 64 characters or fewer to avoid generating invalid CSRs. This value is ignored by TLS clients when any subject alt name is set. This is x509 behaviour: https://tools.ietf.org/html/rfc6125#section-6.4.4' + description: |- + Requested common name X509 certificate subject attribute. + More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 + NOTE: TLS clients will ignore this value when any subject alternative name is + set (see https://tools.ietf.org/html/rfc6125#section-6.4.4). + + + Should have a length of 64 characters or fewer to avoid generating invalid CSRs. + Cannot be set if the `literalSubject` field is set. type: string dnsNames: - description: DNSNames is a list of DNS subjectAltNames to be set on the Certificate. + description: Requested DNS subject alternative names. type: array items: type: string duration: - description: The requested 'duration' (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types. If unset this defaults to 90 days. Certificate will be renewed either 2/3 through its duration or `renewBefore` period before its expiry, whichever is later. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration + description: |- + Requested 'duration' (i.e. lifetime) of the Certificate. Note that the + issuer may choose to ignore the requested duration, just like any other + requested attribute. + + + If unset, this defaults to 90 days. + Minimum accepted duration is 1 hour. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. type: string emailAddresses: - description: EmailAddresses is a list of email subjectAltNames to be set on the Certificate. + description: Requested email subject alternative names. type: array items: type: string encodeUsagesInRequest: - description: EncodeUsagesInRequest controls whether key usages should be present in the CertificateRequest + description: |- + Whether the KeyUsage and ExtKeyUsage extensions should be set in the encoded CSR. + + + This option defaults to true, and should only be disabled if the target + issuer does not support CSRs with these X509 KeyUsage/ ExtKeyUsage extensions. type: boolean ipAddresses: - description: IPAddresses is a list of IP address subjectAltNames to be set on the Certificate. + description: Requested IP address subject alternative names. type: array items: type: string isCA: - description: IsCA will mark this Certificate as valid for certificate signing. This will automatically add the `cert sign` usage to the list of `usages`. + description: |- + Requested basic constraints isCA value. + The isCA value is used to set the `isCA` field on the created CertificateRequest + resources. Note that the issuer may choose to ignore the requested isCA value, just + like any other requested attribute. + + + If true, this will automatically add the `cert sign` usage to the list + of requested `usages`. type: boolean issuerRef: - description: IssuerRef is a reference to the issuer for this certificate. If the `kind` field is not set, or set to `Issuer`, an Issuer resource with the given name in the same namespace as the Certificate will be used. If the `kind` field is set to `ClusterIssuer`, a ClusterIssuer with the provided name will be used. The `name` field in this stanza is required at all times. + description: |- + Reference to the issuer responsible for issuing the certificate. + If the issuer is namespace-scoped, it must be in the same namespace + as the Certificate. If the issuer is cluster-scoped, it can be used + from any namespace. + + + The `name` field of the reference must always be specified. type: object required: - name @@ -322,94 +520,325 @@ spec: description: Name of the resource being referred to. type: string keystores: - description: Keystores configures additional keystore output formats stored in the `secretName` Secret resource. + description: Additional keystore output formats to be stored in the Certificate's Secret. type: object properties: jks: - description: JKS configures options for storing a JKS keystore in the `spec.secretName` Secret resource. + description: |- + JKS configures options for storing a JKS keystore in the + `spec.secretName` Secret resource. type: object required: - create - passwordSecretRef properties: + alias: + description: |- + Alias specifies the alias of the key in the keystore, required by the JKS format. + If not provided, the default alias `certificate` will be used. + type: string create: - description: Create enables JKS keystore creation for the Certificate. If true, a file named `keystore.jks` will be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef`. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named `truststore.jks` will also be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef` containing the issuing Certificate Authority + description: |- + Create enables JKS keystore creation for the Certificate. + If true, a file named `keystore.jks` will be created in the target + Secret resource, encrypted using the password stored in + `passwordSecretRef`. + The keystore file will be updated immediately. + If the issuer provided a CA certificate, a file named `truststore.jks` + will also be created in the target Secret resource, encrypted using the + password stored in `passwordSecretRef` + containing the issuing Certificate Authority type: boolean passwordSecretRef: - description: PasswordSecretRef is a reference to a key in a Secret resource containing the password used to encrypt the JKS keystore. + description: |- + PasswordSecretRef is a reference to a key in a Secret resource + containing the password used to encrypt the JKS keystore. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string pkcs12: - description: PKCS12 configures options for storing a PKCS12 keystore in the `spec.secretName` Secret resource. + description: |- + PKCS12 configures options for storing a PKCS12 keystore in the + `spec.secretName` Secret resource. type: object required: - create - passwordSecretRef properties: create: - description: Create enables PKCS12 keystore creation for the Certificate. If true, a file named `keystore.p12` will be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef`. The keystore file will be updated immediately. If the issuer provided a CA certificate, a file named `truststore.p12` will also be created in the target Secret resource, encrypted using the password stored in `passwordSecretRef` containing the issuing Certificate Authority + description: |- + Create enables PKCS12 keystore creation for the Certificate. + If true, a file named `keystore.p12` will be created in the target + Secret resource, encrypted using the password stored in + `passwordSecretRef`. + The keystore file will be updated immediately. + If the issuer provided a CA certificate, a file named `truststore.p12` will + also be created in the target Secret resource, encrypted using the + password stored in `passwordSecretRef` containing the issuing Certificate + Authority type: boolean passwordSecretRef: - description: PasswordSecretRef is a reference to a key in a Secret resource containing the password used to encrypt the PKCS12 keystore. + description: |- + PasswordSecretRef is a reference to a key in a Secret resource + containing the password used to encrypt the PKCS12 keystore. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string + profile: + description: |- + Profile specifies the key and certificate encryption algorithms and the HMAC algorithm + used to create the PKCS12 keystore. Default value is `LegacyRC2` for backward compatibility. + + + If provided, allowed values are: + `LegacyRC2`: Deprecated. Not supported by default in OpenSSL 3 or Java 20. + `LegacyDES`: Less secure algorithm. Use this option for maximal compatibility. + `Modern2023`: Secure algorithm. Use this option in case you have to always use secure algorithms + (eg. because of company policy). Please note that the security of the algorithm is not that important + in reality, because the unencrypted certificate and private key are also stored in the Secret. + type: string + enum: + - LegacyRC2 + - LegacyDES + - Modern2023 literalSubject: - description: LiteralSubject is an LDAP formatted string that represents the [X.509 Subject field](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6). Use this *instead* of the Subject field if you need to ensure the correct ordering of the RDN sequence, such as when issuing certs for LDAP authentication. See https://github.com/cert-manager/cert-manager/issues/3203, https://github.com/cert-manager/cert-manager/issues/4424. This field is alpha level and is only supported by cert-manager installations where LiteralCertificateSubject feature gate is enabled on both cert-manager controller and webhook. + description: |- + Requested X.509 certificate subject, represented using the LDAP "String + Representation of a Distinguished Name" [1]. + Important: the LDAP string format also specifies the order of the attributes + in the subject, this is important when issuing certs for LDAP authentication. + Example: `CN=foo,DC=corp,DC=example,DC=com` + More info [1]: https://datatracker.ietf.org/doc/html/rfc4514 + More info: https://github.com/cert-manager/cert-manager/issues/3203 + More info: https://github.com/cert-manager/cert-manager/issues/4424 + + + Cannot be set if the `subject` or `commonName` field is set. type: string + nameConstraints: + description: |- + x.509 certificate NameConstraint extension which MUST NOT be used in a non-CA certificate. + More Info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10 + + + This is an Alpha Feature and is only enabled with the + `--feature-gates=NameConstraints=true` option set on both + the controller and webhook components. + type: object + properties: + critical: + description: if true then the name constraints are marked critical. + type: boolean + excluded: + description: |- + Excluded contains the constraints which must be disallowed. Any name matching a + restriction in the excluded field is invalid regardless + of information appearing in the permitted + type: object + properties: + dnsDomains: + description: DNSDomains is a list of DNS domains that are permitted or excluded. + type: array + items: + type: string + emailAddresses: + description: EmailAddresses is a list of Email Addresses that are permitted or excluded. + type: array + items: + type: string + ipRanges: + description: |- + IPRanges is a list of IP Ranges that are permitted or excluded. + This should be a valid CIDR notation. + type: array + items: + type: string + uriDomains: + description: URIDomains is a list of URI domains that are permitted or excluded. + type: array + items: + type: string + permitted: + description: Permitted contains the constraints in which the names must be located. + type: object + properties: + dnsDomains: + description: DNSDomains is a list of DNS domains that are permitted or excluded. + type: array + items: + type: string + emailAddresses: + description: EmailAddresses is a list of Email Addresses that are permitted or excluded. + type: array + items: + type: string + ipRanges: + description: |- + IPRanges is a list of IP Ranges that are permitted or excluded. + This should be a valid CIDR notation. + type: array + items: + type: string + uriDomains: + description: URIDomains is a list of URI domains that are permitted or excluded. + type: array + items: + type: string + otherNames: + description: |- + `otherNames` is an escape hatch for SAN that allows any type. We currently restrict the support to string like otherNames, cf RFC 5280 p 37 + Any UTF8 String valued otherName can be passed with by setting the keys oid: x.x.x.x and UTF8Value: somevalue for `otherName`. + Most commonly this would be UPN set with oid: 1.3.6.1.4.1.311.20.2.3 + You should ensure that any OID passed is valid for the UTF8String type as we do not explicitly validate this. + type: array + items: + type: object + properties: + oid: + description: |- + OID is the object identifier for the otherName SAN. + The object identifier must be expressed as a dotted string, for + example, "1.2.840.113556.1.4.221". + type: string + utf8Value: + description: |- + utf8Value is the string value of the otherName SAN. + The utf8Value accepts any valid UTF8 string to set as value for the otherName SAN. + type: string privateKey: - description: Options to control private keys used for the Certificate. + description: |- + Private key options. These include the key algorithm and size, the used + encoding and the rotation policy. type: object properties: algorithm: - description: Algorithm is the private key algorithm of the corresponding private key for this certificate. If provided, allowed values are either `RSA`,`Ed25519` or `ECDSA` If `algorithm` is specified and `size` is not provided, key size of 256 will be used for `ECDSA` key algorithm and key size of 2048 will be used for `RSA` key algorithm. key size is ignored when using the `Ed25519` key algorithm. + description: |- + Algorithm is the private key algorithm of the corresponding private key + for this certificate. + + + If provided, allowed values are either `RSA`, `ECDSA` or `Ed25519`. + If `algorithm` is specified and `size` is not provided, + key size of 2048 will be used for `RSA` key algorithm and + key size of 256 will be used for `ECDSA` key algorithm. + key size is ignored when using the `Ed25519` key algorithm. type: string enum: - RSA - ECDSA - Ed25519 encoding: - description: The private key cryptography standards (PKCS) encoding for this certificate's private key to be encoded in. If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 and PKCS#8, respectively. Defaults to `PKCS1` if not specified. + description: |- + The private key cryptography standards (PKCS) encoding for this + certificate's private key to be encoded in. + + + If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 + and PKCS#8, respectively. + Defaults to `PKCS1` if not specified. type: string enum: - PKCS1 - PKCS8 rotationPolicy: - description: RotationPolicy controls how private keys should be regenerated when a re-issuance is being processed. If set to Never, a private key will only be generated if one does not already exist in the target `spec.secretName`. If one does exists but it does not have the correct algorithm or size, a warning will be raised to await user intervention. If set to Always, a private key matching the specified requirements will be generated whenever a re-issuance occurs. Default is 'Never' for backward compatibility. + description: |- + RotationPolicy controls how private keys should be regenerated when a + re-issuance is being processed. + + + If set to `Never`, a private key will only be generated if one does not + already exist in the target `spec.secretName`. If one does exists but it + does not have the correct algorithm or size, a warning will be raised + to await user intervention. + If set to `Always`, a private key matching the specified requirements + will be generated whenever a re-issuance occurs. + Default is `Never` for backward compatibility. type: string enum: - Never - Always size: - description: Size is the key bit size of the corresponding private key for this certificate. If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, and will default to `2048` if not specified. If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, and will default to `256` if not specified. If `algorithm` is set to `Ed25519`, Size is ignored. No other values are allowed. + description: |- + Size is the key bit size of the corresponding private key for this certificate. + + + If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, + and will default to `2048` if not specified. + If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, + and will default to `256` if not specified. + If `algorithm` is set to `Ed25519`, Size is ignored. + No other values are allowed. type: integer renewBefore: - description: How long before the currently issued certificate's expiry cert-manager should renew the certificate. The default is 2/3 of the issued certificate's duration. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration + description: |- + How long before the currently issued certificate's expiry cert-manager should + renew the certificate. For example, if a certificate is valid for 60 minutes, + and `renewBefore=10m`, cert-manager will begin to attempt to renew the certificate + 50 minutes after it was issued (i.e. when there are 10 minutes remaining until + the certificate is no longer valid). + + + NOTE: The actual lifetime of the issued certificate is used to determine the + renewal time. If an issuer returns a certificate with a different lifetime than + the one requested, cert-manager will use the lifetime of the issued certificate. + + + If unset, this defaults to 1/3 of the issued certificate's lifetime. + Minimum accepted value is 5 minutes. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. type: string revisionHistoryLimit: - description: revisionHistoryLimit is the maximum number of CertificateRequest revisions that are maintained in the Certificate's history. Each revision represents a single `CertificateRequest` created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number. If set, revisionHistoryLimit must be a value of `1` or greater. If unset (`nil`), revisions will not be garbage collected. Default value is `nil`. + description: |- + The maximum number of CertificateRequest revisions that are maintained in + the Certificate's history. Each revision represents a single `CertificateRequest` + created by this Certificate, either when it was created, renewed, or Spec + was changed. Revisions will be removed by oldest first if the number of + revisions exceeds this number. + + + If set, revisionHistoryLimit must be a value of `1` or greater. + If unset (`nil`), revisions will not be garbage collected. + Default value is `nil`. type: integer format: int32 secretName: - description: SecretName is the name of the secret resource that will be automatically created and managed by this Certificate resource. It will be populated with a private key and certificate, signed by the denoted issuer. + description: |- + Name of the Secret resource that will be automatically created and + managed by this Certificate resource. It will be populated with a + private key and certificate, signed by the denoted issuer. The Secret + resource lives in the same namespace as the Certificate resource. type: string secretTemplate: - description: SecretTemplate defines annotations and labels to be copied to the Certificate's Secret. Labels and annotations on the Secret will be changed as they appear on the SecretTemplate when added or removed. SecretTemplate annotations are added in conjunction with, and cannot overwrite, the base set of annotations cert-manager sets on the Certificate's Secret. + description: |- + Defines annotations and labels to be copied to the Certificate's Secret. + Labels and annotations on the Secret will be changed as they appear on the + SecretTemplate when added or removed. SecretTemplate annotations are added + in conjunction with, and cannot overwrite, the base set of annotations + cert-manager sets on the Certificate's Secret. type: object properties: annotations: @@ -423,7 +852,13 @@ spec: additionalProperties: type: string subject: - description: Full X509 name specification (https://golang.org/pkg/crypto/x509/pkix/#Name). + description: |- + Requested set of X509 certificate subject attributes. + More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 + + + The common name attribute is specified separately in the `commonName` field. + Cannot be set if the `literalSubject` field is set. type: object properties: countries: @@ -465,15 +900,52 @@ spec: items: type: string uris: - description: URIs is a list of URI subjectAltNames to be set on the Certificate. + description: Requested URI subject alternative names. type: array items: type: string usages: - description: Usages is the set of x509 usages that are requested for the certificate. Defaults to `digital signature` and `key encipherment` if not specified. + description: |- + Requested key usages and extended key usages. + These usages are used to set the `usages` field on the created CertificateRequest + resources. If `encodeUsagesInRequest` is unset or set to `true`, the usages + will additionally be encoded in the `request` field which contains the CSR blob. + + + If unset, defaults to `digital signature` and `key encipherment`. type: array items: - description: "KeyUsage specifies valid usage contexts for keys. See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 \n Valid KeyUsage values are as follows: \"signing\", \"digital signature\", \"content commitment\", \"key encipherment\", \"key agreement\", \"data encipherment\", \"cert sign\", \"crl sign\", \"encipher only\", \"decipher only\", \"any\", \"server auth\", \"client auth\", \"code signing\", \"email protection\", \"s/mime\", \"ipsec end system\", \"ipsec tunnel\", \"ipsec user\", \"timestamping\", \"ocsp signing\", \"microsoft sgc\", \"netscape sgc\"" + description: |- + KeyUsage specifies valid usage contexts for keys. + See: + https://tools.ietf.org/html/rfc5280#section-4.2.1.3 + https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + + + Valid KeyUsage values are as follows: + "signing", + "digital signature", + "content commitment", + "key encipherment", + "key agreement", + "data encipherment", + "cert sign", + "crl sign", + "encipher only", + "decipher only", + "any", + "server auth", + "client auth", + "code signing", + "email protection", + "s/mime", + "ipsec end system", + "ipsec tunnel", + "ipsec user", + "timestamping", + "ocsp signing", + "microsoft sgc", + "netscape sgc" type: string enum: - signing @@ -500,11 +972,17 @@ spec: - microsoft sgc - netscape sgc status: - description: Status of the Certificate. This is set and managed automatically. + description: |- + Status of the Certificate. + This is set and managed automatically. + Read-only. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status type: object properties: conditions: - description: List of status conditions to indicate the status of certificates. Known condition types are `Ready` and `Issuing`. + description: |- + List of status conditions to indicate the status of certificates. + Known condition types are `Ready` and `Issuing`. type: array items: description: CertificateCondition contains condition information for an Certificate. @@ -514,18 +992,29 @@ spec: - type properties: lastTransitionTime: - description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. type: string format: date-time message: - description: Message is a human readable description of the details of the last transition, complementing reason. + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. type: string observedGeneration: - description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Certificate. + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Certificate. type: integer format: int64 reason: - description: Reason is a brief machine readable explanation for the condition's last transition. + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. type: string status: description: Status of the condition, one of (`True`, `False`, `Unknown`). @@ -541,37 +1030,85 @@ spec: - type x-kubernetes-list-type: map failedIssuanceAttempts: - description: The number of continuous failed issuance attempts up till now. This field gets removed (if set) on a successful issuance and gets set to 1 if unset and an issuance has failed. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1). + description: |- + The number of continuous failed issuance attempts up till now. This + field gets removed (if set) on a successful issuance and gets set to + 1 if unset and an issuance has failed. If an issuance has failed, the + delay till the next issuance will be calculated using formula + time.Hour * 2 ^ (failedIssuanceAttempts - 1). type: integer lastFailureTime: - description: LastFailureTime is set only if the lastest issuance for this Certificate failed and contains the time of the failure. If an issuance has failed, the delay till the next issuance will be calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - 1). If the latest issuance has succeeded this field will be unset. + description: |- + LastFailureTime is set only if the lastest issuance for this + Certificate failed and contains the time of the failure. If an + issuance has failed, the delay till the next issuance will be + calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - + 1). If the latest issuance has succeeded this field will be unset. type: string format: date-time nextPrivateKeySecretName: - description: The name of the Secret resource containing the private key to be used for the next certificate iteration. The keymanager controller will automatically set this field if the `Issuing` condition is set to `True`. It will automatically unset this field when the Issuing condition is not set or False. + description: |- + The name of the Secret resource containing the private key to be used + for the next certificate iteration. + The keymanager controller will automatically set this field if the + `Issuing` condition is set to `True`. + It will automatically unset this field when the Issuing condition is + not set or False. type: string notAfter: - description: The expiration time of the certificate stored in the secret named by this resource in `spec.secretName`. + description: |- + The expiration time of the certificate stored in the secret named + by this resource in `spec.secretName`. type: string format: date-time notBefore: - description: The time after which the certificate stored in the secret named by this resource in spec.secretName is valid. + description: |- + The time after which the certificate stored in the secret named + by this resource in `spec.secretName` is valid. type: string format: date-time renewalTime: - description: RenewalTime is the time at which the certificate will be next renewed. If not set, no upcoming renewal is scheduled. + description: |- + RenewalTime is the time at which the certificate will be next + renewed. + If not set, no upcoming renewal is scheduled. type: string format: date-time revision: - description: "The current 'revision' of the certificate as issued. \n When a CertificateRequest resource is created, it will have the `cert-manager.io/certificate-revision` set to one greater than the current value of this field. \n Upon issuance, this field will be set to the value of the annotation on the CertificateRequest resource used to issue the certificate. \n Persisting the value on the CertificateRequest resource allows the certificates controller to know whether a request is part of an old issuance or if it is part of the ongoing revision's issuance by checking if the revision value in the annotation is greater than this field." + description: |- + The current 'revision' of the certificate as issued. + + + When a CertificateRequest resource is created, it will have the + `cert-manager.io/certificate-revision` set to one greater than the + current value of this field. + + + Upon issuance, this field will be set to the value of the annotation + on the CertificateRequest resource used to issue the certificate. + + + Persisting the value on the CertificateRequest resource allows the + certificates controller to know whether a request is part of an old + issuance or if it is part of the ongoing revision's issuance by + checking if the revision value in the annotation is greater than this + field. type: integer served: true storage: true + +# END crd {{- end }} + --- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: challenges.acme.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} labels: app: '{{ template "cert-manager.name" . }}' app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' @@ -614,10 +1151,19 @@ spec: - spec properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -634,13 +1180,23 @@ spec: - url properties: authorizationURL: - description: The URL to the ACME Authorization resource that this challenge is a part of. + description: |- + The URL to the ACME Authorization resource that this + challenge is a part of. type: string dnsName: - description: dnsName is the identifier that this challenge is for, e.g. example.com. If the requested DNSName is a 'wildcard', this field MUST be set to the non-wildcard domain, e.g. for `*.example.com`, it must be `example.com`. + description: |- + dnsName is the identifier that this challenge is for, e.g. example.com. + If the requested DNSName is a 'wildcard', this field MUST be set to the + non-wildcard domain, e.g. for `*.example.com`, it must be `example.com`. type: string issuerRef: - description: References a properly configured ACME-type Issuer which should be used to create this Challenge. If the Issuer does not exist, processing will be retried. If the Issuer is not an 'ACME' Issuer, an error will be returned and the Challenge will be marked as failed. + description: |- + References a properly configured ACME-type Issuer which should + be used to create this Challenge. + If the Issuer does not exist, processing will be retried. + If the Issuer is not an 'ACME' Issuer, an error will be returned and the + Challenge will be marked as failed. type: object required: - name @@ -655,34 +1211,54 @@ spec: description: Name of the resource being referred to. type: string key: - description: 'The ACME challenge key for this challenge For HTTP01 challenges, this is the value that must be responded with to complete the HTTP01 challenge in the format: `.`. For DNS01 challenges, this is the base64 encoded SHA256 sum of the `.` text that must be set as the TXT record content.' + description: |- + The ACME challenge key for this challenge + For HTTP01 challenges, this is the value that must be responded with to + complete the HTTP01 challenge in the format: + `.`. + For DNS01 challenges, this is the base64 encoded SHA256 sum of the + `.` + text that must be set as the TXT record content. type: string solver: - description: Contains the domain solving configuration that should be used to solve this challenge resource. + description: |- + Contains the domain solving configuration that should be used to + solve this challenge resource. type: object properties: dns01: - description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. type: object properties: acmeDNS: - description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. type: object required: - accountSecretRef - host properties: accountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string host: type: string @@ -696,40 +1272,61 @@ spec: - serviceConsumerDomain properties: accessTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string clientSecretSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string clientTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string serviceConsumerDomain: type: string @@ -741,19 +1338,30 @@ spec: - subscriptionID properties: clientID: - description: if both this and ClientSecret are left unset MSI will be used + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. type: string clientSecretSecretRef: - description: if both this and ClientID are left unset MSI will be used + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string environment: description: name of the Azure environment (default AzurePublicCloud) @@ -767,14 +1375,19 @@ spec: description: name of the DNS zone that should be used type: string managedIdentity: - description: managed identity configuration, can not be used at the same time as clientID, clientSecretSecretRef or tenantID + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. type: object properties: clientID: description: client ID of the managed identity, can not be used at the same time as resourceID type: string resourceID: - description: resource ID of the managed identity, can not be used at the same time as clientID + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity type: string resourceGroupName: description: resource group the DNS zone is located in @@ -783,7 +1396,10 @@ spec: description: ID of the Azure subscription type: string tenantID: - description: when specifying ClientID and ClientSecret then this field is also needed + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. type: string cloudDNS: description: Use the Google Cloud DNS API to manage DNS01 challenge records. @@ -792,37 +1408,55 @@ spec: - project properties: hostedZoneName: - description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. type: string project: type: string serviceAccountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string cloudflare: description: Use the Cloudflare API to manage DNS01 challenge records. type: object properties: apiKeySecretRef: - description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string apiTokenSecretRef: description: API token used to authenticate with Cloudflare. @@ -831,16 +1465,23 @@ spec: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string email: description: Email of the account, only required when using API key based authentication. type: string cnameStrategy: - description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. type: string enum: - None @@ -852,43 +1493,69 @@ spec: - tokenSecretRef properties: tokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string rfc2136: - description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. type: object required: - nameserver properties: nameserver: - description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. type: string tsigAlgorithm: - description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. type: string tsigKeyName: - description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. type: string tsigSecretSecretRef: - description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string route53: description: Use the AWS Route53 API to manage DNS01 challenge records. @@ -897,20 +1564,71 @@ spec: - region properties: accessKeyID: - description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: string accessKeyIDSecretRef: - description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string hostedZoneID: description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. type: string @@ -918,113 +1636,301 @@ spec: description: Always set the region when using AccessKeyID and SecretAccessKey type: string role: - description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata type: string secretAccessKeySecretRef: - description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string webhook: - description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. type: object required: - groupName - solverName properties: config: - description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. x-kubernetes-preserve-unknown-fields: true groupName: - description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. type: string solverName: - description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. type: string http01: - description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. type: object properties: gatewayHTTPRoute: - description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. type: object properties: labels: - description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. type: object additionalProperties: type: string parentRefs: - description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways type: array items: - description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). The only kind of parent resource with \"Core\" support is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + + This API may be extended in the future to support additional kinds of parent + resources. + + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. type: object required: - name properties: group: - description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + + Support: Core type: string default: gateway.networking.k8s.io maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ kind: - description: "Kind is kind of the referent. \n Support: Core (Gateway) \n Support: Implementation-specific (Other Resources)" + description: |- + Kind is kind of the referent. + + + There are two kinds of parent resources with "Core" support: + + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + + Support for other resources is Implementation-Specific. type: string default: Gateway maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ name: - description: "Name is the name of the referent. \n Support: Core" + description: |- + Name is the name of the referent. + + + Support: Core type: string maxLength: 253 minLength: 1 namespace: - description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n Support: Core" + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + + Support: Core type: string maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ port: - description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + + Support: Extended type: integer format: int32 maximum: 65535 minimum: 1 sectionName: - description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + + Support: Core type: string maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. type: string ingress: - description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. type: object properties: class: - description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. type: string ingressClassName: - description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. type: string ingressTemplate: - description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. type: object properties: metadata: - description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. type: object properties: annotations: @@ -1038,14 +1944,26 @@ spec: additionalProperties: type: string name: - description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. type: string podTemplate: - description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. type: object properties: metadata: - description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. type: object properties: annotations: @@ -1059,7 +1977,10 @@ spec: additionalProperties: type: string spec: - description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. type: object properties: affinity: @@ -1071,10 +1992,21 @@ spec: type: object properties: preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. type: array items: - description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). type: object required: - preference @@ -1088,7 +2020,9 @@ spec: description: A list of node selector requirements by node's labels. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -1098,18 +2032,29 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -1119,20 +2064,35 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic x-kubernetes-map-type: atomic weight: description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. type: integer format: int32 + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. type: object required: - nodeSelectorTerms @@ -1141,14 +2101,19 @@ spec: description: Required. A list of node selector terms. The terms are ORed. type: array items: - description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. type: object properties: matchExpressions: description: A list of node selector requirements by node's labels. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -1158,18 +2123,29 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -1179,21 +2155,40 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic x-kubernetes-map-type: atomic podAffinity: description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). type: object properties: preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. type: array items: description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) @@ -1209,14 +2204,18 @@ spec: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -1226,28 +2225,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -1257,49 +2304,90 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. type: integer format: int32 + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. type: array items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running type: object required: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -1309,28 +2397,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -1340,33 +2476,64 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string + x-kubernetes-list-type: atomic podAntiAffinity: description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). type: object properties: preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. type: array items: description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) @@ -1382,14 +2549,18 @@ spec: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -1399,28 +2570,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -1430,49 +2649,90 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. type: integer format: int32 + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. type: array items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running type: object required: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -1482,28 +2742,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -1513,40 +2821,75 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string + x-kubernetes-list-type: atomic imagePullSecrets: description: If specified, the pod's imagePullSecrets type: array items: - description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. type: object properties: name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string + default: "" x-kubernetes-map-type: atomic nodeSelector: - description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ type: object additionalProperties: type: string @@ -1560,76 +2903,141 @@ spec: description: If specified, the pod's tolerations. type: array items: - description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . type: object properties: effect: - description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. type: string tolerationSeconds: - description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. type: integer format: int64 value: - description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. type: string serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. type: string selector: - description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. type: object properties: dnsNames: - description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. type: array items: type: string dnsZones: - description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. type: array items: type: string matchLabels: - description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. type: object additionalProperties: type: string token: - description: The ACME challenge token for this challenge. This is the raw value returned from the ACME server. + description: |- + The ACME challenge token for this challenge. + This is the raw value returned from the ACME server. type: string type: - description: The type of ACME challenge this resource represents. One of "HTTP-01" or "DNS-01". + description: |- + The type of ACME challenge this resource represents. + One of "HTTP-01" or "DNS-01". type: string enum: - HTTP-01 - DNS-01 url: - description: The URL of the ACME Challenge resource for this challenge. This can be used to lookup details about the status of this challenge. + description: |- + The URL of the ACME Challenge resource for this challenge. + This can be used to lookup details about the status of this challenge. type: string wildcard: - description: wildcard will be true if this challenge is for a wildcard identifier, for example '*.example.com'. + description: |- + wildcard will be true if this challenge is for a wildcard identifier, + for example '*.example.com'. type: boolean status: type: object properties: presented: - description: presented will be set to true if the challenge values for this challenge are currently 'presented'. This *does not* imply the self check is passing. Only that the values have been 'submitted' for the appropriate challenge mechanism (i.e. the DNS01 TXT record has been presented, or the HTTP01 configuration has been configured). + description: |- + presented will be set to true if the challenge values for this challenge + are currently 'presented'. + This *does not* imply the self check is passing. Only that the values + have been 'submitted' for the appropriate challenge mechanism (i.e. the + DNS01 TXT record has been presented, or the HTTP01 configuration has been + configured). type: boolean processing: - description: Used to denote whether this challenge should be processed or not. This field will only be set to true by the 'scheduling' component. It will only be set to false by the 'challenges' controller, after the challenge has reached a final state or timed out. If this field is set to false, the challenge controller will not take any more action. + description: |- + Used to denote whether this challenge should be processed or not. + This field will only be set to true by the 'scheduling' component. + It will only be set to false by the 'challenges' controller, after the + challenge has reached a final state or timed out. + If this field is set to false, the challenge controller will not take + any more action. type: boolean reason: - description: Contains human readable information on why the Challenge is in the current state. + description: |- + Contains human readable information on why the Challenge is in the + current state. type: string state: - description: Contains the current 'state' of the challenge. If not set, the state of the challenge is unknown. + description: |- + Contains the current 'state' of the challenge. + If not set, the state of the challenge is unknown. type: string enum: - valid @@ -1643,15 +3051,23 @@ spec: storage: true subresources: status: {} + +# END crd {{- end }} + --- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: clusterissuers.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} labels: app: '{{ template "cert-manager.name" . }}' app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' - app.kubernetes.io/instance: "{{ .Release.Name }}" + app.kubernetes.io/instance: '{{ .Release.Name }}' # Generated labels {{- include "labels" . | nindent 4 }} spec: group: cert-manager.io @@ -1681,16 +3097,30 @@ spec: type: date schema: openAPIV3Schema: - description: A ClusterIssuer represents a certificate issuing authority which can be referenced as part of `issuerRef` fields. It is similar to an Issuer, however it is cluster-scoped and therefore can be referenced by resources that exist in *any* namespace, not just the same namespace as the referent. + description: |- + A ClusterIssuer represents a certificate issuing authority which can be + referenced as part of `issuerRef` fields. + It is similar to an Issuer, however it is cluster-scoped and therefore can + be referenced by resources that exist in *any* namespace, not just the same + namespace as the referent. type: object required: - spec properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -1699,34 +3129,65 @@ spec: type: object properties: acme: - description: ACME configures this issuer to communicate with a RFC8555 (ACME) server to obtain signed x509 certificates. + description: |- + ACME configures this issuer to communicate with a RFC8555 (ACME) server + to obtain signed x509 certificates. type: object required: - privateKeySecretRef - server properties: caBundle: - description: Base64-encoded bundle of PEM CAs which can be used to validate the certificate chain presented by the ACME server. Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various kinds of security vulnerabilities. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. + description: |- + Base64-encoded bundle of PEM CAs which can be used to validate the certificate + chain presented by the ACME server. + Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various + kinds of security vulnerabilities. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. type: string format: byte disableAccountKeyGeneration: - description: Enables or disables generating a new ACME account key. If true, the Issuer resource will *not* request a new account but will expect the account key to be supplied via an existing secret. If false, the cert-manager system will generate a new ACME account key for the Issuer. Defaults to false. + description: |- + Enables or disables generating a new ACME account key. + If true, the Issuer resource will *not* request a new account but will expect + the account key to be supplied via an existing secret. + If false, the cert-manager system will generate a new ACME account key + for the Issuer. + Defaults to false. type: boolean email: - description: Email is the email address to be associated with the ACME account. This field is optional, but it is strongly recommended to be set. It will be used to contact you in case of issues with your account or certificates, including expiry notification emails. This field may be updated after the account is initially registered. + description: |- + Email is the email address to be associated with the ACME account. + This field is optional, but it is strongly recommended to be set. + It will be used to contact you in case of issues with your account or + certificates, including expiry notification emails. + This field may be updated after the account is initially registered. type: string enableDurationFeature: - description: Enables requesting a Not After date on certificates that matches the duration of the certificate. This is not supported by all ACME servers like Let's Encrypt. If set to true when the ACME server does not support it it will create an error on the Order. Defaults to false. + description: |- + Enables requesting a Not After date on certificates that matches the + duration of the certificate. This is not supported by all ACME servers + like Let's Encrypt. If set to true when the ACME server does not support + it, it will create an error on the Order. + Defaults to false. type: boolean externalAccountBinding: - description: ExternalAccountBinding is a reference to a CA external account of the ACME server. If set, upon registration cert-manager will attempt to associate the given external account credentials with the registered ACME account. + description: |- + ExternalAccountBinding is a reference to a CA external account of the ACME + server. + If set, upon registration cert-manager will attempt to associate the given + external account credentials with the registered ACME account. type: object required: - keyID - keySecretRef properties: keyAlgorithm: - description: 'Deprecated: keyAlgorithm field exists for historical compatibility reasons and should not be used. The algorithm is now hardcoded to HS256 in golang/x/crypto/acme.' + description: |- + Deprecated: keyAlgorithm field exists for historical compatibility + reasons and should not be used. The algorithm is now hardcoded to HS256 + in golang/x/crypto/acme. type: string enum: - HS256 @@ -1736,68 +3197,130 @@ spec: description: keyID is the ID of the CA key that the External Account is bound to. type: string keySecretRef: - description: keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes Secret which holds the symmetric MAC key of the External Account Binding. The `key` is the index string that is paired with the key data in the Secret and should not be confused with the key data itself, or indeed with the External Account Binding keyID above. The secret key stored in the Secret **must** be un-padded, base64 URL encoded data. + description: |- + keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes + Secret which holds the symmetric MAC key of the External Account Binding. + The `key` is the index string that is paired with the key data in the + Secret and should not be confused with the key data itself, or indeed with + the External Account Binding keyID above. + The secret key stored in the Secret **must** be un-padded, base64 URL + encoded data. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string preferredChain: - description: 'PreferredChain is the chain to use if the ACME server outputs multiple. PreferredChain is no guarantee that this one gets delivered by the ACME endpoint. For example, for Let''s Encrypt''s DST crosssign you would use: "DST Root CA X3" or "ISRG Root X1" for the newer Let''s Encrypt root CA. This value picks the first certificate bundle in the ACME alternative chains that has a certificate with this value as its issuer''s CN' + description: |- + PreferredChain is the chain to use if the ACME server outputs multiple. + PreferredChain is no guarantee that this one gets delivered by the ACME + endpoint. + For example, for Let's Encrypt's DST crosssign you would use: + "DST Root CA X3" or "ISRG Root X1" for the newer Let's Encrypt root CA. + This value picks the first certificate bundle in the combined set of + ACME default and alternative chains that has a root-most certificate with + this value as its issuer's commonname. type: string maxLength: 64 privateKeySecretRef: - description: PrivateKey is the name of a Kubernetes Secret resource that will be used to store the automatically generated ACME account private key. Optionally, a `key` may be specified to select a specific entry within the named Secret resource. If `key` is not specified, a default of `tls.key` will be used. + description: |- + PrivateKey is the name of a Kubernetes Secret resource that will be used to + store the automatically generated ACME account private key. + Optionally, a `key` may be specified to select a specific entry within + the named Secret resource. + If `key` is not specified, a default of `tls.key` will be used. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string server: - description: 'Server is the URL used to access the ACME server''s ''directory'' endpoint. For example, for Let''s Encrypt''s staging endpoint, you would use: "https://acme-staging-v02.api.letsencrypt.org/directory". Only ACME v2 endpoints (i.e. RFC 8555) are supported.' + description: |- + Server is the URL used to access the ACME server's 'directory' endpoint. + For example, for Let's Encrypt's staging endpoint, you would use: + "https://acme-staging-v02.api.letsencrypt.org/directory". + Only ACME v2 endpoints (i.e. RFC 8555) are supported. type: string skipTLSVerify: - description: 'INSECURE: Enables or disables validation of the ACME server TLS certificate. If true, requests to the ACME server will not have the TLS certificate chain validated. Mutually exclusive with CABundle; prefer using CABundle to prevent various kinds of security vulnerabilities. Only enable this option in development environments. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. Defaults to false.' + description: |- + INSECURE: Enables or disables validation of the ACME server TLS certificate. + If true, requests to the ACME server will not have the TLS certificate chain + validated. + Mutually exclusive with CABundle; prefer using CABundle to prevent various + kinds of security vulnerabilities. + Only enable this option in development environments. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + Defaults to false. type: boolean solvers: - description: 'Solvers is a list of challenge solvers that will be used to solve ACME challenges for the matching domains. Solver configurations must be provided in order to obtain certificates from an ACME server. For more information, see: https://cert-manager.io/docs/configuration/acme/' + description: |- + Solvers is a list of challenge solvers that will be used to solve + ACME challenges for the matching domains. + Solver configurations must be provided in order to obtain certificates + from an ACME server. + For more information, see: https://cert-manager.io/docs/configuration/acme/ type: array items: - description: An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. A selector may be provided to use different solving strategies for different DNS names. Only one of HTTP01 or DNS01 must be provided. + description: |- + An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. + A selector may be provided to use different solving strategies for different DNS names. + Only one of HTTP01 or DNS01 must be provided. type: object properties: dns01: - description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. type: object properties: acmeDNS: - description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. type: object required: - accountSecretRef - host properties: accountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string host: type: string @@ -1811,40 +3334,61 @@ spec: - serviceConsumerDomain properties: accessTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string clientSecretSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string clientTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string serviceConsumerDomain: type: string @@ -1856,19 +3400,30 @@ spec: - subscriptionID properties: clientID: - description: if both this and ClientSecret are left unset MSI will be used + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. type: string clientSecretSecretRef: - description: if both this and ClientID are left unset MSI will be used + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string environment: description: name of the Azure environment (default AzurePublicCloud) @@ -1882,14 +3437,19 @@ spec: description: name of the DNS zone that should be used type: string managedIdentity: - description: managed identity configuration, can not be used at the same time as clientID, clientSecretSecretRef or tenantID + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. type: object properties: clientID: description: client ID of the managed identity, can not be used at the same time as resourceID type: string resourceID: - description: resource ID of the managed identity, can not be used at the same time as clientID + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity type: string resourceGroupName: description: resource group the DNS zone is located in @@ -1898,7 +3458,10 @@ spec: description: ID of the Azure subscription type: string tenantID: - description: when specifying ClientID and ClientSecret then this field is also needed + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. type: string cloudDNS: description: Use the Google Cloud DNS API to manage DNS01 challenge records. @@ -1907,37 +3470,55 @@ spec: - project properties: hostedZoneName: - description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. type: string project: type: string serviceAccountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string cloudflare: description: Use the Cloudflare API to manage DNS01 challenge records. type: object properties: apiKeySecretRef: - description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string apiTokenSecretRef: description: API token used to authenticate with Cloudflare. @@ -1946,16 +3527,23 @@ spec: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string email: description: Email of the account, only required when using API key based authentication. type: string cnameStrategy: - description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. type: string enum: - None @@ -1967,43 +3555,69 @@ spec: - tokenSecretRef properties: tokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string rfc2136: - description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. type: object required: - nameserver properties: nameserver: - description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. type: string tsigAlgorithm: - description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. type: string tsigKeyName: - description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. type: string tsigSecretSecretRef: - description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string route53: description: Use the AWS Route53 API to manage DNS01 challenge records. @@ -2012,20 +3626,71 @@ spec: - region properties: accessKeyID: - description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: string accessKeyIDSecretRef: - description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string hostedZoneID: description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. type: string @@ -2033,113 +3698,301 @@ spec: description: Always set the region when using AccessKeyID and SecretAccessKey type: string role: - description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata type: string secretAccessKeySecretRef: - description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string webhook: - description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. type: object required: - groupName - solverName properties: config: - description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. x-kubernetes-preserve-unknown-fields: true groupName: - description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. type: string solverName: - description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. type: string http01: - description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. type: object properties: gatewayHTTPRoute: - description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. type: object properties: labels: - description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. type: object additionalProperties: type: string parentRefs: - description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways type: array items: - description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). The only kind of parent resource with \"Core\" support is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + + This API may be extended in the future to support additional kinds of parent + resources. + + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. type: object required: - name properties: group: - description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + + Support: Core type: string default: gateway.networking.k8s.io maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ kind: - description: "Kind is kind of the referent. \n Support: Core (Gateway) \n Support: Implementation-specific (Other Resources)" + description: |- + Kind is kind of the referent. + + + There are two kinds of parent resources with "Core" support: + + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + + Support for other resources is Implementation-Specific. type: string default: Gateway maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ name: - description: "Name is the name of the referent. \n Support: Core" + description: |- + Name is the name of the referent. + + + Support: Core type: string maxLength: 253 minLength: 1 namespace: - description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n Support: Core" + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + + Support: Core type: string maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ port: - description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + + Support: Extended type: integer format: int32 maximum: 65535 minimum: 1 sectionName: - description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + + Support: Core type: string maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. type: string ingress: - description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. type: object properties: class: - description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. type: string ingressClassName: - description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. type: string ingressTemplate: - description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. type: object properties: metadata: - description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. type: object properties: annotations: @@ -2153,14 +4006,26 @@ spec: additionalProperties: type: string name: - description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. type: string podTemplate: - description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. type: object properties: metadata: - description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. type: object properties: annotations: @@ -2174,7 +4039,10 @@ spec: additionalProperties: type: string spec: - description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. type: object properties: affinity: @@ -2186,10 +4054,21 @@ spec: type: object properties: preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. type: array items: - description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). type: object required: - preference @@ -2203,7 +4082,9 @@ spec: description: A list of node selector requirements by node's labels. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -2213,18 +4094,29 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -2234,20 +4126,35 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic x-kubernetes-map-type: atomic weight: description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. type: integer format: int32 + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. type: object required: - nodeSelectorTerms @@ -2256,14 +4163,19 @@ spec: description: Required. A list of node selector terms. The terms are ORed. type: array items: - description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. type: object properties: matchExpressions: description: A list of node selector requirements by node's labels. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -2273,18 +4185,29 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -2294,21 +4217,40 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic x-kubernetes-map-type: atomic podAffinity: description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). type: object properties: preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. type: array items: description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) @@ -2324,14 +4266,18 @@ spec: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -2341,28 +4287,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -2372,49 +4366,90 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. type: integer format: int32 + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. type: array items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running type: object required: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -2424,28 +4459,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -2455,33 +4538,64 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string + x-kubernetes-list-type: atomic podAntiAffinity: description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). type: object properties: preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. type: array items: description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) @@ -2497,14 +4611,18 @@ spec: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -2514,28 +4632,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -2545,49 +4711,90 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. type: integer format: int32 + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. type: array items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running type: object required: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -2597,28 +4804,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -2628,40 +4883,75 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string + x-kubernetes-list-type: atomic imagePullSecrets: description: If specified, the pod's imagePullSecrets type: array items: - description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. type: object properties: name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string + default: "" x-kubernetes-map-type: atomic nodeSelector: - description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ type: object additionalProperties: type: string @@ -2675,77 +4965,146 @@ spec: description: If specified, the pod's tolerations. type: array items: - description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . type: object properties: effect: - description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. type: string tolerationSeconds: - description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. type: integer format: int64 value: - description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. type: string serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. type: string selector: - description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. type: object properties: dnsNames: - description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. type: array items: type: string dnsZones: - description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. type: array items: type: string matchLabels: - description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. type: object additionalProperties: type: string ca: - description: CA configures this issuer to sign certificates using a signing CA keypair stored in a Secret resource. This is used to build internal PKIs that are managed by cert-manager. + description: |- + CA configures this issuer to sign certificates using a signing CA keypair + stored in a Secret resource. + This is used to build internal PKIs that are managed by cert-manager. type: object required: - secretName properties: crlDistributionPoints: - description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set, certificates will be issued without distribution points set. + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + issuingCertificateURLs: + description: |- + IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates + it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. + As an example, such a URL might be "http://ca.domain.com/ca.crt". type: array items: type: string ocspServers: - description: The OCSP server list is an X.509 v3 extension that defines a list of URLs of OCSP responders. The OCSP responders can be queried for the revocation status of an issued certificate. If not set, the certificate will be issued with no OCSP servers set. For example, an OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + description: |- + The OCSP server list is an X.509 v3 extension that defines a list of + URLs of OCSP responders. The OCSP responders can be queried for the + revocation status of an issued certificate. If not set, the + certificate will be issued with no OCSP servers set. For example, an + OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". type: array items: type: string secretName: - description: SecretName is the name of the secret used to sign Certificates issued by this Issuer. + description: |- + SecretName is the name of the secret used to sign Certificates issued + by this Issuer. type: string selfSigned: - description: SelfSigned configures this issuer to 'self sign' certificates using the private key used to create the CertificateRequest object. + description: |- + SelfSigned configures this issuer to 'self sign' certificates using the + private key used to create the CertificateRequest object. type: object properties: crlDistributionPoints: - description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set certificate will be issued without CDP. Values are strings. + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set certificate will be issued without CDP. Values are strings. type: array items: type: string vault: - description: Vault configures this issuer to sign certificates using a HashiCorp Vault PKI backend. + description: |- + Vault configures this issuer to sign certificates using a HashiCorp Vault + PKI backend. type: object required: - auth @@ -2757,7 +5116,9 @@ spec: type: object properties: appRole: - description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. type: object required: - path @@ -2765,53 +5126,94 @@ spec: - secretRef properties: path: - description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + description: |- + Path where the App Role authentication backend is mounted in Vault, e.g: + "approle" type: string roleId: - description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. type: string secretRef: - description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string kubernetes: - description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. type: object required: - role properties: mountPath: - description: The Vault mountPath here is the mount path to use when authenticating with Vault. For example, setting a value to `/v1/auth/foo`, will use the path `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the default value "/v1/auth/kubernetes" will be used. + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/kubernetes" will be used. type: string role: - description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. type: string secretRef: - description: The required Secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. Use of 'ambient credentials' is not supported. + description: |- + The required Secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. Use of 'ambient credentials' is not + supported. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string serviceAccountRef: - description: A reference to a service account that will be used to request a bound token (also known as "projected token"). Compared to using "secretRef", using this field means that you don't rely on statically bound tokens. To use this field, you must configure an RBAC rule to let cert-manager request a token. + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). Compared to using "secretRef", + using this field means that you don't rely on statically bound tokens. To + use this field, you must configure an RBAC rule to let cert-manager + request a token. type: object required: - name properties: + audiences: + description: |- + TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token + consisting of the issuer's namespace and name is always included. + type: array + items: + type: string name: description: Name of the ServiceAccount used to request a token. type: string @@ -2822,44 +5224,112 @@ spec: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string caBundle: - description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by Vault. Only used if using HTTPS to connect to Vault and ignored for HTTP connections. Mutually exclusive with CABundleSecretRef. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by Vault. Only used if using HTTPS to connect to Vault and + ignored for HTTP connections. + Mutually exclusive with CABundleSecretRef. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. type: string format: byte caBundleSecretRef: - description: Reference to a Secret containing a bundle of PEM-encoded CAs to use when verifying the certificate chain presented by Vault when using HTTPS. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + description: |- + Reference to a Secret containing a bundle of PEM-encoded CAs to use when + verifying the certificate chain presented by Vault when using HTTPS. + Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + If no key for the Secret is specified, cert-manager will default to 'ca.crt'. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertSecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Certificate to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientKeySecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Private Key to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string namespace: - description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces type: string path: - description: 'Path is the mount path of the Vault PKI backend''s `sign` endpoint, e.g: "my_pki_mount/sign/my-role-name".' + description: |- + Path is the mount path of the Vault PKI backend's `sign` endpoint, e.g: + "my_pki_mount/sign/my-role-name". type: string server: description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' type: string venafi: - description: Venafi configures this issuer to sign certificates using a Venafi TPP or Venafi Cloud policy zone. + description: |- + Venafi configures this issuer to sign certificates using a Venafi TPP + or Venafi Cloud policy zone. type: object required: - zone properties: cloud: - description: Cloud specifies the Venafi cloud configuration settings. Only one of TPP or Cloud may be specified. + description: |- + Cloud specifies the Venafi cloud configuration settings. + Only one of TPP or Cloud may be specified. type: object required: - apiTokenSecretRef @@ -2871,59 +5341,96 @@ spec: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string url: - description: URL is the base URL for Venafi Cloud. Defaults to "https://api.venafi.cloud/v1". + description: |- + URL is the base URL for Venafi Cloud. + Defaults to "https://api.venafi.cloud/v1". type: string tpp: - description: TPP specifies Trust Protection Platform configuration settings. Only one of TPP or Cloud may be specified. + description: |- + TPP specifies Trust Protection Platform configuration settings. + Only one of TPP or Cloud may be specified. type: object required: - credentialsRef - url properties: caBundle: - description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain. + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. + If undefined, the certificate bundle in the cert-manager controller container + is used to validate the chain. type: string format: byte credentialsRef: - description: CredentialsRef is a reference to a Secret containing the username and password for the TPP server. The secret must contain two keys, 'username' and 'password'. + description: |- + CredentialsRef is a reference to a Secret containing the username and + password for the TPP server. + The secret must contain two keys, 'username' and 'password'. type: object required: - name properties: name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string url: - description: 'URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, for example: "https://tpp.example.com/vedsdk".' + description: |- + URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, + for example: "https://tpp.example.com/vedsdk". type: string zone: - description: Zone is the Venafi Policy Zone to use for this issuer. All requests made to the Venafi platform will be restricted by the named zone policy. This field is required. + description: |- + Zone is the Venafi Policy Zone to use for this issuer. + All requests made to the Venafi platform will be restricted by the named + zone policy. + This field is required. type: string status: description: Status of the ClusterIssuer. This is set and managed automatically. type: object properties: acme: - description: ACME specific status options. This field should only be set if the Issuer is configured to use an ACME server to issue certificates. + description: |- + ACME specific status options. + This field should only be set if the Issuer is configured to use an ACME + server to issue certificates. type: object properties: lastPrivateKeyHash: - description: LastPrivateKeyHash is a hash of the private key associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + description: |- + LastPrivateKeyHash is a hash of the private key associated with the latest + registered ACME account, in order to track changes made to registered account + associated with the Issuer type: string lastRegisteredEmail: - description: LastRegisteredEmail is the email associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + description: |- + LastRegisteredEmail is the email associated with the latest registered + ACME account, in order to track changes made to registered account + associated with the Issuer type: string uri: - description: URI is the unique account identifier, which can also be used to retrieve account details from the CA + description: |- + URI is the unique account identifier, which can also be used to retrieve + account details from the CA type: string conditions: - description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready`. + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`. type: array items: description: IssuerCondition contains condition information for an Issuer. @@ -2933,18 +5440,29 @@ spec: - type properties: lastTransitionTime: - description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. type: string format: date-time message: - description: Message is a human readable description of the details of the last transition, complementing reason. + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. type: string observedGeneration: - description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Issuer. + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Issuer. type: integer format: int64 reason: - description: Reason is a brief machine readable explanation for the condition's last transition. + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. type: string status: description: Status of the condition, one of (`True`, `False`, `Unknown`). @@ -2961,15 +5479,24 @@ spec: x-kubernetes-list-type: map served: true storage: true + +# END crd {{- end }} + --- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: issuers.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} labels: app: '{{ template "cert-manager.name" . }}' app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' - app.kubernetes.io/instance: "{{ .Release.Name }}" + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: "crds" # Generated labels {{- include "labels" . | nindent 4 }} spec: group: cert-manager.io @@ -2999,16 +5526,29 @@ spec: type: date schema: openAPIV3Schema: - description: An Issuer represents a certificate issuing authority which can be referenced as part of `issuerRef` fields. It is scoped to a single namespace and can therefore only be referenced by resources within the same namespace. + description: |- + An Issuer represents a certificate issuing authority which can be + referenced as part of `issuerRef` fields. + It is scoped to a single namespace and can therefore only be referenced by + resources within the same namespace. type: object required: - spec properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -3017,34 +5557,65 @@ spec: type: object properties: acme: - description: ACME configures this issuer to communicate with a RFC8555 (ACME) server to obtain signed x509 certificates. + description: |- + ACME configures this issuer to communicate with a RFC8555 (ACME) server + to obtain signed x509 certificates. type: object required: - privateKeySecretRef - server properties: caBundle: - description: Base64-encoded bundle of PEM CAs which can be used to validate the certificate chain presented by the ACME server. Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various kinds of security vulnerabilities. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. + description: |- + Base64-encoded bundle of PEM CAs which can be used to validate the certificate + chain presented by the ACME server. + Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various + kinds of security vulnerabilities. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. type: string format: byte disableAccountKeyGeneration: - description: Enables or disables generating a new ACME account key. If true, the Issuer resource will *not* request a new account but will expect the account key to be supplied via an existing secret. If false, the cert-manager system will generate a new ACME account key for the Issuer. Defaults to false. + description: |- + Enables or disables generating a new ACME account key. + If true, the Issuer resource will *not* request a new account but will expect + the account key to be supplied via an existing secret. + If false, the cert-manager system will generate a new ACME account key + for the Issuer. + Defaults to false. type: boolean email: - description: Email is the email address to be associated with the ACME account. This field is optional, but it is strongly recommended to be set. It will be used to contact you in case of issues with your account or certificates, including expiry notification emails. This field may be updated after the account is initially registered. + description: |- + Email is the email address to be associated with the ACME account. + This field is optional, but it is strongly recommended to be set. + It will be used to contact you in case of issues with your account or + certificates, including expiry notification emails. + This field may be updated after the account is initially registered. type: string enableDurationFeature: - description: Enables requesting a Not After date on certificates that matches the duration of the certificate. This is not supported by all ACME servers like Let's Encrypt. If set to true when the ACME server does not support it it will create an error on the Order. Defaults to false. + description: |- + Enables requesting a Not After date on certificates that matches the + duration of the certificate. This is not supported by all ACME servers + like Let's Encrypt. If set to true when the ACME server does not support + it, it will create an error on the Order. + Defaults to false. type: boolean externalAccountBinding: - description: ExternalAccountBinding is a reference to a CA external account of the ACME server. If set, upon registration cert-manager will attempt to associate the given external account credentials with the registered ACME account. + description: |- + ExternalAccountBinding is a reference to a CA external account of the ACME + server. + If set, upon registration cert-manager will attempt to associate the given + external account credentials with the registered ACME account. type: object required: - keyID - keySecretRef properties: keyAlgorithm: - description: 'Deprecated: keyAlgorithm field exists for historical compatibility reasons and should not be used. The algorithm is now hardcoded to HS256 in golang/x/crypto/acme.' + description: |- + Deprecated: keyAlgorithm field exists for historical compatibility + reasons and should not be used. The algorithm is now hardcoded to HS256 + in golang/x/crypto/acme. type: string enum: - HS256 @@ -3054,68 +5625,130 @@ spec: description: keyID is the ID of the CA key that the External Account is bound to. type: string keySecretRef: - description: keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes Secret which holds the symmetric MAC key of the External Account Binding. The `key` is the index string that is paired with the key data in the Secret and should not be confused with the key data itself, or indeed with the External Account Binding keyID above. The secret key stored in the Secret **must** be un-padded, base64 URL encoded data. + description: |- + keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes + Secret which holds the symmetric MAC key of the External Account Binding. + The `key` is the index string that is paired with the key data in the + Secret and should not be confused with the key data itself, or indeed with + the External Account Binding keyID above. + The secret key stored in the Secret **must** be un-padded, base64 URL + encoded data. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string preferredChain: - description: 'PreferredChain is the chain to use if the ACME server outputs multiple. PreferredChain is no guarantee that this one gets delivered by the ACME endpoint. For example, for Let''s Encrypt''s DST crosssign you would use: "DST Root CA X3" or "ISRG Root X1" for the newer Let''s Encrypt root CA. This value picks the first certificate bundle in the ACME alternative chains that has a certificate with this value as its issuer''s CN' + description: |- + PreferredChain is the chain to use if the ACME server outputs multiple. + PreferredChain is no guarantee that this one gets delivered by the ACME + endpoint. + For example, for Let's Encrypt's DST crosssign you would use: + "DST Root CA X3" or "ISRG Root X1" for the newer Let's Encrypt root CA. + This value picks the first certificate bundle in the combined set of + ACME default and alternative chains that has a root-most certificate with + this value as its issuer's commonname. type: string maxLength: 64 privateKeySecretRef: - description: PrivateKey is the name of a Kubernetes Secret resource that will be used to store the automatically generated ACME account private key. Optionally, a `key` may be specified to select a specific entry within the named Secret resource. If `key` is not specified, a default of `tls.key` will be used. + description: |- + PrivateKey is the name of a Kubernetes Secret resource that will be used to + store the automatically generated ACME account private key. + Optionally, a `key` may be specified to select a specific entry within + the named Secret resource. + If `key` is not specified, a default of `tls.key` will be used. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string server: - description: 'Server is the URL used to access the ACME server''s ''directory'' endpoint. For example, for Let''s Encrypt''s staging endpoint, you would use: "https://acme-staging-v02.api.letsencrypt.org/directory". Only ACME v2 endpoints (i.e. RFC 8555) are supported.' + description: |- + Server is the URL used to access the ACME server's 'directory' endpoint. + For example, for Let's Encrypt's staging endpoint, you would use: + "https://acme-staging-v02.api.letsencrypt.org/directory". + Only ACME v2 endpoints (i.e. RFC 8555) are supported. type: string skipTLSVerify: - description: 'INSECURE: Enables or disables validation of the ACME server TLS certificate. If true, requests to the ACME server will not have the TLS certificate chain validated. Mutually exclusive with CABundle; prefer using CABundle to prevent various kinds of security vulnerabilities. Only enable this option in development environments. If CABundle and SkipTLSVerify are unset, the system certificate bundle inside the container is used to validate the TLS connection. Defaults to false.' + description: |- + INSECURE: Enables or disables validation of the ACME server TLS certificate. + If true, requests to the ACME server will not have the TLS certificate chain + validated. + Mutually exclusive with CABundle; prefer using CABundle to prevent various + kinds of security vulnerabilities. + Only enable this option in development environments. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + Defaults to false. type: boolean solvers: - description: 'Solvers is a list of challenge solvers that will be used to solve ACME challenges for the matching domains. Solver configurations must be provided in order to obtain certificates from an ACME server. For more information, see: https://cert-manager.io/docs/configuration/acme/' + description: |- + Solvers is a list of challenge solvers that will be used to solve + ACME challenges for the matching domains. + Solver configurations must be provided in order to obtain certificates + from an ACME server. + For more information, see: https://cert-manager.io/docs/configuration/acme/ type: array items: - description: An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. A selector may be provided to use different solving strategies for different DNS names. Only one of HTTP01 or DNS01 must be provided. + description: |- + An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. + A selector may be provided to use different solving strategies for different DNS names. + Only one of HTTP01 or DNS01 must be provided. type: object properties: dns01: - description: Configures cert-manager to attempt to complete authorizations by performing the DNS01 challenge flow. + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. type: object properties: acmeDNS: - description: Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage DNS01 challenge records. + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. type: object required: - accountSecretRef - host properties: accountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string host: type: string @@ -3129,40 +5762,61 @@ spec: - serviceConsumerDomain properties: accessTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string clientSecretSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string clientTokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string serviceConsumerDomain: type: string @@ -3174,19 +5828,30 @@ spec: - subscriptionID properties: clientID: - description: if both this and ClientSecret are left unset MSI will be used + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. type: string clientSecretSecretRef: - description: if both this and ClientID are left unset MSI will be used + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string environment: description: name of the Azure environment (default AzurePublicCloud) @@ -3200,14 +5865,19 @@ spec: description: name of the DNS zone that should be used type: string managedIdentity: - description: managed identity configuration, can not be used at the same time as clientID, clientSecretSecretRef or tenantID + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. type: object properties: clientID: description: client ID of the managed identity, can not be used at the same time as resourceID type: string resourceID: - description: resource ID of the managed identity, can not be used at the same time as clientID + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity type: string resourceGroupName: description: resource group the DNS zone is located in @@ -3216,7 +5886,10 @@ spec: description: ID of the Azure subscription type: string tenantID: - description: when specifying ClientID and ClientSecret then this field is also needed + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. type: string cloudDNS: description: Use the Google Cloud DNS API to manage DNS01 challenge records. @@ -3225,37 +5898,55 @@ spec: - project properties: hostedZoneName: - description: HostedZoneName is an optional field that tells cert-manager in which Cloud DNS zone the challenge record has to be created. If left empty cert-manager will automatically choose a zone. + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. type: string project: type: string serviceAccountSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string cloudflare: description: Use the Cloudflare API to manage DNS01 challenge records. type: object properties: apiKeySecretRef: - description: 'API key to use to authenticate with Cloudflare. Note: using an API token to authenticate is now the recommended method as it allows greater control of permissions.' + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string apiTokenSecretRef: description: API token used to authenticate with Cloudflare. @@ -3264,16 +5955,23 @@ spec: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string email: description: Email of the account, only required when using API key based authentication. type: string cnameStrategy: - description: CNAMEStrategy configures how the DNS01 provider should handle CNAME records when found in DNS zones. + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. type: string enum: - None @@ -3285,43 +5983,69 @@ spec: - tokenSecretRef properties: tokenSecretRef: - description: A reference to a specific 'key' within a Secret resource. In some instances, `key` is a required field. + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string rfc2136: - description: Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) to manage DNS01 challenge records. + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. type: object required: - nameserver properties: nameserver: - description: The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. This field is required. + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. type: string tsigAlgorithm: - description: 'The TSIG Algorithm configured in the DNS supporting RFC2136. Used only when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. Supported values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``.' + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. type: string tsigKeyName: - description: The TSIG Key name configured in the DNS. If ``tsigSecretSecretRef`` is defined, this field is required. + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. type: string tsigSecretSecretRef: - description: The name of the secret containing the TSIG value. If ``tsigKeyName`` is defined, this field is required. + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string route53: description: Use the AWS Route53 API to manage DNS01 challenge records. @@ -3330,20 +6054,71 @@ spec: - region properties: accessKeyID: - description: 'The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: string accessKeyIDSecretRef: - description: 'The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string hostedZoneID: description: If set, the provider will manage only this zone in Route53 and will not do an lookup using the route53:ListHostedZonesByName api call. type: string @@ -3351,113 +6126,301 @@ spec: description: Always set the region when using AccessKeyID and SecretAccessKey type: string role: - description: Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata type: string secretAccessKeySecretRef: - description: 'The SecretAccessKey is used for authentication. If neither the Access Key nor Key ID are set, we fall-back to using env vars, shared credentials file or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string webhook: - description: Configure an external webhook based DNS01 challenge solver to manage DNS01 challenge records. + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. type: object required: - groupName - solverName properties: config: - description: Additional configuration that should be passed to the webhook apiserver when challenges are processed. This can contain arbitrary JSON data. Secret values should not be specified in this stanza. If secret values are needed (e.g. credentials for a DNS service), you should use a SecretKeySelector to reference a Secret resource. For details on the schema of this field, consult the webhook provider implementation's documentation. + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. x-kubernetes-preserve-unknown-fields: true groupName: - description: The API group name that should be used when POSTing ChallengePayload resources to the webhook apiserver. This should be the same as the GroupName specified in the webhook provider implementation. + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. type: string solverName: - description: The name of the solver to use, as defined in the webhook provider implementation. This will typically be the name of the provider, e.g. 'cloudflare'. + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. type: string http01: - description: Configures cert-manager to attempt to complete authorizations by performing the HTTP01 challenge flow. It is not possible to obtain certificates for wildcard domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. type: object properties: gatewayHTTPRoute: - description: The Gateway API is a sig-network community API that models service networking in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will create HTTPRoutes with the specified labels in the same namespace as the challenge. This solver is experimental, and fields / behaviour may change in the future. + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. type: object properties: labels: - description: Custom labels that will be applied to HTTPRoutes created by cert-manager while solving HTTP-01 challenges. + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. type: object additionalProperties: type: string parentRefs: - description: 'When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. cert-manager needs to know which parentRefs should be used when creating the HTTPRoute. Usually, the parentRef references a Gateway. See: https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways' + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways type: array items: - description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). The only kind of parent resource with \"Core\" support is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + + This API may be extended in the future to support additional kinds of parent + resources. + + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. type: object required: - name properties: group: - description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + + Support: Core type: string default: gateway.networking.k8s.io maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ kind: - description: "Kind is kind of the referent. \n Support: Core (Gateway) \n Support: Implementation-specific (Other Resources)" + description: |- + Kind is kind of the referent. + + + There are two kinds of parent resources with "Core" support: + + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + + Support for other resources is Implementation-Specific. type: string default: Gateway maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ name: - description: "Name is the name of the referent. \n Support: Core" + description: |- + Name is the name of the referent. + + + Support: Core type: string maxLength: 253 minLength: 1 namespace: - description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n Support: Core" + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + + Support: Core type: string maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ port: - description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + + Support: Extended type: integer format: int32 maximum: 65535 minimum: 1 sectionName: - description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + + Support: Core type: string maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. type: string ingress: - description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress resources in order to route requests for '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are provisioned by cert-manager for each Challenge to be completed. + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. type: object properties: class: - description: This field configures the annotation `kubernetes.io/ingress.class` when creating Ingress resources to solve ACME challenges that use this challenge solver. Only one of `class`, `name` or `ingressClassName` may be specified. + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. type: string ingressClassName: - description: This field configures the field `ingressClassName` on the created Ingress resources used to solve ACME challenges that use this challenge solver. This is the recommended way of configuring the ingress class. Only one of `class`, `name` or `ingressClassName` may be specified. + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. type: string ingressTemplate: - description: Optional ingress template used to configure the ACME challenge solver ingress used for HTTP01 challenges. + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. type: object properties: metadata: - description: ObjectMeta overrides for the ingress used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. type: object properties: annotations: @@ -3471,14 +6434,26 @@ spec: additionalProperties: type: string name: - description: The name of the ingress resource that should have ACME challenge solving routes inserted into it in order to solve HTTP01 challenges. This is typically used in conjunction with ingress controllers like ingress-gce, which maintains a 1:1 mapping between external IPs and ingress resources. Only one of `class`, `name` or `ingressClassName` may be specified. + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. type: string podTemplate: - description: Optional pod template used to configure the ACME challenge solver pods used for HTTP01 challenges. + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. type: object properties: metadata: - description: ObjectMeta overrides for the pod used to solve HTTP01 challenges. Only the 'labels' and 'annotations' fields may be set. If labels or annotations overlap with in-built values, the values here will override the in-built values. + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. type: object properties: annotations: @@ -3492,7 +6467,10 @@ spec: additionalProperties: type: string spec: - description: PodSpec defines overrides for the HTTP01 challenge solver pod. Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. All other fields will be ignored. + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. type: object properties: affinity: @@ -3504,10 +6482,21 @@ spec: type: object properties: preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. type: array items: - description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). type: object required: - preference @@ -3521,7 +6510,9 @@ spec: description: A list of node selector requirements by node's labels. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -3531,18 +6522,29 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -3552,20 +6554,35 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic x-kubernetes-map-type: atomic weight: description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. type: integer format: int32 + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. type: object required: - nodeSelectorTerms @@ -3574,14 +6591,19 @@ spec: description: Required. A list of node selector terms. The terms are ORed. type: array items: - description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. type: object properties: matchExpressions: description: A list of node selector requirements by node's labels. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -3591,18 +6613,29 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. type: array items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. type: object required: - key @@ -3612,21 +6645,40 @@ spec: description: The label key that the selector applies to. type: string operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: - description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic x-kubernetes-map-type: atomic podAffinity: description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). type: object properties: preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. type: array items: description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) @@ -3642,14 +6694,18 @@ spec: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -3659,28 +6715,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -3690,49 +6794,90 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. type: integer format: int32 + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. type: array items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running type: object required: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -3742,28 +6887,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -3773,33 +6966,64 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string + x-kubernetes-list-type: atomic podAntiAffinity: description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). type: object properties: preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. type: array items: description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) @@ -3815,14 +7039,18 @@ spec: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -3832,28 +7060,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -3863,49 +7139,90 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. type: integer format: int32 + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. type: array items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running type: object required: - topologyKey properties: labelSelector: - description: A label query over a set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -3915,28 +7232,76 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + type: array + items: + type: string + x-kubernetes-list-type: atomic namespaceSelector: - description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. type: object properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. type: array items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. type: object required: - key @@ -3946,40 +7311,75 @@ spec: description: key is the label key that the selector applies to. type: string operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: - description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. type: array items: type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic matchLabels: - description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object additionalProperties: type: string x-kubernetes-map-type: atomic namespaces: - description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". type: array items: type: string + x-kubernetes-list-type: atomic topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. type: string + x-kubernetes-list-type: atomic imagePullSecrets: description: If specified, the pod's imagePullSecrets type: array items: - description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. type: object properties: name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string + default: "" x-kubernetes-map-type: atomic nodeSelector: - description: 'NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node''s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ type: object additionalProperties: type: string @@ -3993,77 +7393,146 @@ spec: description: If specified, the pod's tolerations. type: array items: - description: The pod this Toleration is attached to tolerates any taint that matches the triple using the matching operator . + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . type: object properties: effect: - description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string key: - description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string operator: - description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. type: string tolerationSeconds: - description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. type: integer format: int64 value: - description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. type: string serviceType: - description: Optional service type for Kubernetes solver service. Supported values are NodePort or ClusterIP. If unset, defaults to NodePort. + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. type: string selector: - description: Selector selects a set of DNSNames on the Certificate resource that should be solved using this challenge solver. If not specified, the solver will be treated as the 'default' solver with the lowest priority, i.e. if any other solver has a more specific match, it will be used instead. + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. type: object properties: dnsNames: - description: List of DNSNames that this solver will be used to solve. If specified and a match is found, a dnsNames selector will take precedence over a dnsZones selector. If multiple solvers match with the same dnsNames value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. type: array items: type: string dnsZones: - description: List of DNSZones that this solver will be used to solve. The most specific DNS zone match specified here will take precedence over other DNS zone matches, so a solver specifying sys.example.com will be selected over one specifying example.com for the domain www.sys.example.com. If multiple solvers match with the same dnsZones value, the solver with the most matching labels in matchLabels will be selected. If neither has more matches, the solver defined earlier in the list will be selected. + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. type: array items: type: string matchLabels: - description: A label selector that is used to refine the set of certificate's that this challenge solver will apply to. + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. type: object additionalProperties: type: string ca: - description: CA configures this issuer to sign certificates using a signing CA keypair stored in a Secret resource. This is used to build internal PKIs that are managed by cert-manager. + description: |- + CA configures this issuer to sign certificates using a signing CA keypair + stored in a Secret resource. + This is used to build internal PKIs that are managed by cert-manager. type: object required: - secretName properties: crlDistributionPoints: - description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set, certificates will be issued without distribution points set. + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + issuingCertificateURLs: + description: |- + IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates + it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. + As an example, such a URL might be "http://ca.domain.com/ca.crt". type: array items: type: string ocspServers: - description: The OCSP server list is an X.509 v3 extension that defines a list of URLs of OCSP responders. The OCSP responders can be queried for the revocation status of an issued certificate. If not set, the certificate will be issued with no OCSP servers set. For example, an OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + description: |- + The OCSP server list is an X.509 v3 extension that defines a list of + URLs of OCSP responders. The OCSP responders can be queried for the + revocation status of an issued certificate. If not set, the + certificate will be issued with no OCSP servers set. For example, an + OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". type: array items: type: string secretName: - description: SecretName is the name of the secret used to sign Certificates issued by this Issuer. + description: |- + SecretName is the name of the secret used to sign Certificates issued + by this Issuer. type: string selfSigned: - description: SelfSigned configures this issuer to 'self sign' certificates using the private key used to create the CertificateRequest object. + description: |- + SelfSigned configures this issuer to 'self sign' certificates using the + private key used to create the CertificateRequest object. type: object properties: crlDistributionPoints: - description: The CRL distribution points is an X.509 v3 certificate extension which identifies the location of the CRL from which the revocation of this certificate can be checked. If not set certificate will be issued without CDP. Values are strings. + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set certificate will be issued without CDP. Values are strings. type: array items: type: string vault: - description: Vault configures this issuer to sign certificates using a HashiCorp Vault PKI backend. + description: |- + Vault configures this issuer to sign certificates using a HashiCorp Vault + PKI backend. type: object required: - auth @@ -4075,7 +7544,9 @@ spec: type: object properties: appRole: - description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. type: object required: - path @@ -4083,53 +7554,94 @@ spec: - secretRef properties: path: - description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + description: |- + Path where the App Role authentication backend is mounted in Vault, e.g: + "approle" type: string roleId: - description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. type: string secretRef: - description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string kubernetes: - description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. type: object required: - role properties: mountPath: - description: The Vault mountPath here is the mount path to use when authenticating with Vault. For example, setting a value to `/v1/auth/foo`, will use the path `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the default value "/v1/auth/kubernetes" will be used. + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/kubernetes" will be used. type: string role: - description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. type: string secretRef: - description: The required Secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. Use of 'ambient credentials' is not supported. + description: |- + The required Secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. Use of 'ambient credentials' is not + supported. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string serviceAccountRef: - description: A reference to a service account that will be used to request a bound token (also known as "projected token"). Compared to using "secretRef", using this field means that you don't rely on statically bound tokens. To use this field, you must configure an RBAC rule to let cert-manager request a token. + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). Compared to using "secretRef", + using this field means that you don't rely on statically bound tokens. To + use this field, you must configure an RBAC rule to let cert-manager + request a token. type: object required: - name properties: + audiences: + description: |- + TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token + consisting of the issuer's namespace and name is always included. + type: array + items: + type: string name: description: Name of the ServiceAccount used to request a token. type: string @@ -4140,44 +7652,112 @@ spec: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string caBundle: - description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by Vault. Only used if using HTTPS to connect to Vault and ignored for HTTP connections. Mutually exclusive with CABundleSecretRef. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by Vault. Only used if using HTTPS to connect to Vault and + ignored for HTTP connections. + Mutually exclusive with CABundleSecretRef. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. type: string format: byte caBundleSecretRef: - description: Reference to a Secret containing a bundle of PEM-encoded CAs to use when verifying the certificate chain presented by Vault when using HTTPS. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + description: |- + Reference to a Secret containing a bundle of PEM-encoded CAs to use when + verifying the certificate chain presented by Vault when using HTTPS. + Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + If no key for the Secret is specified, cert-manager will default to 'ca.crt'. type: object required: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertSecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Certificate to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientKeySecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Private Key to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string namespace: - description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces type: string path: - description: 'Path is the mount path of the Vault PKI backend''s `sign` endpoint, e.g: "my_pki_mount/sign/my-role-name".' + description: |- + Path is the mount path of the Vault PKI backend's `sign` endpoint, e.g: + "my_pki_mount/sign/my-role-name". type: string server: description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' type: string venafi: - description: Venafi configures this issuer to sign certificates using a Venafi TPP or Venafi Cloud policy zone. + description: |- + Venafi configures this issuer to sign certificates using a Venafi TPP + or Venafi Cloud policy zone. type: object required: - zone properties: cloud: - description: Cloud specifies the Venafi cloud configuration settings. Only one of TPP or Cloud may be specified. + description: |- + Cloud specifies the Venafi cloud configuration settings. + Only one of TPP or Cloud may be specified. type: object required: - apiTokenSecretRef @@ -4189,59 +7769,96 @@ spec: - name properties: key: - description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. type: string name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string url: - description: URL is the base URL for Venafi Cloud. Defaults to "https://api.venafi.cloud/v1". + description: |- + URL is the base URL for Venafi Cloud. + Defaults to "https://api.venafi.cloud/v1". type: string tpp: - description: TPP specifies Trust Protection Platform configuration settings. Only one of TPP or Cloud may be specified. + description: |- + TPP specifies Trust Protection Platform configuration settings. + Only one of TPP or Cloud may be specified. type: object required: - credentialsRef - url properties: caBundle: - description: Base64-encoded bundle of PEM CAs which will be used to validate the certificate chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain. + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. + If undefined, the certificate bundle in the cert-manager controller container + is used to validate the chain. type: string format: byte credentialsRef: - description: CredentialsRef is a reference to a Secret containing the username and password for the TPP server. The secret must contain two keys, 'username' and 'password'. + description: |- + CredentialsRef is a reference to a Secret containing the username and + password for the TPP server. + The secret must contain two keys, 'username' and 'password'. type: object required: - name properties: name: - description: 'Name of the resource being referred to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string url: - description: 'URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, for example: "https://tpp.example.com/vedsdk".' + description: |- + URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, + for example: "https://tpp.example.com/vedsdk". type: string zone: - description: Zone is the Venafi Policy Zone to use for this issuer. All requests made to the Venafi platform will be restricted by the named zone policy. This field is required. + description: |- + Zone is the Venafi Policy Zone to use for this issuer. + All requests made to the Venafi platform will be restricted by the named + zone policy. + This field is required. type: string status: description: Status of the Issuer. This is set and managed automatically. type: object properties: acme: - description: ACME specific status options. This field should only be set if the Issuer is configured to use an ACME server to issue certificates. + description: |- + ACME specific status options. + This field should only be set if the Issuer is configured to use an ACME + server to issue certificates. type: object properties: lastPrivateKeyHash: - description: LastPrivateKeyHash is a hash of the private key associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + description: |- + LastPrivateKeyHash is a hash of the private key associated with the latest + registered ACME account, in order to track changes made to registered account + associated with the Issuer type: string lastRegisteredEmail: - description: LastRegisteredEmail is the email associated with the latest registered ACME account, in order to track changes made to registered account associated with the Issuer + description: |- + LastRegisteredEmail is the email associated with the latest registered + ACME account, in order to track changes made to registered account + associated with the Issuer type: string uri: - description: URI is the unique account identifier, which can also be used to retrieve account details from the CA + description: |- + URI is the unique account identifier, which can also be used to retrieve + account details from the CA type: string conditions: - description: List of status conditions to indicate the status of a CertificateRequest. Known condition types are `Ready`. + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`. type: array items: description: IssuerCondition contains condition information for an Issuer. @@ -4251,18 +7868,29 @@ spec: - type properties: lastTransitionTime: - description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. type: string format: date-time message: - description: Message is a human readable description of the details of the last transition, complementing reason. + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. type: string observedGeneration: - description: If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Issuer. + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Issuer. type: integer format: int64 reason: - description: Reason is a brief machine readable explanation for the condition's last transition. + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. type: string status: description: Status of the condition, one of (`True`, `False`, `Unknown`). @@ -4279,15 +7907,24 @@ spec: x-kubernetes-list-type: map served: true storage: true + +# END crd {{- end }} + --- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: orders.acme.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} labels: app: '{{ template "cert-manager.name" . }}' app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: "crds" # Generated labels {{- include "labels" . | nindent 4 }} spec: group: acme.cert-manager.io @@ -4329,10 +7966,19 @@ spec: - spec properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -4343,23 +7989,39 @@ spec: - request properties: commonName: - description: CommonName is the common name as specified on the DER encoded CSR. If specified, this value must also be present in `dnsNames` or `ipAddresses`. This field must match the corresponding field on the DER encoded CSR. + description: |- + CommonName is the common name as specified on the DER encoded CSR. + If specified, this value must also be present in `dnsNames` or `ipAddresses`. + This field must match the corresponding field on the DER encoded CSR. type: string dnsNames: - description: DNSNames is a list of DNS names that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR. + description: |- + DNSNames is a list of DNS names that should be included as part of the Order + validation process. + This field must match the corresponding field on the DER encoded CSR. type: array items: type: string duration: - description: Duration is the duration for the not after date for the requested certificate. this is set on order creation as pe the ACME spec. + description: |- + Duration is the duration for the not after date for the requested certificate. + this is set on order creation as pe the ACME spec. type: string ipAddresses: - description: IPAddresses is a list of IP addresses that should be included as part of the Order validation process. This field must match the corresponding field on the DER encoded CSR. + description: |- + IPAddresses is a list of IP addresses that should be included as part of the Order + validation process. + This field must match the corresponding field on the DER encoded CSR. type: array items: type: string issuerRef: - description: IssuerRef references a properly configured ACME-type Issuer which should be used to create this Order. If the Issuer does not exist, processing will be retried. If the Issuer is not an 'ACME' Issuer, an error will be returned and the Order will be marked as failed. + description: |- + IssuerRef references a properly configured ACME-type Issuer which should + be used to create this Order. + If the Issuer does not exist, processing will be retried. + If the Issuer is not an 'ACME' Issuer, an error will be returned and the + Order will be marked as failed. type: object required: - name @@ -4374,26 +8036,42 @@ spec: description: Name of the resource being referred to. type: string request: - description: Certificate signing request bytes in DER encoding. This will be used when finalizing the order. This field must be set on the order. + description: |- + Certificate signing request bytes in DER encoding. + This will be used when finalizing the order. + This field must be set on the order. type: string format: byte status: type: object properties: authorizations: - description: Authorizations contains data returned from the ACME server on what authorizations must be completed in order to validate the DNS names specified on the Order. + description: |- + Authorizations contains data returned from the ACME server on what + authorizations must be completed in order to validate the DNS names + specified on the Order. type: array items: - description: ACMEAuthorization contains data returned from the ACME server on an authorization that must be completed in order validate a DNS name on an ACME Order resource. + description: |- + ACMEAuthorization contains data returned from the ACME server on an + authorization that must be completed in order validate a DNS name on an ACME + Order resource. type: object required: - url properties: challenges: - description: Challenges specifies the challenge types offered by the ACME server. One of these challenge types will be selected when validating the DNS name and an appropriate Challenge resource will be created to perform the ACME challenge process. + description: |- + Challenges specifies the challenge types offered by the ACME server. + One of these challenge types will be selected when validating the DNS + name and an appropriate Challenge resource will be created to perform + the ACME challenge process. type: array items: - description: Challenge specifies a challenge offered by the ACME server for an Order. An appropriate Challenge resource can be created to perform the ACME challenge process. + description: |- + Challenge specifies a challenge offered by the ACME server for an Order. + An appropriate Challenge resource can be created to perform the ACME + challenge process. type: object required: - token @@ -4401,19 +8079,36 @@ spec: - url properties: token: - description: Token is the token that must be presented for this challenge. This is used to compute the 'key' that must also be presented. + description: |- + Token is the token that must be presented for this challenge. + This is used to compute the 'key' that must also be presented. type: string type: - description: Type is the type of challenge being offered, e.g. 'http-01', 'dns-01', 'tls-sni-01', etc. This is the raw value retrieved from the ACME server. Only 'http-01' and 'dns-01' are supported by cert-manager, other values will be ignored. + description: |- + Type is the type of challenge being offered, e.g. 'http-01', 'dns-01', + 'tls-sni-01', etc. + This is the raw value retrieved from the ACME server. + Only 'http-01' and 'dns-01' are supported by cert-manager, other values + will be ignored. type: string url: - description: URL is the URL of this challenge. It can be used to retrieve additional metadata about the Challenge from the ACME server. + description: |- + URL is the URL of this challenge. It can be used to retrieve additional + metadata about the Challenge from the ACME server. type: string identifier: description: Identifier is the DNS name to be validated as part of this authorization type: string initialState: - description: InitialState is the initial state of the ACME authorization when first fetched from the ACME server. If an Authorization is already 'valid', the Order controller will not create a Challenge resource for the authorization. This will occur when working with an ACME server that enables 'authz reuse' (such as Let's Encrypt's production endpoint). If not set and 'identifier' is set, the state is assumed to be pending and a Challenge will be created. + description: |- + InitialState is the initial state of the ACME authorization when first + fetched from the ACME server. + If an Authorization is already 'valid', the Order controller will not + create a Challenge resource for the authorization. This will occur when + working with an ACME server that enables 'authz reuse' (such as Let's + Encrypt's production endpoint). + If not set and 'identifier' is set, the state is assumed to be pending + and a Challenge will be created. type: string enum: - valid @@ -4427,24 +8122,41 @@ spec: description: URL is the URL of the Authorization that must be completed type: string wildcard: - description: Wildcard will be true if this authorization is for a wildcard DNS name. If this is true, the identifier will be the *non-wildcard* version of the DNS name. For example, if '*.example.com' is the DNS name being validated, this field will be 'true' and the 'identifier' field will be 'example.com'. + description: |- + Wildcard will be true if this authorization is for a wildcard DNS name. + If this is true, the identifier will be the *non-wildcard* version of + the DNS name. + For example, if '*.example.com' is the DNS name being validated, this + field will be 'true' and the 'identifier' field will be 'example.com'. type: boolean certificate: - description: Certificate is a copy of the PEM encoded certificate for this Order. This field will be populated after the order has been successfully finalized with the ACME server, and the order has transitioned to the 'valid' state. + description: |- + Certificate is a copy of the PEM encoded certificate for this Order. + This field will be populated after the order has been successfully + finalized with the ACME server, and the order has transitioned to the + 'valid' state. type: string format: byte failureTime: - description: FailureTime stores the time that this order failed. This is used to influence garbage collection and back-off. + description: |- + FailureTime stores the time that this order failed. + This is used to influence garbage collection and back-off. type: string format: date-time finalizeURL: - description: FinalizeURL of the Order. This is used to obtain certificates for this order once it has been completed. + description: |- + FinalizeURL of the Order. + This is used to obtain certificates for this order once it has been completed. type: string reason: - description: Reason optionally provides more information about a why the order is in the current state. + description: |- + Reason optionally provides more information about a why the order is in + the current state. type: string state: - description: State contains the current state of this Order resource. States 'success' and 'expired' are 'final' + description: |- + State contains the current state of this Order resource. + States 'success' and 'expired' are 'final' type: string enum: - valid @@ -4455,8 +8167,13 @@ spec: - expired - errored url: - description: URL of the Order. This will initially be empty when the resource is first created. The Order controller will populate this field when the Order is first processed. This field will be immutable after it is initially set. + description: |- + URL of the Order. + This will initially be empty when the resource is first created. + The Order controller will populate this field when the Order is first processed. + This field will be immutable after it is initially set. type: string served: true storage: true -{{- end }} + +# END crd {{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/deployment.yaml b/internal/constellation/helm/charts/cert-manager/templates/deployment.yaml index aea5736c0..e6f3f681e 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/deployment.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/deployment.yaml @@ -15,6 +15,10 @@ metadata: {{- end }} spec: replicas: {{ .Values.replicaCount }} + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.revisionHistoryLimit) (list "" (quote ""))) }} + revisionHistoryLimit: {{ .Values.global.revisionHistoryLimit }} + {{- end }} selector: matchLabels: app.kubernetes.io/name: {{ template "cert-manager.name" . }} @@ -39,7 +43,7 @@ spec: annotations: {{- toYaml . | nindent 8 }} {{- end }} - {{- if and .Values.prometheus.enabled (not .Values.prometheus.servicemonitor.enabled) }} + {{- if and .Values.prometheus.enabled (not (or .Values.prometheus.servicemonitor.enabled .Values.prometheus.podmonitor.enabled)) }} {{- if not .Values.podAnnotations }} annotations: {{- end }} @@ -52,6 +56,7 @@ spec: {{- if hasKey .Values "automountServiceAccountToken" }} automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} {{- end }} + enableServiceLinks: {{ .Values.enableServiceLinks }} {{- with .Values.global.priorityClassName }} priorityClassName: {{ . | quote }} {{- end }} @@ -59,20 +64,30 @@ spec: securityContext: {{- toYaml . | nindent 8 }} {{- end }} - {{- with .Values.volumes }} + {{- if or .Values.volumes .Values.config}} volumes: + {{- if .Values.config }} + - name: config + configMap: + name: {{ include "cert-manager.fullname" . }} + {{- end }} + {{ with .Values.volumes }} {{- toYaml . | nindent 8 }} + {{- end }} {{- end }} containers: - name: {{ .Chart.Name }}-controller - {{- with .Values.image }} - image: "{{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}}" - {{- end }} + image: "{{ template "image" (tuple .Values.image $.Chart.AppVersion) }}" imagePullPolicy: {{ .Values.image.pullPolicy }} args: - {{- if .Values.global.logLevel }} + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.logLevel) (list "" (quote ""))) }} - --v={{ .Values.global.logLevel }} {{- end }} + {{- if .Values.config }} + - --config=/var/cert-manager/config/config.yaml + {{- end }} + {{- $config := default .Values.config "" }} {{- if .Values.clusterResourceNamespace }} - --cluster-resource-namespace={{ .Values.clusterResourceNamespace }} {{- else }} @@ -122,6 +137,9 @@ spec: {{- with .Values.dns01RecursiveNameservers }} - --dns01-recursive-nameservers={{ . }} {{- end }} + {{- if .Values.disableAutoApproval }} + - --controllers=-certificaterequests-approver + {{- end }} ports: - containerPort: 9402 name: http-metrics @@ -133,9 +151,15 @@ spec: securityContext: {{- toYaml . | nindent 12 }} {{- end }} - {{- with .Values.volumeMounts }} + {{- if or .Values.config .Values.volumeMounts }} volumeMounts: + {{- if .Values.config }} + - name: config + mountPath: /var/cert-manager/config + {{- end }} + {{- with .Values.volumeMounts }} {{- toYaml . | nindent 12 }} + {{- end }} {{- end }} env: - name: POD_NAMESPACE @@ -202,3 +226,6 @@ spec: dnsConfig: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.hostAliases }} + hostAliases: {{ toYaml . | nindent 8 }} + {{- end }} \ No newline at end of file diff --git a/internal/constellation/helm/charts/cert-manager/templates/extras-objects.yaml b/internal/constellation/helm/charts/cert-manager/templates/extras-objects.yaml new file mode 100644 index 000000000..9ec3a7e9b --- /dev/null +++ b/internal/constellation/helm/charts/cert-manager/templates/extras-objects.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraObjects }} +--- +{{ tpl . $ }} +{{ end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/networkpolicy-egress.yaml b/internal/constellation/helm/charts/cert-manager/templates/networkpolicy-egress.yaml index 09712009d..37f90bd2e 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/networkpolicy-egress.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/networkpolicy-egress.yaml @@ -11,13 +11,9 @@ spec: {{- end }} podSelector: matchLabels: - app: {{ include "webhook.name" . }} app.kubernetes.io/name: {{ include "webhook.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/component: "webhook" - {{- with .Values.webhook.podLabels }} - {{- toYaml . | nindent 6 }} - {{- end }} policyTypes: - Egress {{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/networkpolicy-webhooks.yaml b/internal/constellation/helm/charts/cert-manager/templates/networkpolicy-webhooks.yaml index 349877a8b..3a0ed7a70 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/networkpolicy-webhooks.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/networkpolicy-webhooks.yaml @@ -12,13 +12,9 @@ spec: {{- end }} podSelector: matchLabels: - app: {{ include "webhook.name" . }} - app.kubernetes.io/name: {{ include "webhook.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/component: "webhook" - {{- with .Values.webhook.podLabels }} - {{- toYaml . | nindent 6 }} - {{- end }} + app.kubernetes.io/name: {{ include "webhook.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "webhook" policyTypes: - Ingress diff --git a/internal/constellation/helm/charts/cert-manager/templates/poddisruptionbudget.yaml b/internal/constellation/helm/charts/cert-manager/templates/poddisruptionbudget.yaml index dab75ce68..ae71eed29 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/poddisruptionbudget.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/poddisruptionbudget.yaml @@ -17,10 +17,13 @@ spec: app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/component: "controller" - {{- with .Values.podDisruptionBudget.minAvailable }} - minAvailable: {{ . }} + {{- if not (or (hasKey .Values.podDisruptionBudget "minAvailable") (hasKey .Values.podDisruptionBudget "maxUnavailable")) }} + minAvailable: 1 # Default value because minAvailable and maxUnavailable are not set {{- end }} - {{- with .Values.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ . }} + {{- if hasKey .Values.podDisruptionBudget "minAvailable" }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if hasKey .Values.podDisruptionBudget "maxUnavailable" }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/podmonitor.yaml b/internal/constellation/helm/charts/cert-manager/templates/podmonitor.yaml new file mode 100644 index 000000000..1adc0609c --- /dev/null +++ b/internal/constellation/helm/charts/cert-manager/templates/podmonitor.yaml @@ -0,0 +1,50 @@ +{{- if and .Values.prometheus.enabled (and .Values.prometheus.podmonitor.enabled .Values.prometheus.servicemonitor.enabled) }} +{{- fail "Either .Values.prometheus.podmonitor.enabled or .Values.prometheus.servicemonitor.enabled can be enabled at a time, but not both." }} +{{- else if and .Values.prometheus.enabled .Values.prometheus.podmonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ template "cert-manager.fullname" . }} +{{- if .Values.prometheus.podmonitor.namespace }} + namespace: {{ .Values.prometheus.podmonitor.namespace }} +{{- else }} + namespace: {{ include "cert-manager.namespace" . }} +{{- end }} + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + prometheus: {{ .Values.prometheus.podmonitor.prometheusInstance }} + {{- with .Values.prometheus.podmonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.prometheus.podmonitor.annotations }} + annotations: + {{- with .Values.prometheus.podmonitor.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +spec: + jobLabel: {{ template "cert-manager.fullname" . }} + selector: + matchLabels: + app.kubernetes.io/name: {{ template "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" +{{- if .Values.prometheus.podmonitor.namespace }} + namespaceSelector: + matchNames: + - {{ include "cert-manager.namespace" . }} +{{- end }} + podMetricsEndpoints: + - port: http-metrics + path: {{ .Values.prometheus.podmonitor.path }} + interval: {{ .Values.prometheus.podmonitor.interval }} + scrapeTimeout: {{ .Values.prometheus.podmonitor.scrapeTimeout }} + honorLabels: {{ .Values.prometheus.podmonitor.honorLabels }} + {{- with .Values.prometheus.servicemonitor.endpointAdditionalProperties }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/rbac.yaml b/internal/constellation/helm/charts/cert-manager/templates/rbac.yaml index 830e37285..7a27d4f7a 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/rbac.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/rbac.yaml @@ -398,6 +398,26 @@ subjects: namespace: {{ include "cert-manager.namespace" . }} kind: ServiceAccount +{{- if .Values.global.rbac.aggregateClusterRoles }} +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-cluster-view + labels: + app: {{ include "cert-manager.name" . }} + app.kubernetes.io/name: {{ include "cert-manager.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "controller" + {{- include "labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-cluster-reader: "true" +rules: + - apiGroups: ["cert-manager.io"] + resources: ["clusterissuers"] + verbs: ["get", "list", "watch"] + +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 @@ -414,6 +434,7 @@ metadata: rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-cluster-reader: "true" {{- end }} rules: - apiGroups: ["cert-manager.io"] @@ -453,6 +474,8 @@ rules: --- +{{- if not .Values.disableAutoApproval -}} + # Permission to approve CertificateRequests referencing cert-manager.io Issuers and ClusterIssuers apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -468,7 +491,12 @@ rules: - apiGroups: ["cert-manager.io"] resources: ["signers"] verbs: ["approve"] - resourceNames: ["issuers.cert-manager.io/*", "clusterissuers.cert-manager.io/*"] + {{- with .Values.approveSignerNames }} + resourceNames: + {{- range . }} + - {{ . | quote }} + {{- end }} + {{- end }} --- @@ -493,6 +521,8 @@ subjects: --- +{{- end -}} + # Permission to: # - Update and sign CertificatSigningeRequests referencing cert-manager.io Issuers and ClusterIssuers # - Perform SubjectAccessReviews to test whether users are able to reference Namespaced Issuers diff --git a/internal/constellation/helm/charts/cert-manager/templates/service.yaml b/internal/constellation/helm/charts/cert-manager/templates/service.yaml index ec34d5878..360ec645e 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/service.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/service.yaml @@ -1,4 +1,4 @@ -{{- if .Values.prometheus.enabled }} +{{- if and .Values.prometheus.enabled (not .Values.prometheus.podmonitor.enabled) }} apiVersion: v1 kind: Service metadata: @@ -19,6 +19,12 @@ metadata: {{- end }} spec: type: ClusterIP + {{- if .Values.serviceIPFamilyPolicy }} + ipFamilyPolicy: {{ .Values.serviceIPFamilyPolicy }} + {{- end }} + {{- if .Values.serviceIPFamilies }} + ipFamilies: {{ .Values.serviceIPFamilies | toYaml | nindent 2 }} + {{- end }} ports: - protocol: TCP port: 9402 diff --git a/internal/constellation/helm/charts/cert-manager/templates/serviceaccount.yaml b/internal/constellation/helm/charts/cert-manager/templates/serviceaccount.yaml index 6026842ff..87fc00ea7 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/serviceaccount.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/serviceaccount.yaml @@ -20,6 +20,6 @@ metadata: app.kubernetes.io/component: "controller" {{- include "labels" . | nindent 4 }} {{- with .Values.serviceAccount.labels }} - {{ toYaml . | nindent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/servicemonitor.yaml b/internal/constellation/helm/charts/cert-manager/templates/servicemonitor.yaml index 9d9e89992..b63886077 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/servicemonitor.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/servicemonitor.yaml @@ -1,4 +1,6 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.servicemonitor.enabled }} +{{- if and .Values.prometheus.enabled (and .Values.prometheus.podmonitor.enabled .Values.prometheus.servicemonitor.enabled) }} +{{- fail "Either .Values.prometheus.podmonitor.enabled or .Values.prometheus.servicemonitor.enabled can be enabled at a time, but not both." }} +{{- else if and .Values.prometheus.enabled .Values.prometheus.servicemonitor.enabled }} apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: @@ -42,4 +44,7 @@ spec: interval: {{ .Values.prometheus.servicemonitor.interval }} scrapeTimeout: {{ .Values.prometheus.servicemonitor.scrapeTimeout }} honorLabels: {{ .Values.prometheus.servicemonitor.honorLabels }} + {{- with .Values.prometheus.servicemonitor.endpointAdditionalProperties }} + {{- toYaml . | nindent 4 }} + {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/startupapicheck-job.yaml b/internal/constellation/helm/charts/cert-manager/templates/startupapicheck-job.yaml index a9b965e18..311b4c48e 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/startupapicheck-job.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/startupapicheck-job.yaml @@ -37,6 +37,7 @@ spec: {{- if hasKey .Values.startupapicheck "automountServiceAccountToken" }} automountServiceAccountToken: {{ .Values.startupapicheck.automountServiceAccountToken }} {{- end }} + enableServiceLinks: {{ .Values.startupapicheck.enableServiceLinks }} {{- with .Values.global.priorityClassName }} priorityClassName: {{ . | quote }} {{- end }} @@ -46,9 +47,7 @@ spec: {{- end }} containers: - name: {{ .Chart.Name }}-startupapicheck - {{- with .Values.startupapicheck.image }} - image: "{{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}}" - {{- end }} + image: "{{ template "image" (tuple .Values.startupapicheck.image $.Chart.AppVersion) }}" imagePullPolicy: {{ .Values.startupapicheck.image.pullPolicy }} args: - check diff --git a/internal/constellation/helm/charts/cert-manager/templates/webhook-config.yaml b/internal/constellation/helm/charts/cert-manager/templates/webhook-config.yaml index f3f72f02e..8f3ce20c3 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/webhook-config.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/webhook-config.yaml @@ -1,12 +1,6 @@ {{- if .Values.webhook.config -}} - {{- if not .Values.webhook.config.apiVersion -}} - {{- fail "webhook.config.apiVersion must be set" -}} - {{- end -}} - - {{- if not .Values.webhook.config.kind -}} - {{- fail "webhook.config.kind must be set" -}} - {{- end -}} -{{- end -}} +{{- $_ := .Values.webhook.config.apiVersion | required ".Values.webhook.config.apiVersion must be set !" -}} +{{- $_ := .Values.webhook.config.kind | required ".Values.webhook.config.kind must be set !" -}} apiVersion: v1 kind: ConfigMap metadata: @@ -19,7 +13,6 @@ metadata: app.kubernetes.io/component: "webhook" {{- include "labels" . | nindent 4 }} data: - {{- if .Values.webhook.config }} config.yaml: | - {{ .Values.webhook.config | toYaml | nindent 4 }} - {{- end }} + {{- .Values.webhook.config | toYaml | nindent 4 }} +{{- end -}} \ No newline at end of file diff --git a/internal/constellation/helm/charts/cert-manager/templates/webhook-deployment.yaml b/internal/constellation/helm/charts/cert-manager/templates/webhook-deployment.yaml index 043c4b150..ae5399e90 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/webhook-deployment.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/webhook-deployment.yaml @@ -15,6 +15,10 @@ metadata: {{- end }} spec: replicas: {{ .Values.webhook.replicaCount }} + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.revisionHistoryLimit) (list "" (quote ""))) }} + revisionHistoryLimit: {{ .Values.global.revisionHistoryLimit }} + {{- end }} selector: matchLabels: app.kubernetes.io/name: {{ include "webhook.name" . }} @@ -44,6 +48,7 @@ spec: {{- if hasKey .Values.webhook "automountServiceAccountToken" }} automountServiceAccountToken: {{ .Values.webhook.automountServiceAccountToken }} {{- end }} + enableServiceLinks: {{ .Values.webhook.enableServiceLinks }} {{- with .Values.global.priorityClassName }} priorityClassName: {{ . | quote }} {{- end }} @@ -54,14 +59,16 @@ spec: {{- if .Values.webhook.hostNetwork }} hostNetwork: true {{- end }} + {{- if .Values.webhook.hostNetwork }} + dnsPolicy: ClusterFirstWithHostNet + {{- end }} containers: - name: {{ .Chart.Name }}-webhook - {{- with .Values.webhook.image }} - image: "{{- if .registry -}}{{ .registry }}/{{- end -}}{{ .repository }}{{- if (.digest) -}} @{{ .digest }}{{- else -}}:{{ default $.Chart.AppVersion .tag }} {{- end -}}" - {{- end }} + image: "{{ template "image" (tuple .Values.webhook.image $.Chart.AppVersion) }}" imagePullPolicy: {{ .Values.webhook.image.pullPolicy }} args: - {{- if .Values.global.logLevel }} + {{- /* The if statement below is equivalent to {{- if $value }} but will also return true for 0. */ -}} + {{- if not (has (quote .Values.global.logLevel) (list "" (quote ""))) }} - --v={{ .Values.global.logLevel }} {{- end }} {{- if .Values.webhook.config }} @@ -71,8 +78,8 @@ spec: {{ if not $config.securePort -}} - --secure-port={{ .Values.webhook.securePort }} {{- end }} - {{- if .Values.featureGates }} - - --feature-gates={{ .Values.featureGates }} + {{- if .Values.webhook.featureGates }} + - --feature-gates={{ .Values.webhook.featureGates }} {{- end }} {{- $tlsConfig := default $config.tlsConfig "" }} {{ if or (not $config.tlsConfig) (and (not $tlsConfig.dynamic) (not $tlsConfig.filesystem) ) -}} @@ -152,8 +159,8 @@ spec: - name: config mountPath: /var/cert-manager/config {{- end }} - {{- if .Values.webhook.volumeMounts }} - {{- toYaml .Values.webhook.volumeMounts | nindent 12 }} + {{- with .Values.webhook.volumeMounts }} + {{- toYaml . | nindent 12 }} {{- end }} {{- end }} {{- with .Values.webhook.nodeSelector }} @@ -179,7 +186,7 @@ spec: configMap: name: {{ include "webhook.fullname" . }} {{- end }} - {{- if .Values.webhook.volumes }} - {{- toYaml .Values.webhook.volumes | nindent 8 }} + {{- with .Values.webhook.volumes }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/webhook-mutating-webhook.yaml b/internal/constellation/helm/charts/cert-manager/templates/webhook-mutating-webhook.yaml index f3db011ef..9ea29777d 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/webhook-mutating-webhook.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/webhook-mutating-webhook.yaml @@ -15,17 +15,19 @@ metadata: {{- end }} webhooks: - name: webhook.cert-manager.io + {{- with .Values.webhook.mutatingWebhookConfiguration.namespaceSelector }} + namespaceSelector: + {{- toYaml . | nindent 6 }} + {{- end }} rules: - apiGroups: - "cert-manager.io" - - "acme.cert-manager.io" apiVersions: - "v1" operations: - CREATE - - UPDATE resources: - - "*/*" + - "certificaterequests" admissionReviewVersions: ["v1"] # This webhook only accepts v1 cert-manager resources. # Equivalent matchPolicy ensures that non-v1 resource requests are sent to @@ -43,4 +45,4 @@ webhooks: name: {{ template "webhook.fullname" . }} namespace: {{ include "cert-manager.namespace" . }} path: /mutate - {{- end }} + {{- end }} \ No newline at end of file diff --git a/internal/constellation/helm/charts/cert-manager/templates/webhook-poddisruptionbudget.yaml b/internal/constellation/helm/charts/cert-manager/templates/webhook-poddisruptionbudget.yaml index c8a357cb1..ab2a48109 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/webhook-poddisruptionbudget.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/webhook-poddisruptionbudget.yaml @@ -17,10 +17,13 @@ spec: app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/component: "webhook" - {{- with .Values.webhook.podDisruptionBudget.minAvailable }} - minAvailable: {{ . }} + {{- if not (or (hasKey .Values.webhook.podDisruptionBudget "minAvailable") (hasKey .Values.webhook.podDisruptionBudget "maxUnavailable")) }} + minAvailable: 1 # Default value because minAvailable and maxUnavailable are not set {{- end }} - {{- with .Values.webhook.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ . }} + {{- if hasKey .Values.webhook.podDisruptionBudget "minAvailable" }} + minAvailable: {{ .Values.webhook.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if hasKey .Values.webhook.podDisruptionBudget "maxUnavailable" }} + maxUnavailable: {{ .Values.webhook.podDisruptionBudget.maxUnavailable }} {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/webhook-service.yaml b/internal/constellation/helm/charts/cert-manager/templates/webhook-service.yaml index 5f9395049..86d47f164 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/webhook-service.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/webhook-service.yaml @@ -18,6 +18,12 @@ metadata: {{- end }} spec: type: {{ .Values.webhook.serviceType }} + {{- if .Values.webhook.serviceIPFamilyPolicy }} + ipFamilyPolicy: {{ .Values.webhook.serviceIPFamilyPolicy }} + {{- end }} + {{- if .Values.webhook.serviceIPFamilies }} + ipFamilies: {{ .Values.webhook.serviceIPFamilies | toYaml | nindent 2 }} + {{- end }} {{- with .Values.webhook.loadBalancerIP }} loadBalancerIP: {{ . }} {{- end }} diff --git a/internal/constellation/helm/charts/cert-manager/templates/webhook-validating-webhook.yaml b/internal/constellation/helm/charts/cert-manager/templates/webhook-validating-webhook.yaml index a5d168e29..76235fdee 100644 --- a/internal/constellation/helm/charts/cert-manager/templates/webhook-validating-webhook.yaml +++ b/internal/constellation/helm/charts/cert-manager/templates/webhook-validating-webhook.yaml @@ -15,16 +15,10 @@ metadata: {{- end }} webhooks: - name: webhook.cert-manager.io + {{- with .Values.webhook.validatingWebhookConfiguration.namespaceSelector }} namespaceSelector: - matchExpressions: - - key: "cert-manager.io/disable-validation" - operator: "NotIn" - values: - - "true" - - key: "name" - operator: "NotIn" - values: - - {{ include "cert-manager.namespace" . }} + {{- toYaml . | nindent 6 }} + {{- end }} rules: - apiGroups: - "cert-manager.io" diff --git a/internal/constellation/helm/charts/cert-manager/values.yaml b/internal/constellation/helm/charts/cert-manager/values.yaml index 0870178c4..ae304af7b 100644 --- a/internal/constellation/helm/charts/cert-manager/values.yaml +++ b/internal/constellation/helm/charts/cert-manager/values.yaml @@ -1,199 +1,376 @@ +# +docs:section=Global + # Default values for cert-manager. # This is a YAML-formatted file. # Declare variables to be passed into your templates. global: - # Reference to one or more secrets to be used when pulling images - # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + # Reference to one or more secrets to be used when pulling images. + # For more information, see [Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/). + # + # For example: + # imagePullSecrets: + # - name: "image-pull-secret" imagePullSecrets: [] - # - name: "image-pull-secret" - - # Labels to apply to all resources + # Labels to apply to all resources. # Please note that this does not add labels to the resources created dynamically by the controllers. # For these resources, you have to add the labels in the template in the cert-manager custom resource: - # eg. podTemplate/ ingressTemplate in ACMEChallengeSolverHTTP01Ingress - # ref: https://cert-manager.io/docs/reference/api-docs/#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01Ingress - # eg. secretTemplate in CertificateSpec - # ref: https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec + # For example, podTemplate/ ingressTemplate in ACMEChallengeSolverHTTP01Ingress + # For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01Ingress). + # For example, secretTemplate in CertificateSpec + # For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec). commonLabels: {} - # team_name: dev + # The number of old ReplicaSets to retain to allow rollback (if not set, the default Kubernetes value is set to 10). + # +docs:property + # revisionHistoryLimit: 1 - # Optional priority class to be used for the cert-manager pods + # The optional priority class to be used for the cert-manager pods. priorityClassName: "" rbac: + # Create required ClusterRoles and ClusterRoleBindings for cert-manager. create: true - # Aggregate ClusterRoles to Kubernetes default user-facing roles. Ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + # Aggregate ClusterRoles to Kubernetes default user-facing roles. For more information, see [User-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) aggregateClusterRoles: true podSecurityPolicy: + # Create PodSecurityPolicy for cert-manager. + # + # Note that PodSecurityPolicy was deprecated in Kubernetes 1.21 and removed in Kubernetes 1.25. enabled: false + # Configure the PodSecurityPolicy to use AppArmor. useAppArmor: true - # Set the verbosity of cert-manager. Range of 0 - 6 with 6 being the most verbose. + # Set the verbosity of cert-manager. A range of 0 - 6, with 6 being the most verbose. logLevel: 2 leaderElection: - # Override the namespace used for the leader election lease + # Override the namespace used for the leader election lease. namespace: "kube-system" # The duration that non-leader candidates will wait after observing a # leadership renewal until attempting to acquire leadership of a led but # unrenewed leader slot. This is effectively the maximum duration that a # leader can be stopped before it is replaced by another candidate. + # +docs:property # leaseDuration: 60s # The interval between attempts by the acting master to renew a leadership # slot before it stops leading. This must be less than or equal to the # lease duration. +# +docs:property # renewDeadline: 40s # The duration the clients should wait between attempting acquisition and # renewal of a leadership. +# +docs:property # retryPeriod: 15s + +# This option is equivalent to setting crds.enabled=true and crds.keep=true. +# Deprecated: use crds.enabled and crds.keep instead. installCRDs: false -replicaCount: 1 -strategy: {} -# type: RollingUpdate -# rollingUpdate: -# maxSurge: 0 -# maxUnavailable: 1 - -podDisruptionBudget: +crds: + # This option decides if the CRDs should be installed + # as part of the Helm installation. enabled: false - minAvailable: 1 - # maxUnavailable: 1 -# minAvailable and maxUnavailable can either be set to an integer (e.g. 1) -# or a percentage value (e.g. 25%) + # This option makes it so that the "helm.sh/resource-policy": keep + # annotation is added to the CRD. This will prevent Helm from uninstalling + # the CRD when the Helm release is uninstalled. + # WARNING: when the CRDs are removed, all cert-manager custom resources + # (Certificates, Issuers, ...) will be removed too by the garbage collector. + keep: true +# +docs:section=Controller -# Comma separated list of feature gates that should be enabled on the controller -# Note: do not use this field to pass feature gate values into webhook -# component as this behaviour relies on a bug that will be fixed in cert-manager 1.13 -# https://github.com/cert-manager/cert-manager/pull/6093 -# Use webhook.extraArgs to pass --feature-gates flag directly instead. +# The number of replicas of the cert-manager controller to run. +# +# The default is 1, but in production set this to 2 or 3 to provide high +# availability. +# +# If `replicas > 1`, consider setting `podDisruptionBudget.enabled=true`. +# +# Note that cert-manager uses leader election to ensure that there can +# only be a single instance active at a time. +replicaCount: 1 +# Deployment update strategy for the cert-manager controller deployment. +# For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). +# +# For example: +# strategy: +# type: RollingUpdate +# rollingUpdate: +# maxSurge: 0 +# maxUnavailable: 1 +strategy: {} +podDisruptionBudget: + # Enable or disable the PodDisruptionBudget resource. + # + # This prevents downtime during voluntary disruptions such as during a Node upgrade. + # For example, the PodDisruptionBudget will block `kubectl drain` + # if it is used on the Node where the only remaining cert-manager + # Pod is currently running. + enabled: false + # This configures the minimum available pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # It cannot be used if `maxUnavailable` is set. + # +docs:property + # minAvailable: 1 +# This configures the maximum unavailable pods for disruptions. It can either be set to +# an integer (e.g. 1) or a percentage value (e.g. 25%). +# it cannot be used if `minAvailable` is set. +# +docs:property +# maxUnavailable: 1 + +# A comma-separated list of feature gates that should be enabled on the +# controller pod. featureGates: "" -# The maximum number of challenges that can be scheduled as 'processing' at once +# The maximum number of challenges that can be scheduled as 'processing' at once. maxConcurrentChallenges: 60 image: - repository: quay.io/jetstack/cert-manager-controller - # You can manage a registry with + # The container registry to pull the manager image from. + # +docs:property # registry: quay.io - # repository: jetstack/cert-manager-controller + # The container image for the cert-manager controller. + # +docs:property + repository: quay.io/jetstack/cert-manager-controller # Override the image tag to deploy by setting this variable. - # If no value is set, the chart's appVersion will be used. - # tag: canary + # If no value is set, the chart's appVersion is used. + # +docs:property + # tag: vX.Y.Z - # Setting a digest will override any tag + # Setting a digest will override any tag. + # +docs:property # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. pullPolicy: IfNotPresent - digest: sha256:fb2546fe51e49206dbf72bb0d6f909a0018eda0c2b024547b03d3f3d604e4c5e + digest: sha256:9b5d5e9c0fd4944221d059921cc05f388c9a5fc0b02a60b47f0eccfcd8243331 # Override the namespace used to store DNS provider credentials etc. for ClusterIssuer # resources. By default, the same namespace as cert-manager is deployed within is # used. This namespace will not be automatically created by the Helm chart. clusterResourceNamespace: "" -# This namespace allows you to define where the services will be installed into -# if not set then they will use the namespace of the release -# This is helpful when installing cert manager as a chart dependency (sub chart) +# This namespace allows you to define where the services are installed into. +# If not set then they use the namespace of the release. +# This is helpful when installing cert manager as a chart dependency (sub chart). namespace: "" serviceAccount: - # Specifies whether a service account should be created + # Specifies whether a service account should be created. create: true # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template + # If not set and create is true, a name is generated using the fullname template. + # +docs:property # name: "" - # Optional additional annotations to add to the controller's ServiceAccount + + # Optional additional annotations to add to the controller's Service Account. + # +docs:property # annotations: {} - # Automount API credentials for a Service Account. - # Optional additional labels to add to the controller's ServiceAccount + + # Optional additional labels to add to the controller's Service Account. + # +docs:property # labels: {} + + # Automount API credentials for a Service Account. automountServiceAccountToken: true -# Automounting API credentials for a particular pod +# Automounting API credentials for a particular pod. +# +docs:property # automountServiceAccountToken: true -# When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted +# When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted. enableCertificateOwnerRef: false -# Setting Nameservers for DNS01 Self Check -# See: https://cert-manager.io/docs/configuration/acme/dns01/#setting-nameservers-for-dns01-self-check +# This property is used to configure options for the controller pod. +# This allows setting options that would usually be provided using flags. +# An APIVersion and Kind must be specified in your values.yaml file. +# Flags will override options that are set here. +# +# For example: +# config: +# apiVersion: controller.config.cert-manager.io/v1alpha1 +# kind: ControllerConfiguration +# logging: +# verbosity: 2 +# format: text +# leaderElectionConfig: +# namespace: kube-system +# kubernetesAPIQPS: 9000 +# kubernetesAPIBurst: 9000 +# numberOfConcurrentWorkers: 200 +# featureGates: +# AdditionalCertificateOutputFormats: true +# DisallowInsecureCSRUsageDefinition: true +# ExperimentalCertificateSigningRequestControllers: true +# ExperimentalGatewayAPISupport: true +# LiteralCertificateSubject: true +# SecretsFilteredCaching: true +# ServerSideApply: true +# StableCertificateRequestName: true +# UseCertificateRequestBasicConstraints: true +# ValidateCAA: true +# metricsTLSConfig: +# dynamic: +# secretNamespace: "cert-manager" +# secretName: "cert-manager-metrics-ca" +# dnsNames: +# - cert-manager-metrics +# - cert-manager-metrics.cert-manager +# - cert-manager-metrics.cert-manager.svc +config: {} +# Setting Nameservers for DNS01 Self Check. +# For more information, see the [cert-manager documentation](https://cert-manager.io/docs/configuration/acme/dns01/#setting-nameservers-for-dns01-self-check). -# Comma separated string with host and port of the recursive nameservers cert-manager should query +# A comma-separated string with the host and port of the recursive nameservers cert-manager should query. dns01RecursiveNameservers: "" -# Forces cert-manager to only use the recursive nameservers for verification. -# Enabling this option could cause the DNS01 self check to take longer due to caching performed by the recursive nameservers +# Forces cert-manager to use only the recursive nameservers for verification. +# Enabling this option could cause the DNS01 self check to take longer owing to caching performed by the recursive nameservers. dns01RecursiveNameserversOnly: false +# Option to disable cert-manager's build-in auto-approver. The auto-approver +# approves all CertificateRequests that reference issuers matching the 'approveSignerNames' +# option. This 'disableAutoApproval' option is useful when you want to make all approval decisions +# using a different approver (like approver-policy - https://github.com/cert-manager/approver-policy). +disableAutoApproval: false +# List of signer names that cert-manager will approve by default. CertificateRequests +# referencing these signer names will be auto-approved by cert-manager. Defaults to just +# approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty +# array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, +# because eg. you are using approver-policy, you can enable 'disableAutoApproval'. +# ref: https://cert-manager.io/docs/concepts/certificaterequest/#approval +# +docs:property +approveSignerNames: + - issuers.cert-manager.io/* + - clusterissuers.cert-manager.io/* # Additional command line flags to pass to cert-manager controller binary. -# To see all available flags run docker run quay.io/jetstack/cert-manager-controller: --help +# To see all available flags run `docker run quay.io/jetstack/cert-manager-controller: --help`. +# +# Use this flag to enable or disable arbitrary controllers. For example, to disable the CertificiateRequests approver. +# +# For example: +# extraArgs: +# - --controllers=*,-certificaterequests-approver extraArgs: [] -# Use this flag to enable or disable arbitrary controllers, for example, disable the CertificiateRequests approver -# - --controllers=*,-certificaterequests-approver - +# Additional environment variables to pass to cert-manager controller binary. extraEnv: [] # - name: SOME_VAR # value: 'some value' +# Resources to provide to the cert-manager controller pod. +# +# For example: +# requests: +# cpu: 10m +# memory: 32Mi +# +# For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). resources: {} -# requests: -# cpu: 10m -# memory: 32Mi - -# Pod Security Context -# ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +# Pod Security Context. +# For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). +# +docs:property securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault -# Container Security Context to be set on the controller component container -# ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +# Container Security Context to be set on the controller component container. +# For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). +# +docs:property containerSecurityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true + readOnlyRootFilesystem: true +# Additional volumes to add to the cert-manager controller pod. volumes: [] +# Additional volume mounts to add to the cert-manager controller container. volumeMounts: [] -# Optional additional annotations to add to the controller Deployment +# Optional additional annotations to add to the controller Deployment. +# +docs:property # deploymentAnnotations: {} -# Optional additional annotations to add to the controller Pods +# Optional additional annotations to add to the controller Pods. +# +docs:property # podAnnotations: {} + +# Optional additional labels to add to the controller Pods. podLabels: {} -# Optional annotations to add to the controller Service +# Optional annotations to add to the controller Service. +# +docs:property # serviceAnnotations: {} -# Optional additional labels to add to the controller Service +# Optional additional labels to add to the controller Service. +# +docs:property # serviceLabels: {} -# Optional DNS settings, useful if you have a public and private DNS zone for -# the same domain on Route 53. What follows is an example of ensuring +# Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). +# +docs:property +# serviceIPFamilyPolicy: "" + +# Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6. +# +docs:property +# serviceIPFamilies: [] + +# Optional DNS settings. These are useful if you have a public and private DNS zone for +# the same domain on Route 53. The following is an example of ensuring # cert-manager can access an ingress or DNS TXT records at all times. -# NOTE: This requires Kubernetes 1.10 or `CustomPodDNS` feature gate enabled for +# Note that this requires Kubernetes 1.10 or `CustomPodDNS` feature gate enabled for # the cluster to work. + +# Pod DNS policy. +# For more information, see [Pod's DNS Policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). +# +docs:property # podDnsPolicy: "None" + +# Pod DNS configuration. The podDnsConfig field is optional and can work with any podDnsPolicy +# settings. However, when a Pod's dnsPolicy is set to "None", the dnsConfig field has to be specified. +# For more information, see [Pod's DNS Config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config). +# +docs:property # podDnsConfig: # nameservers: # - "1.1.1.1" # - "8.8.8.8" + +# Optional hostAliases for cert-manager-controller pods. May be useful when performing ACME DNS-01 self checks. +hostAliases: [] +# - ip: 127.0.0.1 +# hostnames: +# - foo.local +# - bar.local +# - ip: 10.1.2.3 +# hostnames: +# - foo.remote +# - bar.remote + +# The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with +# matching labels. +# For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). +# +# This default ensures that Pods are only scheduled to Linux nodes. +# It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. +# +docs:property nodeSelector: kubernetes.io/os: linux +# +docs:ignore ingressShim: {} +# Optional default issuer to use for ingress resources. +# +docs:property=ingressShim.defaultIssuerName # defaultIssuerName: "" + +# Optional default issuer kind to use for ingress resources. +# +docs:property=ingressShim.defaultIssuerKind # defaultIssuerKind: "" + +# Optional default issuer group to use for ingress resources. +# +docs:property=ingressShim.defaultIssuerGroup # defaultIssuerGroup: "" -prometheus: - enabled: true - servicemonitor: - enabled: false - prometheusInstance: default - targetPort: 9402 - path: /metrics - interval: 60s - scrapeTimeout: 30s - labels: {} - annotations: {} - honorLabels: false -# Use these variables to configure the HTTP_PROXY environment variables +# Use these variables to configure the HTTP_PROXY environment variables. + +# Configures the HTTP_PROXY environment variable where a HTTP proxy is required. +# +docs:property # http_proxy: "http://proxy:8080" + +# Configures the HTTPS_PROXY environment variable where a HTTP proxy is required. +# +docs:property # https_proxy: "https://proxy:8080" + +# Configures the NO_PROXY environment variable where a HTTP proxy is required, +# but certain domains should be excluded. +# +docs:property # no_proxy: 127.0.0.1,localhost -# A Kubernetes Affinty, if required; see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core -# for example: +# A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). +# +# For example: # affinity: # nodeAffinity: # requiredDuringSchedulingIgnoredDuringExecution: @@ -204,16 +381,18 @@ prometheus: # values: # - master affinity: {} -# A list of Kubernetes Tolerations, if required; see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core -# for example: +# A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). +# +# For example: # tolerations: # - key: foo.bar.com/role # operator: Equal # value: master # effect: NoSchedule tolerations: [] -# A list of Kubernetes TopologySpreadConstraints, if required; see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core -# for example: +# A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core +# +# For example: # topologySpreadConstraints: # - maxSkew: 2 # topologyKey: topology.kubernetes.io/zone @@ -225,150 +404,361 @@ tolerations: [] topologySpreadConstraints: [] # LivenessProbe settings for the controller container of the controller Pod. # -# Disabled by default, because the controller has a leader election mechanism -# which should cause it to exit if it is unable to renew its leader election -# record. +# This is enabled by default, in order to enable the clock-skew liveness probe that +# restarts the controller in case of a skew between the system clock and the monotonic clock. # LivenessProbe durations and thresholds are based on those used for the Kubernetes -# controller-manager. See: -# https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245 +# controller-manager. For more information see the following on the +# [Kubernetes GitHub repository](https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245) +# +docs:property livenessProbe: - enabled: false + enabled: true initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 15 successThreshold: 1 failureThreshold: 8 +# enableServiceLinks indicates whether information about services should be +# injected into the pod's environment variables, matching the syntax of Docker +# links. +enableServiceLinks: false +# +docs:section=Prometheus +prometheus: + # Enable Prometheus monitoring for the cert-manager controller to use with the + # Prometheus Operator. If this option is enabled without enabling `prometheus.servicemonitor.enabled` or + # `prometheus.podmonitor.enabled`, 'prometheus.io' annotations are added to the cert-manager Deployment + # resources. Additionally, a service is created which can be used together + # with your own ServiceMonitor (managed outside of this Helm chart). + # Otherwise, a ServiceMonitor/ PodMonitor is created. + enabled: true + servicemonitor: + # Create a ServiceMonitor to add cert-manager to Prometheus. + enabled: false + # Specifies the `prometheus` label on the created ServiceMonitor. This is + # used when different Prometheus instances have label selectors matching + # different ServiceMonitors. + prometheusInstance: default + # The target port to set on the ServiceMonitor. This must match the port that the + # cert-manager controller is listening on for metrics. + targetPort: 9402 + # The path to scrape for metrics. + path: /metrics + # The interval to scrape metrics. + interval: 60s + # The timeout before a metrics scrape fails. + scrapeTimeout: 30s + # Additional labels to add to the ServiceMonitor. + labels: {} + # Additional annotations to add to the ServiceMonitor. + annotations: {} + # Keep labels from scraped data, overriding server-side labels. + honorLabels: false + # EndpointAdditionalProperties allows setting additional properties on the + # endpoint such as relabelings, metricRelabelings etc. + # + # For example: + # endpointAdditionalProperties: + # relabelings: + # - action: replace + # sourceLabels: + # - __meta_kubernetes_pod_node_name + # targetLabel: instance + # + # +docs:property + endpointAdditionalProperties: {} + # Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in a error. + podmonitor: + # Create a PodMonitor to add cert-manager to Prometheus. + enabled: false + # Specifies the `prometheus` label on the created PodMonitor. This is + # used when different Prometheus instances have label selectors matching + # different PodMonitors. + prometheusInstance: default + # The path to scrape for metrics. + path: /metrics + # The interval to scrape metrics. + interval: 60s + # The timeout before a metrics scrape fails. + scrapeTimeout: 30s + # Additional labels to add to the PodMonitor. + labels: {} + # Additional annotations to add to the PodMonitor. + annotations: {} + # Keep labels from scraped data, overriding server-side labels. + honorLabels: false + # EndpointAdditionalProperties allows setting additional properties on the + # endpoint such as relabelings, metricRelabelings etc. + # + # For example: + # endpointAdditionalProperties: + # relabelings: + # - action: replace + # sourceLabels: + # - __meta_kubernetes_pod_node_name + # targetLabel: instance + # + # +docs:property + endpointAdditionalProperties: {} +# +docs:section=Webhook webhook: + # Number of replicas of the cert-manager webhook to run. + # + # The default is 1, but in production set this to 2 or 3 to provide high + # availability. + # + # If `replicas > 1`, consider setting `webhook.podDisruptionBudget.enabled=true`. replicaCount: 1 - timeoutSeconds: 10 - # Used to configure options for the webhook pod. - # This allows setting options that'd usually be provided via flags. + # The number of seconds the API server should wait for the webhook to respond before treating the call as a failure. + # The value must be between 1 and 30 seconds. For more information, see + # [Validating webhook configuration v1](https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/validating-webhook-configuration-v1/). + # + # The default is set to the maximum value of 30 seconds as + # users sometimes report that the connection between the K8S API server and + # the cert-manager webhook server times out. + # If *this* timeout is reached, the error message will be "context deadline exceeded", + # which doesn't help the user diagnose what phase of the HTTPS connection timed out. + # For example, it could be during DNS resolution, TCP connection, TLS + # negotiation, HTTP negotiation, or slow HTTP response from the webhook + # server. + # By setting this timeout to its maximum value the underlying timeout error + # message has more chance of being returned to the end user. + timeoutSeconds: 30 + # This is used to configure options for the webhook pod. + # This allows setting options that would usually be provided using flags. # An APIVersion and Kind must be specified in your values.yaml file. - # Flags will override options that are set here. - config: - # apiVersion: webhook.config.cert-manager.io/v1alpha1 - # kind: WebhookConfiguration - - # The port that the webhook should listen on for requests. - # In GKE private clusters, by default kubernetes apiservers are allowed to - # talk to the cluster nodes only on 443 and 10250. so configuring - # securePort: 10250, will work out of the box without needing to add firewall - # rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000. - # This should be uncommented and set as a default by the chart once we graduate - # the apiVersion of WebhookConfiguration past v1alpha1. - # securePort: 10250 + # Flags override options that are set here. + # + # For example: + # apiVersion: webhook.config.cert-manager.io/v1alpha1 + # kind: WebhookConfiguration + # # The port that the webhook listens on for requests. + # # In GKE private clusters, by default Kubernetes apiservers are allowed to + # # talk to the cluster nodes only on 443 and 10250. Configuring + # # securePort: 10250 therefore will work out-of-the-box without needing to add firewall + # # rules or requiring NET_BIND_SERVICE capabilities to bind port numbers < 1000. + # # This should be uncommented and set as a default by the chart once + # # the apiVersion of WebhookConfiguration graduates beyond v1alpha1. + # securePort: 10250 + config: {} + # The update strategy for the cert-manager webhook deployment. + # For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) + # + # For example: + # strategy: + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 0 + # maxUnavailable: 1 strategy: {} - # type: RollingUpdate - # rollingUpdate: - # maxSurge: 0 - # maxUnavailable: 1 - - # Pod Security Context to be set on the webhook component Pod - # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + # Pod Security Context to be set on the webhook component Pod. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault - podDisruptionBudget: - enabled: false - minAvailable: 1 - # maxUnavailable: 1 - # minAvailable and maxUnavailable can either be set to an integer (e.g. 1) - # or a percentage value (e.g. 25%) - - # Container Security Context to be set on the webhook component container - # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + # Container Security Context to be set on the webhook component container. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property containerSecurityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # Optional additional annotations to add to the webhook Deployment + readOnlyRootFilesystem: true + podDisruptionBudget: + # Enable or disable the PodDisruptionBudget resource. + # + # This prevents downtime during voluntary disruptions such as during a Node upgrade. + # For example, the PodDisruptionBudget will block `kubectl drain` + # if it is used on the Node where the only remaining cert-manager + # Pod is currently running. + enabled: false + # This property configures the minimum available pods for disruptions. Can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # It cannot be used if `maxUnavailable` is set. + # +docs:property + # minAvailable: 1 + # This property configures the maximum unavailable pods for disruptions. Can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # It cannot be used if `minAvailable` is set. + # +docs:property + # maxUnavailable: 1 + + # Optional additional annotations to add to the webhook Deployment. + # +docs:property # deploymentAnnotations: {} - # Optional additional annotations to add to the webhook Pods + # Optional additional annotations to add to the webhook Pods. + # +docs:property # podAnnotations: {} - # Optional additional annotations to add to the webhook Service + # Optional additional annotations to add to the webhook Service. + # +docs:property # serviceAnnotations: {} - # Optional additional annotations to add to the webhook MutatingWebhookConfiguration + # Optional additional annotations to add to the webhook MutatingWebhookConfiguration. + # +docs:property # mutatingWebhookConfigurationAnnotations: {} - # Optional additional annotations to add to the webhook ValidatingWebhookConfiguration + # Optional additional annotations to add to the webhook ValidatingWebhookConfiguration. + # +docs:property # validatingWebhookConfigurationAnnotations: {} - + validatingWebhookConfiguration: + # Configure spec.namespaceSelector for validating webhooks. + # +docs:property + namespaceSelector: + matchExpressions: + - key: "cert-manager.io/disable-validation" + operator: "NotIn" + values: + - "true" + mutatingWebhookConfiguration: + # Configure spec.namespaceSelector for mutating webhooks. + # +docs:property + namespaceSelector: {} + # matchLabels: + # key: value + # matchExpressions: + # - key: kubernetes.io/metadata.name + # operator: NotIn + # values: + # - kube-system # Additional command line flags to pass to cert-manager webhook binary. - # To see all available flags run docker run quay.io/jetstack/cert-manager-webhook: --help + # To see all available flags run `docker run quay.io/jetstack/cert-manager-webhook: --help`. extraArgs: [] - # Path to a file containing a WebhookConfiguration object used to configure the webhook + # Path to a file containing a WebhookConfiguration object used to configure the webhook. # - --config= + # Comma separated list of feature gates that should be enabled on the + # webhook pod. + featureGates: "" + # Resources to provide to the cert-manager webhook pod. + # + # For example: + # requests: + # cpu: 10m + # memory: 32Mi + # + # For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). resources: {} - # requests: - # cpu: 10m - # memory: 32Mi - - ## Liveness and readiness probe values - ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes - ## + # Liveness probe values. + # For more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes). + # + # +docs:property livenessProbe: failureThreshold: 3 initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 + # Readiness probe values. + # For more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes). + # + # +docs:property readinessProbe: failureThreshold: 3 initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 + # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with + # matching labels. + # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + # + # This default ensures that Pods are only scheduled to Linux nodes. + # It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + # +docs:property nodeSelector: kubernetes.io/os: linux + # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + # + # For example: + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: foo.bar.com/role + # operator: In + # values: + # - master affinity: {} + # A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + # + # For example: + # tolerations: + # - key: foo.bar.com/role + # operator: Equal + # value: master + # effect: NoSchedule tolerations: [] + # A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core). + # + # For example: + # topologySpreadConstraints: + # - maxSkew: 2 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: ScheduleAnyway + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: cert-manager + # app.kubernetes.io/component: controller topologySpreadConstraints: [] - # Optional additional labels to add to the Webhook Pods + # Optional additional labels to add to the Webhook Pods. podLabels: {} - # Optional additional labels to add to the Webhook Service + # Optional additional labels to add to the Webhook Service. serviceLabels: {} + # Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). + serviceIPFamilyPolicy: "" + # Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6. + serviceIPFamilies: [] image: - repository: quay.io/jetstack/cert-manager-webhook - # You can manage a registry with + # The container registry to pull the webhook image from. + # +docs:property # registry: quay.io - # repository: jetstack/cert-manager-webhook + # The container image for the cert-manager webhook + # +docs:property + repository: quay.io/jetstack/cert-manager-webhook # Override the image tag to deploy by setting this variable. # If no value is set, the chart's appVersion will be used. - # tag: canary + # +docs:property + # tag: vX.Y.Z # Setting a digest will override any tag + # +docs:property # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. pullPolicy: IfNotPresent - digest: sha256:db0bb8c02c0b82f3055315fbc52ad41b90fbe94f82431a0d76666f7c6beeb7f0 + digest: sha256:85df7b64a3d66de3cd7995ae0f2151b54fd18db424cb7cf84d3bd6d4a39d975f serviceAccount: - # Specifies whether a service account should be created + # Specifies whether a service account should be created. create: true # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template + # If not set and create is true, a name is generated using the fullname template. + # +docs:property # name: "" - # Optional additional annotations to add to the controller's ServiceAccount + + # Optional additional annotations to add to the controller's Service Account. + # +docs:property # annotations: {} - # Optional additional labels to add to the webhook's ServiceAccount + + # Optional additional labels to add to the webhook's Service Account. + # +docs:property # labels: {} + # Automount API credentials for a Service Account. automountServiceAccountToken: true - # Automounting API credentials for a particular pod + # Automounting API credentials for a particular pod. + # +docs:property # automountServiceAccountToken: true - # The port that the webhook should listen on for requests. - # In GKE private clusters, by default kubernetes apiservers are allowed to - # talk to the cluster nodes only on 443 and 10250. so configuring - # securePort: 10250, will work out of the box without needing to add firewall - # rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000 + # The port that the webhook listens on for requests. + # In GKE private clusters, by default Kubernetes apiservers are allowed to + # talk to the cluster nodes only on 443 and 10250. Configuring + # securePort: 10250, therefore will work out-of-the-box without needing to add firewall + # rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000. securePort: 10250 # Specifies if the webhook should be started in hostNetwork mode. # @@ -381,10 +771,12 @@ webhook: # running in hostNetwork mode. hostNetwork: false # Specifies how the service should be handled. Useful if you want to expose the - # webhook to outside of the cluster. In some cases, the control plane cannot + # webhook outside of the cluster. In some cases, the control plane cannot # reach internal services. serviceType: ClusterIP - # loadBalancerIP: + # Specify the load balancer IP for the created service. + # +docs:property + # loadBalancerIP: "10.10.10.10" # Overrides the mutating webhook and validating webhook so they reach the webhook # service using the `url` field instead of a service. @@ -393,11 +785,18 @@ webhook: # Enables default network policies for webhooks. networkPolicy: + # Create network policies for the webhooks. enabled: false + # Ingress rule for the webhook network policy. By default, it allows all + # inbound traffic. + # +docs:property ingress: - from: - ipBlock: cidr: 0.0.0.0/0 + # Egress rule for the webhook network policy. By default, it allows all + # outbound traffic to ports 80 and 443, as well as DNS ports. + # +docs:property egress: - ports: - port: 80 @@ -408,202 +807,393 @@ webhook: protocol: TCP - port: 53 protocol: UDP - # On OpenShift and OKD, the Kubernetes API server listens on + # On OpenShift and OKD, the Kubernetes API server listens on. # port 6443. - port: 6443 protocol: TCP to: - ipBlock: cidr: 0.0.0.0/0 + # Additional volumes to add to the cert-manager controller pod. volumes: [] + # Additional volume mounts to add to the cert-manager controller container. volumeMounts: [] + # enableServiceLinks indicates whether information about services should be + # injected into the pod's environment variables, matching the syntax of Docker + # links. + enableServiceLinks: false +# +docs:section=CA Injector cainjector: + # Create the CA Injector deployment enabled: true + # The number of replicas of the cert-manager cainjector to run. + # + # The default is 1, but in production set this to 2 or 3 to provide high + # availability. + # + # If `replicas > 1`, consider setting `cainjector.podDisruptionBudget.enabled=true`. + # + # Note that cert-manager uses leader election to ensure that there can + # only be a single instance active at a time. replicaCount: 1 + # This is used to configure options for the cainjector pod. + # It allows setting options that are usually provided via flags. + # An APIVersion and Kind must be specified in your values.yaml file. + # Flags override options that are set here. + # + # For example: + # apiVersion: cainjector.config.cert-manager.io/v1alpha1 + # kind: CAInjectorConfiguration + # logging: + # verbosity: 2 + # format: text + # leaderElectionConfig: + # namespace: kube-system + config: {} + # Deployment update strategy for the cert-manager cainjector deployment. + # For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). + # + # For example: + # strategy: + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 0 + # maxUnavailable: 1 strategy: {} - # type: RollingUpdate - # rollingUpdate: - # maxSurge: 0 - # maxUnavailable: 1 - # Pod Security Context to be set on the cainjector component Pod - # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault - podDisruptionBudget: - enabled: false - minAvailable: 1 - # maxUnavailable: 1 - # minAvailable and maxUnavailable can either be set to an integer (e.g. 1) - # or a percentage value (e.g. 25%) - # Container Security Context to be set on the cainjector component container - # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property containerSecurityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # Optional additional annotations to add to the cainjector Deployment + readOnlyRootFilesystem: true + podDisruptionBudget: + # Enable or disable the PodDisruptionBudget resource. + # + # This prevents downtime during voluntary disruptions such as during a Node upgrade. + # For example, the PodDisruptionBudget will block `kubectl drain` + # if it is used on the Node where the only remaining cert-manager + # Pod is currently running. + enabled: false + # `minAvailable` configures the minimum available pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # Cannot be used if `maxUnavailable` is set. + # +docs:property + # minAvailable: 1 + # `maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # Cannot be used if `minAvailable` is set. + # +docs:property + # maxUnavailable: 1 + + # Optional additional annotations to add to the cainjector Deployment. + # +docs:property # deploymentAnnotations: {} - # Optional additional annotations to add to the cainjector Pods + # Optional additional annotations to add to the cainjector Pods. + # +docs:property # podAnnotations: {} # Additional command line flags to pass to cert-manager cainjector binary. - # To see all available flags run docker run quay.io/jetstack/cert-manager-cainjector: --help + # To see all available flags run `docker run quay.io/jetstack/cert-manager-cainjector: --help`. extraArgs: [] - # Enable profiling for cainjector + # Enable profiling for cainjector. # - --enable-profiling=true + # Comma separated list of feature gates that should be enabled on the + # cainjector pod. + featureGates: "" + # Resources to provide to the cert-manager cainjector pod. + # + # For example: + # requests: + # cpu: 10m + # memory: 32Mi + # + # For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). resources: {} - # requests: - # cpu: 10m - # memory: 32Mi - + # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with + # matching labels. + # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + # + # This default ensures that Pods are only scheduled to Linux nodes. + # It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + # +docs:property nodeSelector: kubernetes.io/os: linux + # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + # + # For example: + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: foo.bar.com/role + # operator: In + # values: + # - master affinity: {} + # A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + # + # For example: + # tolerations: + # - key: foo.bar.com/role + # operator: Equal + # value: master + # effect: NoSchedule tolerations: [] + # A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core). + # + # For example: + # topologySpreadConstraints: + # - maxSkew: 2 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: ScheduleAnyway + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: cert-manager + # app.kubernetes.io/component: controller topologySpreadConstraints: [] - # Optional additional labels to add to the CA Injector Pods + # Optional additional labels to add to the CA Injector Pods. podLabels: {} image: - repository: quay.io/jetstack/cert-manager-cainjector - # You can manage a registry with + # The container registry to pull the cainjector image from. + # +docs:property # registry: quay.io - # repository: jetstack/cert-manager-cainjector + # The container image for the cert-manager cainjector + # +docs:property + repository: quay.io/jetstack/cert-manager-cainjector # Override the image tag to deploy by setting this variable. # If no value is set, the chart's appVersion will be used. - # tag: canary + # +docs:property + # tag: vX.Y.Z - # Setting a digest will override any tag + # Setting a digest will override any tag. + # +docs:property # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. pullPolicy: IfNotPresent - digest: sha256:2a70d9497a645101210d077874c35dc0431233d8c6e53a851835ca301523d64b + digest: sha256:edb1c1e0083ee4cd8e2ccb296ee0f436d2e465ecf90159f9d03141fc19bd3c23 serviceAccount: - # Specifies whether a service account should be created + # Specifies whether a service account should be created. create: true # The name of the service account to use. # If not set and create is true, a name is generated using the fullname template + # +docs:property # name: "" - # Optional additional annotations to add to the controller's ServiceAccount + + # Optional additional annotations to add to the controller's Service Account. + # +docs:property # annotations: {} - # Automount API credentials for a Service Account. - # Optional additional labels to add to the cainjector's ServiceAccount + + # Optional additional labels to add to the cainjector's Service Account. + # +docs:property # labels: {} + + # Automount API credentials for a Service Account. automountServiceAccountToken: true - # Automounting API credentials for a particular pod + # Automounting API credentials for a particular pod. + # +docs:property # automountServiceAccountToken: true + + # Additional volumes to add to the cert-manager controller pod. volumes: [] + # Additional volume mounts to add to the cert-manager controller container. volumeMounts: [] + # enableServiceLinks indicates whether information about services should be + # injected into the pod's environment variables, matching the syntax of Docker + # links. + enableServiceLinks: false +# +docs:section=ACME Solver acmesolver: image: - repository: quay.io/jetstack/cert-manager-acmesolver - # You can manage a registry with + # The container registry to pull the acmesolver image from. + # +docs:property # registry: quay.io - # repository: jetstack/cert-manager-acmesolver - digest: sha256:12a62e54ba8defda94df71ef76f9c8fe68405d59370f665991734d6b692e35f2 -# Override the image tag to deploy by setting this variable. -# If no value is set, the chart's appVersion will be used. -# tag: canary + # The container image for the cert-manager acmesolver. + # +docs:property + repository: quay.io/jetstack/cert-manager-acmesolver + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion is used. + # +docs:property + # tag: vX.Y.Z -# Setting a digest will override any tag -# digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + # Setting a digest will override any tag. + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + digest: sha256:99feb5d6cd8e8b4c6eb1ab14b317304141c25114b0bd3e5588b9f551f664cb8f +# +docs:section=Startup API Check # This startupapicheck is a Helm post-install hook that waits for the webhook # endpoints to become available. -# The check is implemented using a Kubernetes Job- if you are injecting mesh -# sidecar proxies into cert-manager pods, you probably want to ensure that they -# are not injected into this Job's pod. Otherwise the installation may time out -# due to the Job never being completed because the sidecar proxy does not exit. -# See https://github.com/cert-manager/cert-manager/pull/4414 for context. +# The check is implemented using a Kubernetes Job - if you are injecting mesh +# sidecar proxies into cert-manager pods, ensure that they +# are not injected into this Job's pod. Otherwise, the installation may time out +# owing to the Job never being completed because the sidecar proxy does not exit. +# For more information, see [this note](https://github.com/cert-manager/cert-manager/pull/4414). startupapicheck: + # Enables the startup api check. enabled: true - # Pod Security Context to be set on the startupapicheck component Pod - # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + # Pod Security Context to be set on the startupapicheck component Pod. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault - # Container Security Context to be set on the controller component container - # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + # Container Security Context to be set on the controller component container. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property containerSecurityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # Timeout for 'kubectl check api' command + readOnlyRootFilesystem: true + # Timeout for 'kubectl check api' command. timeout: 1m # Job backoffLimit backoffLimit: 4 - # Optional additional annotations to add to the startupapicheck Job + # Optional additional annotations to add to the startupapicheck Job. + # +docs:property jobAnnotations: helm.sh/hook: post-install helm.sh/hook-weight: "1" helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded - # Optional additional annotations to add to the startupapicheck Pods + # Optional additional annotations to add to the startupapicheck Pods. + # +docs:property # podAnnotations: {} # Additional command line flags to pass to startupapicheck binary. - # To see all available flags run docker run quay.io/jetstack/cert-manager-ctl: --help - extraArgs: [] + # To see all available flags run `docker run quay.io/jetstack/cert-manager-startupapicheck: --help`. + # + # Verbose logging is enabled by default so that if startupapicheck fails, you + # can know what exactly caused the failure. Verbose logs include details of + # the webhook URL, IP address and TCP connect errors for example. + # +docs:property + extraArgs: + - -v + # Resources to provide to the cert-manager controller pod. + # + # For example: + # requests: + # cpu: 10m + # memory: 32Mi + # + # For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). resources: {} - # requests: - # cpu: 10m - # memory: 32Mi - + # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with + # matching labels. + # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + # + # This default ensures that Pods are only scheduled to Linux nodes. + # It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + # +docs:property nodeSelector: kubernetes.io/os: linux + # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + # For example: + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: foo.bar.com/role + # operator: In + # values: + # - master affinity: {} + # A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + # + # For example: + # tolerations: + # - key: foo.bar.com/role + # operator: Equal + # value: master + # effect: NoSchedule tolerations: [] - # Optional additional labels to add to the startupapicheck Pods + # Optional additional labels to add to the startupapicheck Pods. podLabels: {} image: - repository: quay.io/jetstack/cert-manager-ctl - # You can manage a registry with + # The container registry to pull the startupapicheck image from. + # +docs:property # registry: quay.io - # repository: jetstack/cert-manager-ctl + # The container image for the cert-manager startupapicheck. + # +docs:property + repository: quay.io/jetstack/cert-manager-startupapicheck # Override the image tag to deploy by setting this variable. - # If no value is set, the chart's appVersion will be used. - # tag: canary + # If no value is set, the chart's appVersion is used. + # +docs:property + # tag: vX.Y.Z - # Setting a digest will override any tag + # Setting a digest will override any tag. + # +docs:property # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. pullPolicy: IfNotPresent - digest: sha256:1b988a4a2ae83aae995d396fa67fdb4c90bc55bc91ea74679f17c6c347541406 + digest: sha256:6365e940a5a913a3aeca0ea519102236d9bec5f0e8f0011fa3498c26d18348e5 rbac: - # annotations for the startup API Check job RBAC and PSP resources + # annotations for the startup API Check job RBAC and PSP resources. + # +docs:property annotations: helm.sh/hook: post-install helm.sh/hook-weight: "-5" helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded - # Automounting API credentials for a particular pod + # Automounting API credentials for a particular pod. + # +docs:property # automountServiceAccountToken: true serviceAccount: - # Specifies whether a service account should be created + # Specifies whether a service account should be created. create: true # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template + # If not set and create is true, a name is generated using the fullname template. + # +docs:property # name: "" - # Optional additional annotations to add to the Job's ServiceAccount + # Optional additional annotations to add to the Job's Service Account. + # +docs:property annotations: helm.sh/hook: post-install helm.sh/hook-weight: "-5" helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded # Automount API credentials for a Service Account. + # +docs:property automountServiceAccountToken: true - # Optional additional labels to add to the startupapicheck's ServiceAccount + # Optional additional labels to add to the startupapicheck's Service Account. + # +docs:property # labels: {} + # Additional volumes to add to the cert-manager controller pod. volumes: [] + # Additional volume mounts to add to the cert-manager controller container. volumeMounts: [] + # enableServiceLinks indicates whether information about services should be + # injected into pod's environment variables, matching the syntax of Docker + # links. + enableServiceLinks: false +# Create dynamic manifests via values. +# +# For example: +# extraObjects: +# - | +# apiVersion: v1 +# kind: ConfigMap +# metadata: +# name: '{{ template "cert-manager.name" . }}-extra-configmap' +extraObjects: [] diff --git a/internal/constellation/helm/charts/cilium/Chart.yaml b/internal/constellation/helm/charts/cilium/Chart.yaml index 3ba2d273f..0aa3edc19 100644 --- a/internal/constellation/helm/charts/cilium/Chart.yaml +++ b/internal/constellation/helm/charts/cilium/Chart.yaml @@ -2,10 +2,10 @@ apiVersion: v2 name: cilium displayName: Cilium home: https://cilium.io/ -version: 1.15.0-pre.3-edg.3 -appVersion: 1.15.0-pre.3-edg.3 +version: 1.15.8-edg.0 +appVersion: 1.15.8-edg.0 kubeVersion: ">= 1.16.0-0" -icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg +icon: https://cdn.jsdelivr.net/gh/cilium/cilium@v1.15/Documentation/images/logo-solo.svg description: eBPF-based Networking, Security, and Observability keywords: - BPF diff --git a/internal/constellation/helm/charts/cilium/README.md b/internal/constellation/helm/charts/cilium/README.md index bdbca6edc..78fcdf684 100644 --- a/internal/constellation/helm/charts/cilium/README.md +++ b/internal/constellation/helm/charts/cilium/README.md @@ -1,6 +1,6 @@ # cilium -![Version: 1.15.0-pre.3](https://img.shields.io/badge/Version-1.15.0--pre.3-informational?style=flat-square) ![AppVersion: 1.15.0-pre.3](https://img.shields.io/badge/AppVersion-1.15.0--pre.3-informational?style=flat-square) +![Version: 1.15.8](https://img.shields.io/badge/Version-1.15.8-informational?style=flat-square) ![AppVersion: 1.15.8](https://img.shields.io/badge/AppVersion-1.15.8-informational?style=flat-square) Cilium is open source software for providing and transparently securing network connectivity and loadbalancing between application workloads such as @@ -46,7 +46,7 @@ offer from the [Getting Started Guides page](https://docs.cilium.io/en/stable/ge ## Getting Help The best way to get help if you get stuck is to ask a question on the -[Cilium Slack channel](https://cilium.herokuapp.com/). With Cilium +[Cilium Slack channel](https://slack.cilium.io). With Cilium contributors across the globe, there is almost always someone available to help. ## Values @@ -73,16 +73,17 @@ contributors across the globe, there is almost always someone available to help. | authentication.mutual.spire.enabled | bool | `false` | Enable SPIRE integration (beta) | | authentication.mutual.spire.install.agent.affinity | object | `{}` | SPIRE agent affinity configuration | | authentication.mutual.spire.install.agent.annotations | object | `{}` | SPIRE agent annotations | -| authentication.mutual.spire.install.agent.image | object | `{"digest":"sha256:d489bc8470d7a0f292e0e3576c3e7025253343dc798241bcfd9061828e2a6bef","override":null,"pullPolicy":"IfNotPresent","repository":"ghcr.io/spiffe/spire-agent","tag":"1.8.4","useDigest":true}` | SPIRE agent image | +| authentication.mutual.spire.install.agent.image | object | `{"digest":"sha256:99405637647968245ff9fe215f8bd2bd0ea9807be9725f8bf19fe1b21471e52b","override":null,"pullPolicy":"IfNotPresent","repository":"ghcr.io/spiffe/spire-agent","tag":"1.8.5","useDigest":true}` | SPIRE agent image | | authentication.mutual.spire.install.agent.labels | object | `{}` | SPIRE agent labels | | authentication.mutual.spire.install.agent.nodeSelector | object | `{}` | SPIRE agent nodeSelector configuration ref: ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | authentication.mutual.spire.install.agent.podSecurityContext | object | `{}` | Security context to be added to spire agent pods. SecurityContext holds pod-level security attributes and common container settings. ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod | | authentication.mutual.spire.install.agent.securityContext | object | `{}` | Security context to be added to spire agent containers. SecurityContext holds pod-level security attributes and common container settings. ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container | | authentication.mutual.spire.install.agent.serviceAccount | object | `{"create":true,"name":"spire-agent"}` | SPIRE agent service account | | authentication.mutual.spire.install.agent.skipKubeletVerification | bool | `true` | SPIRE Workload Attestor kubelet verification. | -| authentication.mutual.spire.install.agent.tolerations | list | `[]` | SPIRE agent tolerations configuration ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| authentication.mutual.spire.install.agent.tolerations | list | `[{"effect":"NoSchedule","key":"node.kubernetes.io/not-ready"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane"},{"effect":"NoSchedule","key":"node.cloudprovider.kubernetes.io/uninitialized","value":"true"},{"key":"CriticalAddonsOnly","operator":"Exists"}]` | SPIRE agent tolerations configuration By default it follows the same tolerations as the agent itself to allow the Cilium agent on this node to connect to SPIRE. ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | | authentication.mutual.spire.install.enabled | bool | `true` | Enable SPIRE installation. This will only take effect only if authentication.mutual.spire.enabled is true | -| authentication.mutual.spire.install.initImage | object | `{"digest":"sha256:223ae047b1065bd069aac01ae3ac8088b3ca4a527827e283b85112f29385fb1b","override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/library/busybox","tag":"1.36.1","useDigest":true}` | init container image of SPIRE agent and server | +| authentication.mutual.spire.install.existingNamespace | bool | `false` | SPIRE namespace already exists. Set to true if Helm should not create, manage, and import the SPIRE namespace. | +| authentication.mutual.spire.install.initImage | object | `{"digest":"sha256:9ae97d36d26566ff84e8893c64a6dc4fe8ca6d1144bf5b87b2b85a32def253c7","override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/library/busybox","tag":"1.36.1","useDigest":true}` | init container image of SPIRE agent and server | | authentication.mutual.spire.install.namespace | string | `"cilium-spire"` | SPIRE namespace to install into | | authentication.mutual.spire.install.server.affinity | object | `{}` | SPIRE server affinity configuration | | authentication.mutual.spire.install.server.annotations | object | `{}` | SPIRE server annotations | @@ -92,7 +93,7 @@ contributors across the globe, there is almost always someone available to help. | authentication.mutual.spire.install.server.dataStorage.enabled | bool | `true` | Enable SPIRE server data storage | | authentication.mutual.spire.install.server.dataStorage.size | string | `"1Gi"` | Size of the SPIRE server data storage | | authentication.mutual.spire.install.server.dataStorage.storageClass | string | `nil` | StorageClass of the SPIRE server data storage | -| authentication.mutual.spire.install.server.image | object | `{"digest":"sha256:bf79e0a921f8b8aa92602f7ea335616e72f7e91f939848e7ccc52d5bddfe96a1","override":null,"pullPolicy":"IfNotPresent","repository":"ghcr.io/spiffe/spire-server","tag":"1.8.4","useDigest":true}` | SPIRE server image | +| authentication.mutual.spire.install.server.image | object | `{"digest":"sha256:28269265882048dcf0fed32fe47663cd98613727210b8d1a55618826f9bf5428","override":null,"pullPolicy":"IfNotPresent","repository":"ghcr.io/spiffe/spire-server","tag":"1.8.5","useDigest":true}` | SPIRE server image | | authentication.mutual.spire.install.server.initContainers | list | `[]` | SPIRE server init containers | | authentication.mutual.spire.install.server.labels | object | `{}` | SPIRE server labels | | authentication.mutual.spire.install.server.nodeSelector | object | `{}` | SPIRE server nodeSelector configuration ref: ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | @@ -135,13 +136,14 @@ contributors across the globe, there is almost always someone available to help. | bpf.monitorInterval | string | `"5s"` | Configure the typical time between monitor notifications for active connections. | | bpf.natMax | int | `524288` | Configure the maximum number of entries for the NAT table. | | bpf.neighMax | int | `524288` | Configure the maximum number of entries for the neighbor table. | -| bpf.policyMapMax | int | `16384` | Configure the maximum number of entries in endpoint policy map (per endpoint). | +| bpf.nodeMapMax | int | `nil` | Configures the maximum number of entries for the node table. | +| bpf.policyMapMax | int | `16384` | Configure the maximum number of entries in endpoint policy map (per endpoint). @schema type: [null, integer] @schema | | bpf.preallocateMaps | bool | `false` | Enables pre-allocation of eBPF map values. This increases memory usage but can reduce latency. | | bpf.root | string | `"/sys/fs/bpf"` | Configure the mount point for the BPF filesystem | | bpf.tproxy | bool | `false` | Configure the eBPF-based TPROXY to reduce reliance on iptables rules for implementing Layer 7 policy. | | bpf.vlanBypass | list | `[]` | Configure explicitly allowed VLAN id's for bpf logic bypass. [0] will allow all VLAN id's without any filtering. | | bpfClockProbe | bool | `false` | Enable BPF clock source probing for more efficient tick retrieval. | -| certgen | object | `{"affinity":{},"annotations":{"cronJob":{},"job":{}},"extraVolumeMounts":[],"extraVolumes":[],"image":{"digest":"sha256:89a0847753686444daabde9474b48340993bd19c7bea66a46e45b2974b82041f","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/certgen","tag":"v0.1.9","useDigest":true},"podLabels":{},"tolerations":[],"ttlSecondsAfterFinished":1800}` | Configure certificate generation for Hubble integration. If hubble.tls.auto.method=cronJob, these values are used for the Kubernetes CronJob which will be scheduled regularly to (re)generate any certificates not provided manually. | +| certgen | object | `{"affinity":{},"annotations":{"cronJob":{},"job":{}},"extraVolumeMounts":[],"extraVolumes":[],"image":{"digest":"sha256:40cdac65aa6ee86c16ce107f8726c4b55ce6654d07bbdf490db6bd492587bf54","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/certgen","tag":"v0.1.14","useDigest":true},"podLabels":{},"tolerations":[],"ttlSecondsAfterFinished":1800}` | Configure certificate generation for Hubble integration. If hubble.tls.auto.method=cronJob, these values are used for the Kubernetes CronJob which will be scheduled regularly to (re)generate any certificates not provided manually. | | certgen.affinity | object | `{}` | Affinity for certgen | | certgen.annotations | object | `{"cronJob":{},"job":{}}` | Annotations to be added to the hubble-certgen initial Job and CronJob | | certgen.extraVolumeMounts | list | `[]` | Additional certgen volumeMounts. | @@ -169,7 +171,7 @@ contributors across the globe, there is almost always someone available to help. | clustermesh.apiserver.extraEnv | list | `[]` | Additional clustermesh-apiserver environment variables. | | clustermesh.apiserver.extraVolumeMounts | list | `[]` | Additional clustermesh-apiserver volumeMounts. | | clustermesh.apiserver.extraVolumes | list | `[]` | Additional clustermesh-apiserver volumes. | -| clustermesh.apiserver.image | object | `{"digest":"","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/clustermesh-apiserver","tag":"v1.15.0-pre.3","useDigest":false}` | Clustermesh API server image. | +| clustermesh.apiserver.image | object | `{"digest":"","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/clustermesh-apiserver","tag":"v1.15.8","useDigest":false}` | Clustermesh API server image. | | clustermesh.apiserver.kvstoremesh.enabled | bool | `false` | Enable KVStoreMesh. KVStoreMesh caches the information retrieved from the remote clusters in the local etcd instance. | | clustermesh.apiserver.kvstoremesh.extraArgs | list | `[]` | Additional KVStoreMesh arguments. | | clustermesh.apiserver.kvstoremesh.extraEnv | list | `[]` | Additional KVStoreMesh environment variables. | @@ -211,6 +213,8 @@ contributors across the globe, there is almost always someone available to help. | clustermesh.apiserver.service.annotations | object | `{}` | Annotations for the clustermesh-apiserver For GKE LoadBalancer, use annotation cloud.google.com/load-balancer-type: "Internal" For EKS LoadBalancer, use annotation service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0 | | clustermesh.apiserver.service.externalTrafficPolicy | string | `nil` | The externalTrafficPolicy of service used for apiserver access. | | clustermesh.apiserver.service.internalTrafficPolicy | string | `nil` | The internalTrafficPolicy of service used for apiserver access. | +| clustermesh.apiserver.service.loadBalancerClass | string | `nil` | Configure a loadBalancerClass. Allows to configure the loadBalancerClass on the clustermesh-apiserver LB service in case the Service type is set to LoadBalancer (requires Kubernetes 1.24+). | +| clustermesh.apiserver.service.loadBalancerIP | string | `nil` | Configure a specific loadBalancerIP. Allows to configure a specific loadBalancerIP on the clustermesh-apiserver LB service in case the Service type is set to LoadBalancer. | | clustermesh.apiserver.service.nodePort | int | `32379` | Optional port to use as the node port for apiserver access. WARNING: make sure to configure a different NodePort in each cluster if kube-proxy replacement is enabled, as Cilium is currently affected by a known bug (#24692) when NodePorts are handled by the KPR implementation. If a service with the same NodePort exists both in the local and the remote cluster, all traffic originating from inside the cluster and targeting the corresponding NodePort will be redirected to a local backend, regardless of whether the destination node belongs to the local or the remote cluster. | | clustermesh.apiserver.service.type | string | `"NodePort"` | The type of service used for apiserver access. | | clustermesh.apiserver.terminationGracePeriodSeconds | int | `30` | terminationGracePeriodSeconds for the clustermesh-apiserver deployment | @@ -272,6 +276,7 @@ contributors across the globe, there is almost always someone available to help. | dnsProxy.preCache | string | `""` | DNS cache data at this path is preloaded on agent startup. | | dnsProxy.proxyPort | int | `0` | Global port on which the in-agent DNS proxy should listen. Default 0 is a OS-assigned port. | | dnsProxy.proxyResponseMaxDelay | string | `"100ms"` | The maximum time the DNS proxy holds an allowed DNS response before sending it along. Responses are sent as soon as the datapath is updated with the new IP information. | +| dnsProxy.socketLingerTimeout | int | `10` | Timeout (in seconds) when closing the connection between the DNS proxy and the upstream server. If set to 0, the connection is closed immediately (with TCP RST). If set to -1, the connection is closed asynchronously in the background. | | egressGateway.enabled | bool | `false` | Enables egress gateway to redirect and SNAT the traffic that leaves the cluster. | | egressGateway.installRoutes | bool | `false` | Deprecated without a replacement necessary. | | egressGateway.reconciliationTriggerInterval | string | `"1s"` | Time between triggers of egress gateway state reconciliations | @@ -297,10 +302,11 @@ contributors across the globe, there is almost always someone available to help. | encryption.mountPath | string | `"/etc/ipsec"` | Deprecated in favor of encryption.ipsec.mountPath. To be removed in 1.15. Path to mount the secret inside the Cilium pod. This option is only effective when encryption.type is set to ipsec. | | encryption.nodeEncryption | bool | `false` | Enable encryption for pure node to node traffic. This option is only effective when encryption.type is set to "wireguard". | | encryption.secretName | string | `"cilium-ipsec-keys"` | Deprecated in favor of encryption.ipsec.secretName. To be removed in 1.15. Name of the Kubernetes secret containing the encryption keys. This option is only effective when encryption.type is set to ipsec. | -| encryption.strictMode | object | `{"allowRemoteNodeIdentities":false,"cidr":"","enabled":false}` | Configure the WireGuard Pod2Pod strict mode. | -| encryption.strictMode.allowRemoteNodeIdentities | bool | `false` | Allow dynamic lookup of remote node identities. This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. | -| encryption.strictMode.cidr | string | `""` | CIDR for the WireGuard Pod2Pod strict mode. | -| encryption.strictMode.enabled | bool | `false` | Enable WireGuard Pod2Pod strict mode. | +| encryption.strictMode | object | `{"allowRemoteNodeIdentities":true,"enabled":false,"nodeCIDRList":[],"podCIDRList":[]}` | Configure the WireGuard strict mode. | +| encryption.strictMode.allowRemoteNodeIdentities | bool | `true` | Allow dynamic lookup of remote node identities. This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. This is also required when control-plane nodes are exempted from node-to-node encryption. | +| encryption.strictMode.enabled | bool | `false` | Enable WireGuard strict mode. | +| encryption.strictMode.nodeCIDRList | list | `[]` | nodeCIDRList for the WireGuard strict mode. | +| encryption.strictMode.podCIDRList | list | `[]` | podCIDRList for the WireGuard strict mode. | | encryption.type | string | `"ipsec"` | Encryption method. Can be either ipsec or wireguard. | | encryption.wireguard.persistentKeepalive | string | `"0s"` | Controls Wireguard PersistentKeepalive option. Set 0s to disable. | | encryption.wireguard.userspaceFallback | bool | `false` | Enables the fallback to the user-space implementation. | @@ -319,7 +325,7 @@ contributors across the globe, there is almost always someone available to help. | eni.subnetIDsFilter | list | `[]` | Filter via subnet IDs which will dictate which subnets are going to be used to create new ENIs Important note: This requires that each instance has an ENI with a matching subnet attached when Cilium is deployed. If you only want to control subnets for ENIs attached by Cilium, use the CNI configuration file settings (cni.customConf) instead. | | eni.subnetTagsFilter | list | `[]` | Filter via tags (k=v) which will dictate which subnets are going to be used to create new ENIs Important note: This requires that each instance has an ENI with a matching subnet attached when Cilium is deployed. If you only want to control subnets for ENIs attached by Cilium, use the CNI configuration file settings (cni.customConf) instead. | | eni.updateEC2AdapterLimitViaAPI | bool | `true` | Update ENI Adapter limits from the EC2 API | -| envoy.affinity | object | `{"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium-envoy"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-envoy. | +| envoy.affinity | object | `{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"cilium.io/no-schedule","operator":"NotIn","values":["true"]}]}]}},"podAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium"}},"topologyKey":"kubernetes.io/hostname"}]},"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium-envoy"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-envoy. | | envoy.annotations | object | `{}` | Annotations to be added to all top-level cilium-envoy objects (resources under templates/cilium-envoy) | | envoy.connectTimeoutSeconds | int | `2` | Time in seconds after which a TCP connection attempt times out | | envoy.dnsPolicy | string | `nil` | DNS policy for Cilium envoy pods. Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy | @@ -332,7 +338,7 @@ contributors across the globe, there is almost always someone available to help. | envoy.extraVolumes | list | `[]` | Additional envoy volumes. | | envoy.healthPort | int | `9878` | TCP port for the health API. | | envoy.idleTimeoutDurationSeconds | int | `60` | Set Envoy upstream HTTP idle connection timeout seconds. Does not apply to connections with pending requests. Default 60s | -| envoy.image | object | `{"digest":"sha256:80de27c1d16ab92923cc0cd1fff90f2e7047a9abf3906fda712268d9cbc5b950","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.27.2-f19708f3d0188fe39b7e024b4525b75a9eeee61f","useDigest":true}` | Envoy container image. | +| envoy.image | object | `{"digest":"sha256:bd5ff8c66716080028f414ec1cb4f7dc66f40d2fb5a009fff187f4a9b90b566b","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.29.7-39a2a56bbd5b3a591f69dbca51d3e30ef97e0e51","useDigest":true}` | Envoy container image. | | envoy.livenessProbe.failureThreshold | int | `10` | failure threshold of liveness probe | | envoy.livenessProbe.periodSeconds | int | `30` | interval between checks of the liveness probe | | envoy.log.format | string | `"[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v"` | The format string to use for laying out the log message metadata of Envoy. | @@ -342,16 +348,18 @@ contributors across the globe, there is almost always someone available to help. | envoy.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node selector for cilium-envoy. | | envoy.podAnnotations | object | `{}` | Annotations to be added to envoy pods | | envoy.podLabels | object | `{}` | Labels to be added to envoy pods | -| envoy.podSecurityContext | object | `{}` | Security Context for cilium-envoy pods. | +| envoy.podSecurityContext | object | `{"appArmorProfile":{"type":"Unconfined"}}` | Security Context for cilium-envoy pods. | +| envoy.podSecurityContext.appArmorProfile | object | `{"type":"Unconfined"}` | AppArmorProfile options for the `cilium-agent` and init containers | | envoy.priorityClassName | string | `nil` | The priority class to use for cilium-envoy. | +| envoy.prometheus | object | `{"enabled":true,"port":"9964","serviceMonitor":{"annotations":{},"enabled":false,"interval":"10s","labels":{},"metricRelabelings":null,"relabelings":[{"replacement":"${1}","sourceLabels":["__meta_kubernetes_pod_node_name"],"targetLabel":"node"}]}}` | Configure Cilium Envoy Prometheus options. Note that some of these apply to either cilium-agent or cilium-envoy. | | envoy.prometheus.enabled | bool | `true` | Enable prometheus metrics for cilium-envoy | | envoy.prometheus.port | string | `"9964"` | Serve prometheus metrics for cilium-envoy on the configured port | | envoy.prometheus.serviceMonitor.annotations | object | `{}` | Annotations to add to ServiceMonitor cilium-envoy | -| envoy.prometheus.serviceMonitor.enabled | bool | `false` | Enable service monitors. This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) | +| envoy.prometheus.serviceMonitor.enabled | bool | `false` | Enable service monitors. This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) Note that this setting applies to both cilium-envoy _and_ cilium-agent with Envoy enabled. | | envoy.prometheus.serviceMonitor.interval | string | `"10s"` | Interval for scrape metrics. | | envoy.prometheus.serviceMonitor.labels | object | `{}` | Labels to add to ServiceMonitor cilium-envoy | -| envoy.prometheus.serviceMonitor.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor cilium-envoy | -| envoy.prometheus.serviceMonitor.relabelings | list | `[{"replacement":"${1}","sourceLabels":["__meta_kubernetes_pod_node_name"],"targetLabel":"node"}]` | Relabeling configs for the ServiceMonitor cilium-envoy | +| envoy.prometheus.serviceMonitor.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor cilium-envoy or for cilium-agent with Envoy configured. | +| envoy.prometheus.serviceMonitor.relabelings | list | `[{"replacement":"${1}","sourceLabels":["__meta_kubernetes_pod_node_name"],"targetLabel":"node"}]` | Relabeling configs for the ServiceMonitor cilium-envoy or for cilium-agent with Envoy configured. | | envoy.readinessProbe.failureThreshold | int | `3` | failure threshold of readiness probe | | envoy.readinessProbe.periodSeconds | int | `30` | interval between checks of the readiness probe | | envoy.resources | object | `{}` | Envoy resource limits & requests ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | @@ -364,6 +372,8 @@ contributors across the globe, there is almost always someone available to help. | envoy.terminationGracePeriodSeconds | int | `1` | Configure termination grace period for cilium-envoy DaemonSet. | | envoy.tolerations | list | `[{"operator":"Exists"}]` | Node tolerations for envoy scheduling to nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | | envoy.updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":2},"type":"RollingUpdate"}` | cilium-envoy update strategy ref: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#updating-a-daemonset | +| envoy.xffNumTrustedHopsL7PolicyEgress | int | `0` | Number of trusted hops regarding the x-forwarded-for and related HTTP headers for the egress L7 policy enforcement Envoy listeners. | +| envoy.xffNumTrustedHopsL7PolicyIngress | int | `0` | Number of trusted hops regarding the x-forwarded-for and related HTTP headers for the ingress L7 policy enforcement Envoy listeners. | | envoyConfig.enabled | bool | `false` | Enable CiliumEnvoyConfig CRD CiliumEnvoyConfig CRD can also be implicitly enabled by other options. | | envoyConfig.secretsNamespace | object | `{"create":true,"name":"cilium-secrets"}` | SecretsNamespace is the namespace in which envoy SDS will retrieve secrets from. | | envoyConfig.secretsNamespace.create | bool | `true` | Create secrets namespace for CiliumEnvoyConfig CRDs. | @@ -452,9 +462,11 @@ contributors across the globe, there is almost always someone available to help. | hubble.relay.dialTimeout | string | `nil` | Dial timeout to connect to the local hubble instance to receive peer information (e.g. "30s"). | | hubble.relay.enabled | bool | `false` | Enable Hubble Relay (requires hubble.enabled=true) | | hubble.relay.extraEnv | list | `[]` | Additional hubble-relay environment variables. | +| hubble.relay.extraVolumeMounts | list | `[]` | Additional hubble-relay volumeMounts. | +| hubble.relay.extraVolumes | list | `[]` | Additional hubble-relay volumes. | | hubble.relay.gops.enabled | bool | `true` | Enable gops for hubble-relay | | hubble.relay.gops.port | int | `9893` | Configure gops listen port for hubble-relay | -| hubble.relay.image | object | `{"digest":"","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-relay","tag":"v1.15.0-pre.3","useDigest":false}` | Hubble-relay container image. | +| hubble.relay.image | object | `{"digest":"","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-relay","tag":"v1.15.8","useDigest":false}` | Hubble-relay container image. | | hubble.relay.listenHost | string | `""` | Host to listen to. Specify an empty string to bind to all the interfaces. | | hubble.relay.listenPort | string | `"4245"` | Port to listen to. | | hubble.relay.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | @@ -512,7 +524,7 @@ contributors across the globe, there is almost always someone available to help. | hubble.ui.backend.extraEnv | list | `[]` | Additional hubble-ui backend environment variables. | | hubble.ui.backend.extraVolumeMounts | list | `[]` | Additional hubble-ui backend volumeMounts. | | hubble.ui.backend.extraVolumes | list | `[]` | Additional hubble-ui backend volumes. | -| hubble.ui.backend.image | object | `{"digest":"sha256:1f86f3400827a0451e6332262467f894eeb7caf0eb8779bd951e2caa9d027cbe","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-ui-backend","tag":"v0.12.1","useDigest":true}` | Hubble-ui backend image. | +| hubble.ui.backend.image | object | `{"digest":"sha256:0e0eed917653441fded4e7cdb096b7be6a3bddded5a2dd10812a27b1fc6ed95b","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-ui-backend","tag":"v0.13.1","useDigest":true}` | Hubble-ui backend image. | | hubble.ui.backend.livenessProbe.enabled | bool | `false` | Enable liveness probe for Hubble-ui backend (requires Hubble-ui 0.12+) | | hubble.ui.backend.readinessProbe.enabled | bool | `false` | Enable readiness probe for Hubble-ui backend (requires Hubble-ui 0.12+) | | hubble.ui.backend.resources | object | `{}` | Resource requests and limits for the 'backend' container of the 'hubble-ui' deployment. | @@ -522,7 +534,7 @@ contributors across the globe, there is almost always someone available to help. | hubble.ui.frontend.extraEnv | list | `[]` | Additional hubble-ui frontend environment variables. | | hubble.ui.frontend.extraVolumeMounts | list | `[]` | Additional hubble-ui frontend volumeMounts. | | hubble.ui.frontend.extraVolumes | list | `[]` | Additional hubble-ui frontend volumes. | -| hubble.ui.frontend.image | object | `{"digest":"sha256:9e5f81ee747866480ea1ac4630eb6975ff9227f9782b7c93919c081c33f38267","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-ui","tag":"v0.12.1","useDigest":true}` | Hubble-ui frontend image. | +| hubble.ui.frontend.image | object | `{"digest":"sha256:e2e9313eb7caf64b0061d9da0efbdad59c6c461f6ca1752768942bfeda0796c6","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-ui","tag":"v0.13.1","useDigest":true}` | Hubble-ui frontend image. | | hubble.ui.frontend.resources | object | `{}` | Resource requests and limits for the 'frontend' container of the 'hubble-ui' deployment. | | hubble.ui.frontend.securityContext | object | `{}` | Hubble-ui frontend security context. | | hubble.ui.frontend.server.ipv6 | object | `{"enabled":true}` | Controls server listener for ipv6 | @@ -549,7 +561,7 @@ contributors across the globe, there is almost always someone available to help. | hubble.ui.updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | hubble-ui update strategy. | | identityAllocationMode | string | `"crd"` | Method to use for identity allocation (`crd` or `kvstore`). | | identityChangeGracePeriod | string | `"5s"` | Time to wait before using new identity on endpoint identity change. | -| image | object | `{"digest":"","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.15.0-pre.3","useDigest":false}` | Agent container image. | +| image | object | `{"digest":"","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.15.8","useDigest":false}` | Agent container image. | | imagePullSecrets | string | `nil` | Configure image pull secrets for pulling container images | | ingressController.default | bool | `false` | Set cilium ingress controller to be the default ingress controller This will let cilium ingress controller route entries without ingress class set | | ingressController.defaultSecretName | string | `nil` | Default secret name for ingresses without .spec.tls[].secretName set. | @@ -573,6 +585,7 @@ contributors across the globe, there is almost always someone available to help. | ingressController.service.name | string | `"cilium-ingress"` | Service name | | ingressController.service.secureNodePort | string | `nil` | Configure a specific nodePort for secure HTTPS traffic on the shared LB service | | ingressController.service.type | string | `"LoadBalancer"` | Service type for the shared LB service | +| initResources | object | `{}` | resources & limits for the agent init containers | | installNoConntrackIptablesRules | bool | `false` | Install Iptables rules to skip netfilter connection tracking on all pod traffic. This option is only effective when Cilium is running in direct routing and full KPR mode. Moreover, this option cannot be enabled when Cilium is running in a managed Kubernetes environment or in a chained CNI setup. | | ipMasqAgent | object | `{"enabled":false}` | Configure the eBPF-based ip-masq-agent | | ipam.ciliumNodeUpdateRate | string | `"15s"` | Maximum rate at which the CiliumNode custom resource is updated. | @@ -637,10 +650,12 @@ contributors across the globe, there is almost always someone available to help. | nodeinit.extraEnv | list | `[]` | Additional nodeinit environment variables. | | nodeinit.extraVolumeMounts | list | `[]` | Additional nodeinit volumeMounts. | | nodeinit.extraVolumes | list | `[]` | Additional nodeinit volumes. | -| nodeinit.image | object | `{"override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/startup-script","tag":"62093c5c233ea914bfa26a10ba41f8780d9b737f"}` | node-init image. | +| nodeinit.image | object | `{"digest":"sha256:8d7b41c4ca45860254b3c19e20210462ef89479bb6331d6760c4e609d651b29c","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/startup-script","tag":"c54c7edeab7fde4da68e59acd319ab24af242c3f","useDigest":true}` | node-init image. | | nodeinit.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for nodeinit pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | nodeinit.podAnnotations | object | `{}` | Annotations to be added to node-init pods. | | nodeinit.podLabels | object | `{}` | Labels to be added to node-init pods. | +| nodeinit.podSecurityContext | object | `{"appArmorProfile":{"type":"Unconfined"}}` | Security Context for cilium-node-init pods. | +| nodeinit.podSecurityContext.appArmorProfile | object | `{"type":"Unconfined"}` | AppArmorProfile options for the `cilium-node-init` and init containers | | nodeinit.prestop | object | `{"postScript":"","preScript":""}` | prestop offers way to customize prestop nodeinit script (pre and post position) | | nodeinit.priorityClassName | string | `""` | The priority class to use for the nodeinit pod. | | nodeinit.resources | object | `{"requests":{"cpu":"100m","memory":"100Mi"}}` | nodeinit resource limits & requests ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | @@ -661,7 +676,7 @@ contributors across the globe, there is almost always someone available to help. | operator.extraVolumes | list | `[]` | Additional cilium-operator volumes. | | operator.identityGCInterval | string | `"15m0s"` | Interval for identity garbage collection. | | operator.identityHeartbeatTimeout | string | `"30m0s"` | Timeout for identity heartbeats. | -| operator.image | object | `{"alibabacloudDigest":"","awsDigest":"","azureDigest":"","genericDigest":"","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/operator","suffix":"","tag":"v1.15.0-pre.3","useDigest":false}` | cilium-operator image. | +| operator.image | object | `{"alibabacloudDigest":"","awsDigest":"","azureDigest":"","genericDigest":"","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/operator","suffix":"","tag":"v1.15.8","useDigest":false}` | cilium-operator image. | | operator.nodeGCInterval | string | `"5m0s"` | Interval for cilium node garbage collection. | | operator.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for cilium-operator pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | operator.podAnnotations | object | `{}` | Annotations to be added to cilium-operator pods | @@ -699,7 +714,8 @@ contributors across the globe, there is almost always someone available to help. | pmtuDiscovery.enabled | bool | `false` | Enable path MTU discovery to send ICMP fragmentation-needed replies to the client. | | podAnnotations | object | `{}` | Annotations to be added to agent pods | | podLabels | object | `{}` | Labels to be added to agent pods | -| podSecurityContext | object | `{}` | Security Context for cilium-agent pods. | +| podSecurityContext | object | `{"appArmorProfile":{"type":"Unconfined"}}` | Security Context for cilium-agent pods. | +| podSecurityContext.appArmorProfile | object | `{"type":"Unconfined"}` | AppArmorProfile options for the `cilium-agent` and init containers | | policyCIDRMatchMode | string | `nil` | policyCIDRMatchMode is a list of entities that may be selected by CIDR selector. The possible value is "nodes". | | policyEnforcementMode | string | `"default"` | The agent can be put into one of the three policy enforcement modes: default, always and never. ref: https://docs.cilium.io/en/stable/security/policy/intro/#policy-enforcement-modes | | pprof.address | string | `"localhost"` | Configure pprof listen address for cilium-agent | @@ -711,7 +727,7 @@ contributors across the globe, there is almost always someone available to help. | preflight.extraEnv | list | `[]` | Additional preflight environment variables. | | preflight.extraVolumeMounts | list | `[]` | Additional preflight volumeMounts. | | preflight.extraVolumes | list | `[]` | Additional preflight volumes. | -| preflight.image | object | `{"digest":"","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.15.0-pre.3","useDigest":false}` | Cilium pre-flight image. | +| preflight.image | object | `{"digest":"","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.15.8","useDigest":false}` | Cilium pre-flight image. | | preflight.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for preflight pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | preflight.podAnnotations | object | `{}` | Annotations to be added to preflight pods | | preflight.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | @@ -746,7 +762,7 @@ contributors across the globe, there is almost always someone available to help. | rbac.create | bool | `true` | Enable creation of Resource-Based Access Control configuration. | | readinessProbe.failureThreshold | int | `3` | failure threshold of readiness probe | | readinessProbe.periodSeconds | int | `30` | interval between checks of the readiness probe | -| remoteNodeIdentity | bool | `true` | Enable use of the remote node identity. ref: https://docs.cilium.io/en/v1.7/install/upgrade/#configmap-remote-node-identity | +| remoteNodeIdentity | bool | `true` | Enable use of the remote node identity. ref: https://docs.cilium.io/en/v1.7/install/upgrade/#configmap-remote-node-identity Deprecated without replacement in 1.15. To be removed in 1.16. | | resourceQuotas | object | `{"cilium":{"hard":{"pods":"10k"}},"enabled":false,"operator":{"hard":{"pods":"15"}}}` | Enable resource quotas for priority classes used in the cluster. | | resources | object | `{}` | Agent resource limits & requests ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | | rollOutCiliumPods | bool | `false` | Roll out cilium agent pods automatically when configmap is updated. | @@ -771,6 +787,8 @@ contributors across the globe, there is almost always someone available to help. | startupProbe.periodSeconds | int | `2` | interval between checks of the startup probe | | svcSourceRangeCheck | bool | `true` | Enable check of service source ranges (currently, only for LoadBalancer). | | synchronizeK8sNodes | bool | `true` | Synchronize Kubernetes nodes to kvstore and perform CNP GC. | +| sysctlfix | object | `{"enabled":true}` | Configure sysctl override described in #20072. | +| sysctlfix.enabled | bool | `true` | Enable the sysctl override. When enabled, the init container will mount the /proc of the host so that the `sysctlfix` utility can execute. | | terminationGracePeriodSeconds | int | `1` | Configure termination grace period for cilium-agent DaemonSet. | | tls | object | `{"ca":{"cert":"","certValidityDuration":1095,"key":""},"caBundle":{"enabled":false,"key":"ca.crt","name":"cilium-root-ca.crt","useSecret":false},"secretsBackend":"local"}` | Configure TLS configuration in the agent. | | tls.ca | object | `{"cert":"","certValidityDuration":1095,"key":""}` | Base64 encoded PEM values for the CA certificate and private key. This can be used as common CA to generate certificates used by hubble and clustermesh components. It is neither required nor used when cert-manager is used to generate the certificates. | diff --git a/internal/constellation/helm/charts/cilium/README.md.gotmpl b/internal/constellation/helm/charts/cilium/README.md.gotmpl index db2d81b74..4aa7da8f9 100644 --- a/internal/constellation/helm/charts/cilium/README.md.gotmpl +++ b/internal/constellation/helm/charts/cilium/README.md.gotmpl @@ -48,7 +48,7 @@ offer from the [Getting Started Guides page](https://docs.cilium.io/en/stable/ge ## Getting Help The best way to get help if you get stuck is to ask a question on the -[Cilium Slack channel](https://cilium.herokuapp.com/). With Cilium +[Cilium Slack channel](https://slack.cilium.io). With Cilium contributors across the globe, there is almost always someone available to help. {{ template "chart.valuesSection" . }} diff --git a/internal/constellation/helm/charts/cilium/files/agent/poststart-eni.bash b/internal/constellation/helm/charts/cilium/files/agent/poststart-eni.bash index 66fccf457..a57d89682 100644 --- a/internal/constellation/helm/charts/cilium/files/agent/poststart-eni.bash +++ b/internal/constellation/helm/charts/cilium/files/agent/poststart-eni.bash @@ -11,9 +11,9 @@ set -o nounset # dependencies on anything that is part of the startup script # itself, and can be safely run multiple times per node (e.g. in # case of a restart). -if [[ "$(iptables-save | grep -c 'AWS-SNAT-CHAIN|AWS-CONNMARK-CHAIN')" != "0" ]]; +if [[ "$(iptables-save | grep -E -c 'AWS-SNAT-CHAIN|AWS-CONNMARK-CHAIN')" != "0" ]]; then echo 'Deleting iptables rules created by the AWS CNI VPC plugin' - iptables-save | grep -v 'AWS-SNAT-CHAIN|AWS-CONNMARK-CHAIN' | iptables-restore + iptables-save | grep -E -v 'AWS-SNAT-CHAIN|AWS-CONNMARK-CHAIN' | iptables-restore fi echo 'Done!' diff --git a/internal/constellation/helm/charts/cilium/files/cilium-agent/dashboards/cilium-dashboard.json b/internal/constellation/helm/charts/cilium/files/cilium-agent/dashboards/cilium-dashboard.json index 992c8524a..94af2eac3 100644 --- a/internal/constellation/helm/charts/cilium/files/cilium-agent/dashboards/cilium-dashboard.json +++ b/internal/constellation/helm/charts/cilium/files/cilium-agent/dashboards/cilium-dashboard.json @@ -5823,7 +5823,7 @@ "refId": "C" }, { - "expr": "sum(cilium_policy_change_total{k8s_app=\"cilium\", pod=~\"$pod\"}, outcome=\"fail\") by (pod)", + "expr": "sum(cilium_policy_change_total{k8s_app=\"cilium\", pod=~\"$pod\", outcome=\"fail\"}) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "policy change errors", diff --git a/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-dashboard.json b/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-dashboard.json index 8de5ec1d0..0ff1dcbec 100644 --- a/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-dashboard.json +++ b/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-dashboard.json @@ -3194,7 +3194,23 @@ "style": "dark", "tags": [], "templating": { - "list": [] + "list": [ + { + "current": {}, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] }, "time": { "from": "now-6h", diff --git a/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-dns-namespace.json b/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-dns-namespace.json index d286fdb3a..57f804cf2 100644 --- a/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-dns-namespace.json +++ b/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-dns-namespace.json @@ -484,7 +484,7 @@ "includeAll": false, "label": "Data Source", "multi": false, - "name": "prometheus_datasource", + "name": "DS_PROMETHEUS", "options": [], "query": "prometheus", "queryValue": "", diff --git a/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-network-overview-namespace.json b/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-network-overview-namespace.json index d0cf9d3b4..cddb473d7 100644 --- a/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-network-overview-namespace.json +++ b/internal/constellation/helm/charts/cilium/files/hubble/dashboards/hubble-network-overview-namespace.json @@ -883,7 +883,7 @@ "includeAll": false, "label": "Data Source", "multi": false, - "name": "prometheus_datasource", + "name": "DS_PROMETHEUS", "options": [], "query": "prometheus", "queryValue": "", diff --git a/internal/constellation/helm/charts/cilium/files/nodeinit/startup.bash b/internal/constellation/helm/charts/cilium/files/nodeinit/startup.bash index 975b71fa7..aaaba0925 100644 --- a/internal/constellation/helm/charts/cilium/files/nodeinit/startup.bash +++ b/internal/constellation/helm/charts/cilium/files/nodeinit/startup.bash @@ -100,7 +100,7 @@ then # Since that version containerd no longer allows missing configuration for the CNI, # not even for pods with hostNetwork set to true. Thus, we add a temporary one. # This will be replaced with the real config by the agent pod. - echo -e "{\n\t"cniVersion": "0.3.1",\n\t"name": "cilium",\n\t"type": "cilium-cni"\n}" > /etc/cni/net.d/05-cilium.conf + echo -e '{\n\t"cniVersion": "0.3.1",\n\t"name": "cilium",\n\t"type": "cilium-cni"\n}' > /etc/cni/net.d/05-cilium.conf fi # Start containerd. It won't create it's CNI configuration file anymore. diff --git a/internal/constellation/helm/charts/cilium/templates/_helpers.tpl b/internal/constellation/helm/charts/cilium/templates/_helpers.tpl index 3e5429e2a..39b3d6955 100644 --- a/internal/constellation/helm/charts/cilium/templates/_helpers.tpl +++ b/internal/constellation/helm/charts/cilium/templates/_helpers.tpl @@ -43,62 +43,7 @@ where: {{- if $priorityClass }} {{- $priorityClass }} {{- else if and $root.Values.enableCriticalPriorityClass $criticalPriorityClass -}} - {{- if and (eq $root.Release.Namespace "kube-system") (semverCompare ">=1.10-0" $root.Capabilities.KubeVersion.Version) -}} - {{- $criticalPriorityClass }} - {{- else if semverCompare ">=1.17-0" $root.Capabilities.KubeVersion.Version -}} - {{- $criticalPriorityClass }} - {{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for ingress. -*/}} -{{- define "ingress.apiVersion" -}} -{{- if semverCompare ">=1.16-0, <1.19-0" .Capabilities.KubeVersion.Version -}} -{{- print "networking.k8s.io/v1beta1" -}} -{{- else if semverCompare "^1.19-0" .Capabilities.KubeVersion.Version -}} -{{- print "networking.k8s.io/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate backend for Hubble UI ingress. -*/}} -{{- define "ingress.paths" -}} -{{ if semverCompare ">=1.4-0, <1.19-0" .Capabilities.KubeVersion.Version -}} -backend: - serviceName: hubble-ui - servicePort: http -{{- else if semverCompare "^1.19-0" .Capabilities.KubeVersion.Version -}} -pathType: Prefix -backend: - service: - name: hubble-ui - port: - name: http -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for cronjob. -*/}} -{{- define "cronjob.apiVersion" -}} -{{- if semverCompare ">=1.21-0" .Capabilities.KubeVersion.Version -}} -{{- print "batch/v1" -}} -{{- else -}} -{{- print "batch/v1beta1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for podDisruptionBudget. -*/}} -{{- define "podDisruptionBudget.apiVersion" -}} -{{- if semverCompare ">=1.21-0" .Capabilities.KubeVersion.Version -}} -{{- print "policy/v1" -}} -{{- else -}} -{{- print "policy/v1beta1" -}} + {{- $criticalPriorityClass }} {{- end -}} {{- end -}} diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-agent/daemonset.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-agent/daemonset.yaml index 773a5b26b..3e288525f 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-agent/daemonset.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-agent/daemonset.yaml @@ -53,6 +53,7 @@ spec: cilium.io/cilium-configmap-checksum: {{ include (print $.Template.BasePath "/cilium-configmap.yaml") . | sha256sum | quote }} {{- end }} {{- if not .Values.securityContext.privileged }} + {{- if semverCompare "<1.30.0" (printf "%d.%d.0" (semver .Capabilities.KubeVersion.Version).Major (semver .Capabilities.KubeVersion.Version).Minor) }} # Set app AppArmor's profile to "unconfined". The value of this annotation # can be modified as long users know which profiles they have available # in AppArmor. @@ -63,6 +64,7 @@ spec: container.apparmor.security.beta.kubernetes.io/apply-sysctl-overwrites: "unconfined" {{- end }} {{- end }} + {{- end }} {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} @@ -81,6 +83,11 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} + {{- /* K8s version lower than 1.30.0 don't support the "appArmorProfile" field, */}} + {{- /* thus we have to remove it. */}} + {{- if semverCompare "<1.30.0" (printf "%d.%d.0" (semver .Capabilities.KubeVersion.Version).Major (semver .Capabilities.KubeVersion.Version).Minor) }} + {{- $_ := unset .Values.podSecurityContext "appArmorProfile" }} + {{- end }} {{- with .Values.podSecurityContext }} securityContext: {{- toYaml . | nindent 8 }} @@ -115,7 +122,6 @@ spec: {{- with .Values.extraArgs }} {{- toYaml . | trim | nindent 8 }} {{- end }} - {{- if semverCompare ">=1.20-0" .Capabilities.KubeVersion.Version }} startupProbe: httpGet: host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} @@ -129,7 +135,6 @@ spec: periodSeconds: {{ .Values.startupProbe.periodSeconds }} successThreshold: 1 initialDelaySeconds: 5 - {{- end }} livenessProbe: {{- if or .Values.keepDeprecatedProbes $defaultKeepDeprecatedProbes }} exec: @@ -147,14 +152,6 @@ spec: - name: "brief" value: "true" {{- end }} - {{- if semverCompare "<1.20-0" .Capabilities.KubeVersion.Version }} - # The initial delay for the liveness probe is intentionally large to - # avoid an endless kill & restart cycle if in the event that the initial - # bootstrapping takes longer than expected. - # Starting from Kubernetes 1.20, we are using startupProbe instead - # of this field. - initialDelaySeconds: 120 - {{- end }} periodSeconds: {{ .Values.livenessProbe.periodSeconds }} successThreshold: 1 failureThreshold: {{ .Values.livenessProbe.failureThreshold }} @@ -176,9 +173,6 @@ spec: - name: "brief" value: "true" {{- end }} - {{- if semverCompare "<1.20-0" .Capabilities.KubeVersion.Version }} - initialDelaySeconds: 5 - {{- end }} periodSeconds: {{ .Values.readinessProbe.periodSeconds }} successThreshold: 1 failureThreshold: {{ .Values.readinessProbe.failureThreshold }} @@ -201,6 +195,7 @@ spec: valueFrom: resourceFieldRef: resource: limits.memory + divisor: '1' {{- if .Values.k8sServiceHost }} - name: KUBERNETES_SERVICE_HOST value: {{ .Values.k8sServiceHost | quote }} @@ -405,6 +400,9 @@ spec: volumeMounts: - name: cilium-run mountPath: /var/run/cilium + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} {{- with .Values.monitor.resources }} resources: {{- toYaml . | trim | nindent 10 }} @@ -429,6 +427,9 @@ spec: {{- if (not (kindIs "invalid" .Values.daemon.blockedConfigOverrides)) }} - "--deny-config-keys={{.Values.daemon.blockedConfigOverrides}}" {{- end }} + {{- if .Values.kubeConfigPath }} + - "--k8s-kubeconfig-path={{ .Values.kubeConfigPath }}" + {{- end }} env: - name: K8S_NODE_NAME valueFrom: @@ -454,6 +455,14 @@ spec: volumeMounts: - name: tmp mountPath: /tmp + {{- if .Values.kubeConfigPath }} + - name: kube-config + mountPath: {{ .Values.kubeConfigPath }} + readOnly: true + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} terminationMessagePolicy: FallbackToLogsOnError {{- if .Values.cgroup.autoMount.enabled }} # Required to mount cgroup2 filesystem on the underlying Kubernetes node. @@ -504,9 +513,15 @@ spec: drop: - ALL {{- end}} + {{- end }} + {{- if .Values.sysctlfix.enabled }} - name: apply-sysctl-overwrites image: {{ include "cilium.image" .Values.image | quote }} imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.initResources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} env: - name: BIN_PATH value: {{ .Values.cni.binPath }} @@ -552,6 +567,10 @@ spec: - name: mount-bpf-fs image: {{ include "cilium.image" .Values.image | quote }} imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.initResources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} args: - 'mount | grep "/sys/fs/bpf type bpf" || mount -t bpf bpf /sys/fs/bpf' command: @@ -573,6 +592,10 @@ spec: - name: wait-for-node-init image: {{ include "cilium.image" .Values.image | quote }} imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.initResources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} command: - sh - -c @@ -650,14 +673,21 @@ spec: mountPropagation: HostToContainer - name: cilium-run mountPath: /var/run/cilium - {{- with .Values.nodeinit.resources }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.initResources }} resources: {{- toYaml . | trim | nindent 10 }} {{- end }} - {{- if and .Values.waitForKubeProxy (and (ne $kubeProxyReplacement "strict") (ne $kubeProxyReplacement "true")) }} + {{- if and .Values.waitForKubeProxy (and (ne (toString $kubeProxyReplacement) "strict") (ne (toString $kubeProxyReplacement) "true")) }} - name: wait-for-kube-proxy image: {{ include "cilium.image" .Values.image | quote }} imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.initResources }} + resources: + {{- toYaml . | trim | nindent 10 }} + {{- end }} securityContext: privileged: true command: @@ -716,20 +746,21 @@ spec: mountPath: /host/opt/cni/bin {{- end }} # .Values.cni.install - name: firewall-pods - image: ghcr.io/edgelesssys/cilium/cilium:v1.15.0-pre.3-edg.2@sha256:c21b7fbbb084a128a479d6170e5f89ad2768dfecb4af10ee6a99ffe5d1a11749 + image: {{ include "cilium.image" .Values.image | quote }} imagePullPolicy: IfNotPresent command: - /bin/bash - -exc - | pref=32 - interface=$(ip route | awk '/^default/ { print $5 }') - tc qdisc add dev "${interface}" clsact || true - tc filter del dev "${interface}" ingress pref "${pref}" 2>/dev/null || true - handle=0 - for cidr in ${POD_CIDRS}; do - handle=$((handle + 1)) - tc filter replace dev "${interface}" ingress pref "${pref}" handle "${handle}" protocol ip flower dst_ip "${cidr}" action drop + for interface in $(ip route | awk '/^default/ { print $5 }'); do + tc qdisc add dev "${interface}" clsact || true + tc filter del dev "${interface}" ingress pref "${pref}" 2>/dev/null || true + handle=0 + for cidr in ${POD_CIDRS}; do + handle=$((handle + 1)) + tc filter replace dev "${interface}" ingress pref "${pref}" handle "${handle}" protocol ip flower dst_ip "${cidr}" action drop + done done env: - name: POD_CIDRS @@ -748,7 +779,6 @@ spec: - NET_ADMIN restartPolicy: Always priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.priorityClassName "system-node-critical") }} - serviceAccount: {{ .Values.serviceAccounts.cilium.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.cilium.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.cilium.automount }} terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} @@ -798,8 +828,8 @@ spec: path: /sys/fs/bpf type: DirectoryOrCreate {{- end }} - {{- if .Values.cgroup.autoMount.enabled }} - # To mount cgroup2 filesystem on the host + {{- if or .Values.cgroup.autoMount.enabled .Values.sysctlfix.enabled }} + # To mount cgroup2 filesystem on the host or apply sysctlfix - name: hostproc hostPath: path: /proc diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-agent/servicemonitor.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-agent/servicemonitor.yaml index d7c5e5e3c..c2ffa66c2 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-agent/servicemonitor.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-agent/servicemonitor.yaml @@ -39,6 +39,20 @@ spec: metricRelabelings: {{- toYaml . | nindent 4 }} {{- end }} + {{- if .Values.envoy.prometheus.serviceMonitor.enabled }} + - port: envoy-metrics + interval: {{ .Values.envoy.prometheus.serviceMonitor.interval | quote }} + honorLabels: true + path: /metrics + {{- with .Values.envoy.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.envoy.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} targetLabels: - k8s-app {{- if .Values.prometheus.serviceMonitor.jobLabel }} diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-configmap.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-configmap.yaml index b67e50392..9d393c311 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-configmap.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-configmap.yaml @@ -14,6 +14,7 @@ {{- $azureUsePrimaryAddress := "true" -}} {{- $defaultK8sClientQPS := 5 -}} {{- $defaultK8sClientBurst := 10 -}} +{{- $defaultDNSProxyEnableTransparentMode := "false" -}} {{- /* Default values when 1.8 was initially deployed */ -}} {{- if semverCompare ">=1.8" (default "1.8" .Values.upgradeCompatibility) -}} @@ -48,6 +49,7 @@ {{- $azureUsePrimaryAddress = "false" -}} {{- end }} {{- $defaultKubeProxyReplacement = "disabled" -}} + {{- $defaultDNSProxyEnableTransparentMode = "true" -}} {{- end -}} {{- /* Default values when 1.14 was initially deployed */ -}} @@ -364,6 +366,11 @@ data: enable-host-legacy-routing: "true" {{- end }} +{{- if .Values.bpf.nodeMapMax }} + # node-map-max specifies the maximum number of entries for the node map. + bpf-node-map-max: {{ .Values.bpf.nodeMapMax | quote }} +{{- end }} + {{- if .Values.bpf.authMapMax }} # bpf-auth-map-max specifies the maximum number of entries in the auth map bpf-auth-map-max: {{ .Values.bpf.authMapMax | quote }} @@ -448,9 +455,15 @@ data: # - vxlan (default) # - geneve {{- if .Values.gke.enabled }} + {{- if ne (.Values.routingMode | default "native") "native" }} + {{- fail (printf "RoutingMode must be set to native when gke.enabled=true" )}} + {{- end }} routing-mode: "native" enable-endpoint-routes: "true" {{- else if .Values.aksbyocni.enabled }} + {{- if ne (.Values.routingMode | default "tunnel") "tunnel" }} + {{- fail (printf "RoutingMode must be set to tunnel when aksbyocni.enabled=true" )}} + {{- end }} routing-mode: "tunnel" tunnel-protocol: "vxlan" {{- else if .Values.routingMode }} @@ -1153,6 +1166,16 @@ data: {{- end }} {{- if .Values.dnsProxy }} + {{- if hasKey .Values.dnsProxy "enableTransparentMode" }} + # explicit setting gets precedence + dnsproxy-enable-transparent-mode: {{ .Values.dnsProxy.enableTransparentMode | quote }} + {{- else if eq $cniChainingMode "none" }} + # default DNS proxy to transparent mode in non-chaining modes + dnsproxy-enable-transparent-mode: {{ $defaultDNSProxyEnableTransparentMode | quote }} + {{- end }} + {{- if (not (kindIs "invalid" .Values.dnsProxy.socketLingerTimeout)) }} + dnsproxy-socket-linger-timeout: {{ .Values.dnsProxy.socketLingerTimeout | quote }} + {{- end }} {{- if .Values.dnsProxy.dnsRejectResponseCode }} tofqdns-dns-reject-response-code: {{ .Values.dnsProxy.dnsRejectResponseCode | quote }} {{- end }} @@ -1206,9 +1229,12 @@ data: mesh-auth-spiffe-trust-domain: {{ .Values.authentication.mutual.spire.trustDomain | quote }} {{- end }} + proxy-xff-num-trusted-hops-ingress: {{ .Values.envoy.xffNumTrustedHopsL7PolicyIngress | quote }} + proxy-xff-num-trusted-hops-egress: {{ .Values.envoy.xffNumTrustedHopsL7PolicyEgress | quote }} proxy-connect-timeout: {{ .Values.envoy.connectTimeoutSeconds | quote }} proxy-max-requests-per-connection: {{ .Values.envoy.maxRequestsPerConnection | quote }} proxy-max-connection-duration-seconds: {{ .Values.envoy.maxConnectionDurationSeconds | quote }} + proxy-idle-timeout-seconds: {{ .Values.envoy.idleTimeoutDurationSeconds | quote }} external-envoy-proxy: {{ .Values.envoy.enabled | quote }} diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-envoy/daemonset.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-envoy/daemonset.yaml index baec799ec..fd5168a84 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-envoy/daemonset.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-envoy/daemonset.yaml @@ -35,11 +35,13 @@ spec: cilium.io/cilium-envoy-configmap-checksum: {{ include (print $.Template.BasePath "/cilium-envoy/configmap.yaml") . | sha256sum | quote }} {{- end }} {{- if not .Values.envoy.securityContext.privileged }} + {{- if semverCompare "<1.30.0" (printf "%d.%d.0" (semver .Capabilities.KubeVersion.Version).Major (semver .Capabilities.KubeVersion.Version).Minor) }} # Set app AppArmor's profile to "unconfined". The value of this annotation # can be modified as long users know which profiles they have available # in AppArmor. container.apparmor.security.beta.kubernetes.io/cilium-envoy: "unconfined" {{- end }} + {{- end }} {{- with .Values.envoy.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} @@ -56,6 +58,11 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} + {{- /* K8s version lower than 1.30.0 don't support the "appArmorProfile" field, */}} + {{- /* thus we have to remove it. */}} + {{- if semverCompare "<1.30.0" (printf "%d.%d.0" (semver .Capabilities.KubeVersion.Version).Major (semver .Capabilities.KubeVersion.Version).Minor) }} + {{- $_ := unset .Values.envoy.podSecurityContext "appArmorProfile" }} + {{- end }} {{- with .Values.envoy.podSecurityContext }} securityContext: {{- toYaml . | nindent 8 }} @@ -83,10 +90,9 @@ spec: {{- with .Values.envoy.extraArgs }} {{- toYaml . | trim | nindent 8 }} {{- end }} - {{- if semverCompare ">=1.20-0" .Capabilities.KubeVersion.Version }} startupProbe: httpGet: - host: "localhost" + host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} path: /healthz port: {{ .Values.envoy.healthPort }} scheme: HTTP @@ -94,34 +100,22 @@ spec: periodSeconds: {{ .Values.envoy.startupProbe.periodSeconds }} successThreshold: 1 initialDelaySeconds: 5 - {{- end }} livenessProbe: httpGet: - host: "localhost" + host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} path: /healthz port: {{ .Values.envoy.healthPort }} scheme: HTTP - {{- if semverCompare "<1.20-0" .Capabilities.KubeVersion.Version }} - # The initial delay for the liveness probe is intentionally large to - # avoid an endless kill & restart cycle if in the event that the initial - # bootstrapping takes longer than expected. - # Starting from Kubernetes 1.20, we are using startupProbe instead - # of this field. - initialDelaySeconds: 120 - {{- end }} periodSeconds: {{ .Values.envoy.livenessProbe.periodSeconds }} successThreshold: 1 failureThreshold: {{ .Values.envoy.livenessProbe.failureThreshold }} timeoutSeconds: 5 readinessProbe: httpGet: - host: "localhost" + host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} path: /healthz port: {{ .Values.envoy.healthPort }} scheme: HTTP - {{- if semverCompare "<1.20-0" .Capabilities.KubeVersion.Version }} - initialDelaySeconds: 5 - {{- end }} periodSeconds: {{ .Values.envoy.readinessProbe.periodSeconds }} successThreshold: 1 failureThreshold: {{ .Values.envoy.readinessProbe.failureThreshold }} @@ -207,7 +201,6 @@ spec: {{- end }} restartPolicy: Always priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.envoy.priorityClassName "system-node-critical") }} - serviceAccount: {{ .Values.serviceAccounts.envoy.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.envoy.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.envoy.automount }} terminationGracePeriodSeconds: {{ .Values.envoy.terminationGracePeriodSeconds }} diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-envoy/servicemonitor.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-envoy/servicemonitor.yaml index 3d6b745e3..10f84d82b 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-envoy/servicemonitor.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-envoy/servicemonitor.yaml @@ -7,15 +7,16 @@ metadata: namespace: {{ .Values.envoy.prometheus.serviceMonitor.namespace | default .Release.Namespace }} labels: app.kubernetes.io/part-of: cilium + app.kubernetes.io/name: cilium-envoy {{- with .Values.envoy.prometheus.serviceMonitor.labels }} {{- toYaml . | nindent 4 }} {{- end }} - {{- if or .Values.envoy.prometheus.serviceMonitor .Values.envoy.annotations }} + {{- if or .Values.envoy.prometheus.serviceMonitor.annotations .Values.envoy.annotations }} annotations: {{- with .Values.envoy.annotations }} {{- toYaml . | nindent 4 }} {{- end }} - {{- with .Values.envoy.prometheus.serviceMonitor }} + {{- with .Values.envoy.prometheus.serviceMonitor.annotations }} {{- toYaml . | nindent 4 }} {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-ingress-service.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-ingress-service.yaml index ff6269d22..0e489bdac 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-ingress-service.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-ingress-service.yaml @@ -24,14 +24,12 @@ spec: protocol: TCP nodePort: {{ .Values.ingressController.service.secureNodePort }} type: {{ .Values.ingressController.service.type }} - {{- if semverCompare ">=1.24-0" .Capabilities.KubeVersion.Version -}} {{- if .Values.ingressController.service.loadBalancerClass }} loadBalancerClass: {{ .Values.ingressController.service.loadBalancerClass }} {{- end }} {{- if (not (kindIs "invalid" .Values.ingressController.service.allocateLoadBalancerNodePorts)) }} allocateLoadBalancerNodePorts: {{ .Values.ingressController.service.allocateLoadBalancerNodePorts }} {{- end }} - {{- end -}} {{- if .Values.ingressController.service.loadBalancerIP }} loadBalancerIP: {{ .Values.ingressController.service.loadBalancerIP }} {{- end }} diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-nodeinit/daemonset.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-nodeinit/daemonset.yaml index 76f1a20d2..c92eabfa6 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-nodeinit/daemonset.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-nodeinit/daemonset.yaml @@ -28,11 +28,13 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} {{- if not .Values.securityContext.privileged }} + {{- if semverCompare "<1.30.0" (printf "%d.%d.0" (semver .Capabilities.KubeVersion.Version).Major (semver .Capabilities.KubeVersion.Version).Minor) }} # Set app AppArmor's profile to "unconfined". The value of this annotation # can be modified as long users know which profiles they have available # in AppArmor. container.apparmor.security.beta.kubernetes.io/node-init: "unconfined" {{- end }} + {{- end }} labels: app: cilium-node-init app.kubernetes.io/part-of: cilium @@ -45,6 +47,15 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} + {{- /* K8s version lower than 1.30.0 don't support the "appArmorProfile" field, */}} + {{- /* thus we have to remove it. */}} + {{- if semverCompare "<1.30.0" (printf "%d.%d.0" (semver .Capabilities.KubeVersion.Version).Major (semver .Capabilities.KubeVersion.Version).Minor) }} + {{- $_ := unset .Values.nodeinit.podSecurityContext "appArmorProfile" }} + {{- end }} + {{- with .Values.nodeinit.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: node-init image: {{ include "cilium.image" .Values.nodeinit.image | quote }} @@ -103,7 +114,6 @@ spec: hostNetwork: true priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.nodeinit.priorityClassName "system-node-critical") }} {{- if .Values.serviceAccounts.nodeinit.enabled }} - serviceAccount: {{ .Values.serviceAccounts.nodeinit.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.nodeinit.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.nodeinit.automount }} {{- end }} diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-operator/deployment.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-operator/deployment.yaml index 4f4450e51..5c6c467cf 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-operator/deployment.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-operator/deployment.yaml @@ -252,7 +252,6 @@ spec: {{- end }} restartPolicy: Always priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.operator.priorityClassName "system-cluster-critical") }} - serviceAccount: {{ .Values.serviceAccounts.operator.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.operator.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.operator.automount }} {{- with .Values.operator.affinity }} diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-operator/poddisruptionbudget.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-operator/poddisruptionbudget.yaml index a224b9e6c..05b251046 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-operator/poddisruptionbudget.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-operator/poddisruptionbudget.yaml @@ -1,6 +1,6 @@ {{- if and .Values.operator.enabled .Values.operator.podDisruptionBudget.enabled }} {{- $component := .Values.operator.podDisruptionBudget }} -apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: cilium-operator diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-preflight/daemonset.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-preflight/daemonset.yaml index bc13be432..b5228616b 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-preflight/daemonset.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-preflight/daemonset.yaml @@ -70,8 +70,13 @@ spec: - /tmp/ready initialDelaySeconds: 5 periodSeconds: 5 - {{- with .Values.preflight.extraEnv }} env: + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + {{- with .Values.preflight.extraEnv }} {{- toYaml . | trim | nindent 12 }} {{- end }} volumeMounts: @@ -171,10 +176,13 @@ spec: dnsPolicy: ClusterFirstWithHostNet restartPolicy: Always priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.preflight.priorityClassName "system-node-critical") }} - serviceAccount: {{ .Values.serviceAccounts.preflight.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.preflight.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.preflight.automount }} terminationGracePeriodSeconds: {{ .Values.preflight.terminationGracePeriodSeconds }} + {{- with .Values.preflight.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} {{- with .Values.preflight.tolerations }} tolerations: {{- toYaml . | trim | nindent 8 }} diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-preflight/deployment.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-preflight/deployment.yaml index efd923b2d..1f87d2076 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-preflight/deployment.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-preflight/deployment.yaml @@ -60,6 +60,10 @@ spec: - /tmp/ready-validate-cnp initialDelaySeconds: 5 periodSeconds: 5 + {{- with .Values.preflight.extraVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 10 }} + {{- end }} env: {{- if .Values.k8sServiceHost }} - name: KUBERNETES_SERVICE_HOST @@ -77,11 +81,15 @@ spec: {{- toYaml . | trim | nindent 12 }} {{- end }} terminationMessagePolicy: FallbackToLogsOnError + {{- with .Values.preflight.extraVolumes }} + volumes: + {{- toYaml . | trim | nindent 6 }} + {{- end }} hostNetwork: true restartPolicy: Always priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.preflight.priorityClassName "system-cluster-critical") }} - serviceAccount: {{ .Values.serviceAccounts.preflight.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.preflight.name | quote }} + automountServiceAccountToken: {{ .Values.serviceAccounts.preflight.automount }} terminationGracePeriodSeconds: {{ .Values.preflight.terminationGracePeriodSeconds }} {{- with .Values.preflight.affinity }} affinity: diff --git a/internal/constellation/helm/charts/cilium/templates/cilium-preflight/poddisruptionbudget.yaml b/internal/constellation/helm/charts/cilium/templates/cilium-preflight/poddisruptionbudget.yaml index 4b3c7cb0d..c00d9b896 100644 --- a/internal/constellation/helm/charts/cilium/templates/cilium-preflight/poddisruptionbudget.yaml +++ b/internal/constellation/helm/charts/cilium/templates/cilium-preflight/poddisruptionbudget.yaml @@ -1,6 +1,6 @@ {{- if and .Values.preflight.enabled .Values.preflight.validateCNPs .Values.preflight.podDisruptionBudget.enabled }} {{- $component := .Values.preflight.podDisruptionBudget }} -apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: cilium-pre-flight-check diff --git a/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/deployment.yaml b/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/deployment.yaml index a1d7a6df5..f0d551bb6 100644 --- a/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/deployment.yaml +++ b/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/deployment.yaml @@ -59,7 +59,7 @@ spec: {{- end }} # These need to match the equivalent arguments to etcd in the main container. - --etcd-cluster-name=clustermesh-apiserver - - --etcd-initial-cluster-token=clustermesh-apiserver + - --etcd-initial-cluster-token=$(INITIAL_CLUSTER_TOKEN) - --etcd-data-dir=/var/run/etcd {{- with .Values.clustermesh.apiserver.etcd.init.extraArgs }} {{- toYaml . | trim | nindent 8 }} @@ -76,12 +76,23 @@ spec: configMapKeyRef: name: cilium-config key: cluster-name + - name: INITIAL_CLUSTER_TOKEN + valueFrom: + fieldRef: + fieldPath: metadata.uid {{- with .Values.clustermesh.apiserver.etcd.init.extraEnv }} {{- toYaml . | trim | nindent 8 }} {{- end }} + {{- with .Values.clustermesh.apiserver.etcd.securityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} volumeMounts: - name: etcd-data-dir mountPath: /var/run/etcd + {{- with .Values.clustermesh.apiserver.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} terminationMessagePolicy: FallbackToLogsOnError {{- with .Values.clustermesh.apiserver.etcd.init.resources }} resources: @@ -105,7 +116,7 @@ spec: # uses net.SplitHostPort() internally and it accepts the that format. - --listen-client-urls=https://127.0.0.1:2379,https://[$(HOSTNAME_IP)]:2379 - --advertise-client-urls=https://[$(HOSTNAME_IP)]:2379 - - --initial-cluster-token=clustermesh-apiserver + - --initial-cluster-token=$(INITIAL_CLUSTER_TOKEN) - --auto-compaction-retention=1 {{- if .Values.clustermesh.apiserver.metrics.etcd.enabled }} - --listen-metrics-urls=http://[$(HOSTNAME_IP)]:{{ .Values.clustermesh.apiserver.metrics.etcd.port }} @@ -118,6 +129,10 @@ spec: valueFrom: fieldRef: fieldPath: status.podIP + - name: INITIAL_CLUSTER_TOKEN + valueFrom: + fieldRef: + fieldPath: metadata.uid ports: - name: etcd containerPort: 2379 @@ -133,6 +148,9 @@ spec: readOnly: true - name: etcd-data-dir mountPath: /var/run/etcd + {{- with .Values.clustermesh.apiserver.extraVolumeMounts }} + {{- toYaml . | nindent 8 }} + {{- end }} terminationMessagePolicy: FallbackToLogsOnError {{- with .Values.clustermesh.apiserver.etcd.resources }} resources: @@ -386,7 +404,6 @@ spec: {{- end }} restartPolicy: Always priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.clustermesh.apiserver.priorityClassName "system-cluster-critical") }} - serviceAccount: {{ .Values.serviceAccounts.clustermeshApiserver.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.clustermeshApiserver.name | quote }} terminationGracePeriodSeconds: {{ .Values.clustermesh.apiserver.terminationGracePeriodSeconds }} automountServiceAccountToken: {{ .Values.serviceAccounts.clustermeshApiserver.automount }} diff --git a/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/poddisruptionbudget.yaml b/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/poddisruptionbudget.yaml index 4a1bbf7e0..a5d30b7b1 100644 --- a/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/poddisruptionbudget.yaml +++ b/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/poddisruptionbudget.yaml @@ -1,6 +1,6 @@ {{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.podDisruptionBudget.enabled }} {{- $component := .Values.clustermesh.apiserver.podDisruptionBudget }} -apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: clustermesh-apiserver diff --git a/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/service.yaml b/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/service.yaml index 0a7028c54..14daaeb59 100644 --- a/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/service.yaml +++ b/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/service.yaml @@ -26,6 +26,9 @@ spec: {{- if and (eq "NodePort" .Values.clustermesh.apiserver.service.type) .Values.clustermesh.apiserver.service.nodePort }} nodePort: {{ .Values.clustermesh.apiserver.service.nodePort }} {{- end }} + {{- if and (eq "LoadBalancer" .Values.clustermesh.apiserver.service.type) .Values.clustermesh.apiserver.service.loadBalancerClass }} + loadBalancerClass: {{ .Values.clustermesh.apiserver.service.loadBalancerClass }} + {{- end }} {{- if and (eq "LoadBalancer" .Values.clustermesh.apiserver.service.type) .Values.clustermesh.apiserver.service.loadBalancerIP }} loadBalancerIP: {{ .Values.clustermesh.apiserver.service.loadBalancerIP }} {{- end }} diff --git a/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml b/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml index 946602b40..8c0e4cd5c 100644 --- a/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml +++ b/internal/constellation/helm/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml @@ -1,5 +1,5 @@ {{- if and (or .Values.externalWorkloads.enabled .Values.clustermesh.useAPIServer) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "cronJob") .Values.clustermesh.apiserver.tls.auto.schedule }} -apiVersion: {{ include "cronjob.apiVersion" . }} +apiVersion: batch/v1 kind: CronJob metadata: name: clustermesh-apiserver-generate-certs diff --git a/internal/constellation/helm/charts/cilium/templates/etcd-operator/cilium-etcd-operator-deployment.yaml b/internal/constellation/helm/charts/cilium/templates/etcd-operator/cilium-etcd-operator-deployment.yaml index 5946219f4..7aefc0d35 100644 --- a/internal/constellation/helm/charts/cilium/templates/etcd-operator/cilium-etcd-operator-deployment.yaml +++ b/internal/constellation/helm/charts/cilium/templates/etcd-operator/cilium-etcd-operator-deployment.yaml @@ -110,7 +110,6 @@ spec: hostNetwork: true priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.clustermesh.apiserver.priorityClassName "system-cluster-critical") }} restartPolicy: Always - serviceAccount: {{ .Values.serviceAccounts.etcd.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.etcd.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.etcd.automount }} {{- with .Values.etcd.nodeSelector }} diff --git a/internal/constellation/helm/charts/cilium/templates/etcd-operator/poddisruptionbudget.yaml b/internal/constellation/helm/charts/cilium/templates/etcd-operator/poddisruptionbudget.yaml index 5939b4ae9..d604e5222 100644 --- a/internal/constellation/helm/charts/cilium/templates/etcd-operator/poddisruptionbudget.yaml +++ b/internal/constellation/helm/charts/cilium/templates/etcd-operator/poddisruptionbudget.yaml @@ -1,6 +1,6 @@ {{- if and .Values.etcd.managed .Values.etcd.podDisruptionBudget.enabled }} {{- $component := .Values.etcd.podDisruptionBudget }} -apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: cilium-etcd-operator diff --git a/internal/constellation/helm/charts/cilium/templates/hubble-relay/deployment.yaml b/internal/constellation/helm/charts/cilium/templates/hubble-relay/deployment.yaml index 14d6c62c6..5a5fb35a8 100644 --- a/internal/constellation/helm/charts/cilium/templates/hubble-relay/deployment.yaml +++ b/internal/constellation/helm/charts/cilium/templates/hubble-relay/deployment.yaml @@ -71,26 +71,37 @@ spec: protocol: TCP {{- end }} readinessProbe: - {{- include "hubble-relay.probe" . | nindent 12 }} - {{- if semverCompare "<1.20-0" .Capabilities.KubeVersion.Version }} - # Starting from Kubernetes 1.20, we are using startupProbe instead - # of this field. - initialDelaySeconds: 5 - {{- end }} + grpc: + port: 4222 + timeoutSeconds: 3 + # livenessProbe will kill the pod, we should be very conservative + # here on failures since killing the pod should be a last resort, and + # we should provide enough time for relay to retry before killing it. livenessProbe: - {{- include "hubble-relay.probe" . | nindent 12 }} - {{- if semverCompare "<1.20-0" .Capabilities.KubeVersion.Version }} - # Starting from Kubernetes 1.20, we are using startupProbe instead - # of this field. - initialDelaySeconds: 60 - {{- end }} - {{- if semverCompare ">=1.20-0" .Capabilities.KubeVersion.Version }} + grpc: + port: 4222 + timeoutSeconds: 10 + # Give relay time to establish connections and make a few retries + # before starting livenessProbes. + initialDelaySeconds: 10 + # 10 second * 12 failures = 2 minutes of failure. + # If relay cannot become healthy after 2 minutes, then killing it + # might resolve whatever issue is occurring. + # + # 10 seconds is a reasonable retry period so we can see if it's + # failing regularly or only sporadically. + periodSeconds: 10 + failureThreshold: 12 startupProbe: - # give the relay one minute to start up - {{- include "hubble-relay.probe" . | nindent 12 }} + grpc: + port: 4222 + # Give relay time to get it's certs and establish connections and + # make a few retries before starting startupProbes. + initialDelaySeconds: 10 + # 20 * 3 seconds = 1 minute of failure before we consider startup as failed. failureThreshold: 20 + # Retry more frequently at startup so that it can be considered started more quickly. periodSeconds: 3 - {{- end }} {{- with .Values.hubble.relay.extraEnv }} env: {{- toYaml . | trim | nindent 12 }} @@ -108,10 +119,12 @@ spec: mountPath: /var/lib/hubble-relay/tls readOnly: true {{- end }} + {{- with .Values.hubble.relay.extraVolumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} terminationMessagePolicy: FallbackToLogsOnError restartPolicy: Always priorityClassName: {{ .Values.hubble.relay.priorityClassName }} - serviceAccount: {{ .Values.serviceAccounts.relay.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.relay.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.relay.automount }} terminationGracePeriodSeconds: {{ .Values.hubble.relay.terminationGracePeriodSeconds }} @@ -178,18 +191,7 @@ spec: path: server.key {{- end }} {{- end }} -{{- end }} - -{{- define "hubble-relay.probe" }} -{{- /* This distinction can be removed once we drop support for k8s 1.23 */}} -{{- if semverCompare ">=1.24-0" .Capabilities.KubeVersion.Version -}} -grpc: - port: 4222 -{{- else }} -exec: - command: - - grpc_health_probe - - -addr=localhost:4222 -{{- end }} -timeoutSeconds: 3 + {{- with .Values.hubble.relay.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/cilium/templates/hubble-relay/poddisruptionbudget.yaml b/internal/constellation/helm/charts/cilium/templates/hubble-relay/poddisruptionbudget.yaml index 4fd6da9ba..6162cb81d 100644 --- a/internal/constellation/helm/charts/cilium/templates/hubble-relay/poddisruptionbudget.yaml +++ b/internal/constellation/helm/charts/cilium/templates/hubble-relay/poddisruptionbudget.yaml @@ -1,6 +1,6 @@ {{- if and .Values.hubble.enabled .Values.hubble.relay.enabled .Values.hubble.relay.podDisruptionBudget.enabled }} {{- $component := .Values.hubble.relay.podDisruptionBudget }} -apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: hubble-relay diff --git a/internal/constellation/helm/charts/cilium/templates/hubble-ui/deployment.yaml b/internal/constellation/helm/charts/cilium/templates/hubble-ui/deployment.yaml index a7dd5cb8f..105907a5f 100644 --- a/internal/constellation/helm/charts/cilium/templates/hubble-ui/deployment.yaml +++ b/internal/constellation/helm/charts/cilium/templates/hubble-ui/deployment.yaml @@ -40,13 +40,10 @@ spec: {{- end }} spec: {{- with .Values.hubble.ui.securityContext }} - {{- if .enabled }} securityContext: {{- omit . "enabled" | toYaml | nindent 8 }} - {{- end}} {{- end }} priorityClassName: {{ .Values.hubble.ui.priorityClassName }} - serviceAccount: {{ .Values.serviceAccounts.ui.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.ui.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.ui.automount }} {{- with .Values.imagePullSecrets }} diff --git a/internal/constellation/helm/charts/cilium/templates/hubble-ui/ingress.yaml b/internal/constellation/helm/charts/cilium/templates/hubble-ui/ingress.yaml index 2c0ff7d3e..348e281d7 100644 --- a/internal/constellation/helm/charts/cilium/templates/hubble-ui/ingress.yaml +++ b/internal/constellation/helm/charts/cilium/templates/hubble-ui/ingress.yaml @@ -1,6 +1,6 @@ {{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.hubble.ui.ingress.enabled }} {{- $baseUrl := .Values.hubble.ui.baseUrl -}} -apiVersion: {{ template "ingress.apiVersion" . }} +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: hubble-ui @@ -35,6 +35,11 @@ spec: http: paths: - path: {{ $baseUrl | quote }} - {{- include "ingress.paths" $ | nindent 12 }} + pathType: Prefix + backend: + service: + name: hubble-ui + port: + name: http {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/cilium/templates/hubble-ui/poddisruptionbudget.yaml b/internal/constellation/helm/charts/cilium/templates/hubble-ui/poddisruptionbudget.yaml index af3b6705d..c23e3ad04 100644 --- a/internal/constellation/helm/charts/cilium/templates/hubble-ui/poddisruptionbudget.yaml +++ b/internal/constellation/helm/charts/cilium/templates/hubble-ui/poddisruptionbudget.yaml @@ -1,6 +1,6 @@ {{- if and (or .Values.hubble.enabled .Values.hubble.ui.standalone.enabled) .Values.hubble.ui.enabled .Values.hubble.ui.podDisruptionBudget.enabled }} {{- $component := .Values.hubble.ui.podDisruptionBudget }} -apiVersion: {{ include "podDisruptionBudget.apiVersion" . }} +apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: hubble-ui diff --git a/internal/constellation/helm/charts/cilium/templates/hubble/peer-service.yaml b/internal/constellation/helm/charts/cilium/templates/hubble/peer-service.yaml index 7ba56456b..aec3f889a 100644 --- a/internal/constellation/helm/charts/cilium/templates/hubble/peer-service.yaml +++ b/internal/constellation/helm/charts/cilium/templates/hubble/peer-service.yaml @@ -24,7 +24,5 @@ spec: {{- end }} protocol: TCP targetPort: {{ .Values.hubble.peerService.targetPort }} -{{- if semverCompare ">=1.22-0" .Capabilities.KubeVersion.GitVersion }} internalTrafficPolicy: Local {{- end }} -{{- end }} diff --git a/internal/constellation/helm/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml b/internal/constellation/helm/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml index fa9966080..7d9f7174c 100644 --- a/internal/constellation/helm/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml +++ b/internal/constellation/helm/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml @@ -1,5 +1,5 @@ {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") .Values.hubble.tls.auto.schedule }} -apiVersion: {{ include "cronjob.apiVersion" . }} +apiVersion: batch/v1 kind: CronJob metadata: name: hubble-generate-certs diff --git a/internal/constellation/helm/charts/cilium/templates/spire/agent/daemonset.yaml b/internal/constellation/helm/charts/cilium/templates/spire/agent/daemonset.yaml index f515a9ac9..6c0bffe78 100644 --- a/internal/constellation/helm/charts/cilium/templates/spire/agent/daemonset.yaml +++ b/internal/constellation/helm/charts/cilium/templates/spire/agent/daemonset.yaml @@ -99,10 +99,12 @@ spec: nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} - {{- with .Values.authentication.mutual.spire.install.agent.tolerations }} tolerations: - {{- toYaml . | trim | nindent 8 }} - {{- end }} + {{- with .Values.authentication.mutual.spire.install.agent.tolerations }} + {{- toYaml . | trim | nindent 8 }} + {{- end }} + - key: {{ .Values.agentNotReadyTaintKey | default "node.cilium.io/agent-not-ready" }} + effect: NoSchedule volumes: - name: spire-config configMap: diff --git a/internal/constellation/helm/charts/cilium/templates/spire/namespace.yaml b/internal/constellation/helm/charts/cilium/templates/spire/namespace.yaml index 1c281f4f7..ccd386808 100644 --- a/internal/constellation/helm/charts/cilium/templates/spire/namespace.yaml +++ b/internal/constellation/helm/charts/cilium/templates/spire/namespace.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled -}} +{{- if and .Values.authentication.mutual.spire.enabled .Values.authentication.mutual.spire.install.enabled (not .Values.authentication.mutual.spire.install.existingNamespace) -}} apiVersion: v1 kind: Namespace metadata: diff --git a/internal/constellation/helm/charts/cilium/templates/validate.yaml b/internal/constellation/helm/charts/cilium/templates/validate.yaml index 3c89e4e38..fabd69fe9 100644 --- a/internal/constellation/helm/charts/cilium/templates/validate.yaml +++ b/internal/constellation/helm/charts/cilium/templates/validate.yaml @@ -1,3 +1,17 @@ +{{/* validate deprecated options are not being used */}} +{{- if .Values.tunnel }} + {{ fail "tunnel was deprecated in v1.14 and has been removed in v1.15. For details please refer to https://docs.cilium.io/en/v1.15/operations/upgrade/#helm-options" }} +{{- end }} +{{- if or (dig "clustermesh" "apiserver" "tls" "ca" "cert" "" .Values.AsMap) (dig "clustermesh" "apiserver" "tls" "ca" "key" "" .Values.AsMap) }} + {{ fail "clustermesh.apiserver.tls.ca.cert and clustermesh.apiserver.tls.ca.key were deprecated in v1.14 and has been removed in v1.15. For details please refer to https://docs.cilium.io/en/v1.15/operations/upgrade/#helm-options" }} +{{- end }} +{{- if .Values.enableK8sEventHandover }} + {{ fail "enableK8sEventHandover was deprecated in v1.14 and has been removed in v1.15. For details please refer to https://docs.cilium.io/en/v1.15/operations/upgrade/#helm-options" }} +{{- end }} +{{- if .Values.enableCnpStatusUpdates }} + {{ fail "enableCnpStatusUpdates was deprecated in v1.14 and has been removed in v1.15. For details please refer to https://docs.cilium.io/en/v1.15/operations/upgrade/#helm-options" }} +{{- end }} + {{/* validate hubble config */}} {{- if and .Values.hubble.ui.enabled (not .Values.hubble.ui.standalone.enabled) }} {{- if not .Values.hubble.relay.enabled }} diff --git a/internal/constellation/helm/charts/cilium/values.yaml b/internal/constellation/helm/charts/cilium/values.yaml index 712d981a7..d276064aa 100644 --- a/internal/constellation/helm/charts/cilium/values.yaml +++ b/internal/constellation/helm/charts/cilium/values.yaml @@ -146,7 +146,7 @@ rollOutCiliumPods: false image: override: ~ repository: "quay.io/cilium/cilium" - tag: "v1.15.0-pre.3" + tag: "v1.15.8" pullPolicy: "IfNotPresent" # cilium-digest digest: "" @@ -218,8 +218,10 @@ extraConfig: {} annotations: {} # -- Security Context for cilium-agent pods. -podSecurityContext: {} - +podSecurityContext: + # -- AppArmorProfile options for the `cilium-agent` and init containers + appArmorProfile: + type: "Unconfined" # -- Annotations to be added to agent pods podAnnotations: {} @@ -236,6 +238,9 @@ resources: {} # cpu: 100m # memory: 512Mi +# -- resources & limits for the agent init containers +initResources: {} + securityContext: # -- User to run the pod with # runAsUser: 0 @@ -465,7 +470,17 @@ bpf: # @default -- `524288` neighMax: ~ + # @schema + # type: [null, integer] + # @schema + # @default -- `16384` + # -- (int) Configures the maximum number of entries for the node table. + nodeMapMax: ~ + # -- Configure the maximum number of entries in endpoint policy map (per endpoint). + # @schema + # type: [null, integer] + # @schema policyMapMax: 16384 # -- (float64) Configure auto-sizing for all BPF maps based on available memory. @@ -966,8 +981,8 @@ certgen: image: override: ~ repository: "quay.io/cilium/certgen" - tag: "v0.1.9" - digest: "sha256:89a0847753686444daabde9474b48340993bd19c7bea66a46e45b2974b82041f" + tag: "v0.1.14" + digest: "sha256:40cdac65aa6ee86c16ce107f8726c4b55ce6654d07bbdf490db6bd492587bf54" useDigest: true pullPolicy: "IfNotPresent" # -- Seconds after which the completed job pod will be deleted @@ -1225,7 +1240,7 @@ hubble: image: override: ~ repository: "quay.io/cilium/hubble-relay" - tag: "v1.15.0-pre.3" + tag: "v1.15.8" # hubble-relay-digest digest: "" useDigest: false @@ -1296,6 +1311,12 @@ hubble: rollingUpdate: maxUnavailable: 1 + # -- Additional hubble-relay volumes. + extraVolumes: [] + + # -- Additional hubble-relay volumeMounts. + extraVolumeMounts: [] + # -- hubble-relay pod security context podSecurityContext: fsGroup: 65532 @@ -1456,8 +1477,8 @@ hubble: image: override: ~ repository: "quay.io/cilium/hubble-ui-backend" - tag: "v0.12.1" - digest: "sha256:1f86f3400827a0451e6332262467f894eeb7caf0eb8779bd951e2caa9d027cbe" + tag: "v0.13.1" + digest: "sha256:0e0eed917653441fded4e7cdb096b7be6a3bddded5a2dd10812a27b1fc6ed95b" useDigest: true pullPolicy: "IfNotPresent" @@ -1495,8 +1516,8 @@ hubble: image: override: ~ repository: "quay.io/cilium/hubble-ui" - tag: "v0.12.1" - digest: "sha256:9e5f81ee747866480ea1ac4630eb6975ff9227f9782b7c93919c081c33f38267" + tag: "v0.13.1" + digest: "sha256:e2e9313eb7caf64b0061d9da0efbdad59c6c461f6ca1752768942bfeda0796c6" useDigest: true pullPolicy: "IfNotPresent" @@ -2054,14 +2075,18 @@ envoy: # -- Set Envoy upstream HTTP idle connection timeout seconds. # Does not apply to connections with pending requests. Default 60s idleTimeoutDurationSeconds: 60 + # -- Number of trusted hops regarding the x-forwarded-for and related HTTP headers for the ingress L7 policy enforcement Envoy listeners. + xffNumTrustedHopsL7PolicyIngress: 0 + # -- Number of trusted hops regarding the x-forwarded-for and related HTTP headers for the egress L7 policy enforcement Envoy listeners. + xffNumTrustedHopsL7PolicyEgress: 0 # -- Envoy container image. image: override: ~ repository: "quay.io/cilium/cilium-envoy" - tag: "v1.27.2-f19708f3d0188fe39b7e024b4525b75a9eeee61f" + tag: "v1.29.7-39a2a56bbd5b3a591f69dbca51d3e30ef97e0e51" pullPolicy: "IfNotPresent" - digest: "sha256:80de27c1d16ab92923cc0cd1fff90f2e7047a9abf3906fda712268d9cbc5b950" + digest: "sha256:bd5ff8c66716080028f414ec1cb4f7dc66f40d2fb5a009fff187f4a9b90b566b" useDigest: true # -- Additional containers added to the cilium Envoy DaemonSet. @@ -2107,8 +2132,10 @@ envoy: annotations: {} # -- Security Context for cilium-envoy pods. - podSecurityContext: {} - + podSecurityContext: + # -- AppArmorProfile options for the `cilium-agent` and init containers + appArmorProfile: + type: "Unconfined" # -- Annotations to be added to envoy pods podAnnotations: {} @@ -2177,7 +2204,20 @@ envoy: labelSelector: matchLabels: k8s-app: cilium-envoy - + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: cilium + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: cilium.io/no-schedule + operator: NotIn + values: + - "true" # -- Node selector for cilium-envoy. nodeSelector: kubernetes.io/os: linux @@ -2198,12 +2238,16 @@ envoy: # Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy dnsPolicy: ~ + # -- Configure Cilium Envoy Prometheus options. + # Note that some of these apply to either cilium-agent or cilium-envoy. prometheus: # -- Enable prometheus metrics for cilium-envoy enabled: true serviceMonitor: # -- Enable service monitors. # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + # Note that this setting applies to both cilium-envoy _and_ cilium-agent + # with Envoy enabled. enabled: false # -- Labels to add to ServiceMonitor cilium-envoy labels: {} @@ -2215,18 +2259,21 @@ envoy: # service monitors configured. # namespace: "" # -- Relabeling configs for the ServiceMonitor cilium-envoy + # or for cilium-agent with Envoy configured. relabelings: - sourceLabels: - __meta_kubernetes_pod_node_name targetLabel: node replacement: ${1} # -- Metrics relabeling configs for the ServiceMonitor cilium-envoy + # or for cilium-agent with Envoy configured. metricRelabelings: ~ # -- Serve prometheus metrics for cilium-envoy on the configured port port: "9964" # -- Enable use of the remote node identity. # ref: https://docs.cilium.io/en/v1.7/install/upgrade/#configmap-remote-node-identity +# Deprecated without replacement in 1.15. To be removed in 1.16. remoteNodeIdentity: true # -- Enable resource quotas for priority classes used in the cluster. @@ -2460,7 +2507,7 @@ operator: image: override: ~ repository: "quay.io/cilium/operator" - tag: "v1.15.0-pre.3" + tag: "v1.15.8" # operator-generic-digest genericDigest: "" # operator-azure-digest @@ -2663,7 +2710,9 @@ nodeinit: image: override: ~ repository: "quay.io/cilium/startup-script" - tag: "62093c5c233ea914bfa26a10ba41f8780d9b737f" + tag: "c54c7edeab7fde4da68e59acd319ab24af242c3f" + digest: "sha256:8d7b41c4ca45860254b3c19e20210462ef89479bb6331d6760c4e609d651b29c" + useDigest: true pullPolicy: "IfNotPresent" # -- The priority class to use for the nodeinit pod. @@ -2707,7 +2756,11 @@ nodeinit: # -- Labels to be added to node-init pods. podLabels: {} - + # -- Security Context for cilium-node-init pods. + podSecurityContext: + # -- AppArmorProfile options for the `cilium-node-init` and init containers + appArmorProfile: + type: "Unconfined" # -- nodeinit resource limits & requests # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ resources: @@ -2755,7 +2808,7 @@ preflight: image: override: ~ repository: "quay.io/cilium/cilium" - tag: "v1.15.0-pre.3" + tag: "v1.15.8" # cilium-digest digest: "" useDigest: false @@ -2917,7 +2970,7 @@ clustermesh: image: override: ~ repository: "quay.io/cilium/clustermesh-apiserver" - tag: "v1.15.0-pre.3" + tag: "v1.15.8" # clustermesh-apiserver-digest digest: "" useDigest: false @@ -3005,9 +3058,6 @@ clustermesh: # NodePort will be redirected to a local backend, regardless of whether the # destination node belongs to the local or the remote cluster. nodePort: 32379 - # -- Optional loadBalancer IP address to use with type LoadBalancer. - # loadBalancerIP: - # -- Annotations for the clustermesh-apiserver # For GKE LoadBalancer, use annotation cloud.google.com/load-balancer-type: "Internal" # For EKS LoadBalancer, use annotation service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0 @@ -3019,6 +3069,21 @@ clustermesh: # -- The internalTrafficPolicy of service used for apiserver access. internalTrafficPolicy: + # @schema + # type: [null, string] + # @schema + # -- Configure a loadBalancerClass. + # Allows to configure the loadBalancerClass on the clustermesh-apiserver + # LB service in case the Service type is set to LoadBalancer + # (requires Kubernetes 1.24+). + loadBalancerClass: ~ + # @schema + # type: [null, string] + # @schema + # -- Configure a specific loadBalancerIP. + # Allows to configure a specific loadBalancerIP on the clustermesh-apiserver + # LB service in case the Service type is set to LoadBalancer. + loadBalancerIP: ~ # -- Number of replicas run for the clustermesh-apiserver deployment. replicas: 1 @@ -3276,7 +3341,10 @@ cgroup: # memory: 128Mi # -- Configure cgroup root where cgroup2 filesystem is mounted on the host (see also: `cgroup.autoMount`) hostRoot: /run/cilium/cgroupv2 - +# -- Configure sysctl override described in #20072. +sysctlfix: + # -- Enable the sysctl override. When enabled, the init container will mount the /proc of the host so that the `sysctlfix` utility can execute. + enabled: true # -- Configure whether to enable auto detect of terminating state for endpoints # in order to support graceful termination. enableK8sTerminatingEndpoint: true @@ -3289,6 +3357,8 @@ enableK8sTerminatingEndpoint: true agentNotReadyTaintKey: "node.cilium.io/agent-not-ready" dnsProxy: + # -- Timeout (in seconds) when closing the connection between the DNS proxy and the upstream server. If set to 0, the connection is closed immediately (with TCP RST). If set to -1, the connection is closed asynchronously in the background. + socketLingerTimeout: 10 # -- DNS response code for rejecting DNS requests, available options are '[nameError refused]'. dnsRejectResponseCode: refused # -- Allow the DNS proxy to compress responses to endpoints that are larger than 512 Bytes or the EDNS0 option, if present. @@ -3310,6 +3380,8 @@ dnsProxy: proxyPort: 0 # -- The maximum time the DNS proxy holds an allowed DNS response before sending it along. Responses are sent as soon as the datapath is updated with the new IP information. proxyResponseMaxDelay: 100ms + # -- DNS proxy operation mode (true/false, or unset to use version dependent defaults) + # enableTransparentMode: true # -- SCTP Configuration Values sctp: @@ -3349,12 +3421,14 @@ authentication: enabled: true # -- SPIRE namespace to install into namespace: cilium-spire + # -- SPIRE namespace already exists. Set to true if Helm should not create, manage, and import the SPIRE namespace. + existingNamespace: false # -- init container image of SPIRE agent and server initImage: override: ~ repository: "docker.io/library/busybox" tag: "1.36.1" - digest: "sha256:223ae047b1065bd069aac01ae3ac8088b3ca4a527827e283b85112f29385fb1b" + digest: "sha256:9ae97d36d26566ff84e8893c64a6dc4fe8ca6d1144bf5b87b2b85a32def253c7" useDigest: true pullPolicy: "IfNotPresent" # SPIRE agent configuration @@ -3363,8 +3437,8 @@ authentication: image: override: ~ repository: "ghcr.io/spiffe/spire-agent" - tag: "1.8.4" - digest: "sha256:d489bc8470d7a0f292e0e3576c3e7025253343dc798241bcfd9061828e2a6bef" + tag: "1.8.5" + digest: "sha256:99405637647968245ff9fe215f8bd2bd0ea9807be9725f8bf19fe1b21471e52b" useDigest: true pullPolicy: "IfNotPresent" # -- SPIRE agent service account @@ -3378,8 +3452,21 @@ authentication: # -- SPIRE Workload Attestor kubelet verification. skipKubeletVerification: true # -- SPIRE agent tolerations configuration + # By default it follows the same tolerations as the agent itself + # to allow the Cilium agent on this node to connect to SPIRE. # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ - tolerations: [] + tolerations: + - key: node.kubernetes.io/not-ready + effect: NoSchedule + - key: node-role.kubernetes.io/master + effect: NoSchedule + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + - key: node.cloudprovider.kubernetes.io/uninitialized + effect: NoSchedule + value: "true" + - key: CriticalAddonsOnly + operator: "Exists" # -- SPIRE agent affinity configuration affinity: {} # -- SPIRE agent nodeSelector configuration @@ -3398,8 +3485,8 @@ authentication: image: override: ~ repository: "ghcr.io/spiffe/spire-server" - tag: "1.8.4" - digest: "sha256:bf79e0a921f8b8aa92602f7ea335616e72f7e91f939848e7ccc52d5bddfe96a1" + tag: "1.8.5" + digest: "sha256:28269265882048dcf0fed32fe47663cd98613727210b8d1a55618826f9bf5428" useDigest: true pullPolicy: "IfNotPresent" # -- SPIRE server service account diff --git a/internal/constellation/helm/charts/cilium/values.yaml.tmpl b/internal/constellation/helm/charts/cilium/values.yaml.tmpl index 92a7ad759..dff8612a2 100644 --- a/internal/constellation/helm/charts/cilium/values.yaml.tmpl +++ b/internal/constellation/helm/charts/cilium/values.yaml.tmpl @@ -215,8 +215,10 @@ extraConfig: {} annotations: {} # -- Security Context for cilium-agent pods. -podSecurityContext: {} - +podSecurityContext: + # -- AppArmorProfile options for the `cilium-agent` and init containers + appArmorProfile: + type: "Unconfined" # -- Annotations to be added to agent pods podAnnotations: {} @@ -233,6 +235,9 @@ resources: {} # cpu: 100m # memory: 512Mi +# -- resources & limits for the agent init containers +initResources: {} + securityContext: # -- User to run the pod with # runAsUser: 0 @@ -462,7 +467,17 @@ bpf: # @default -- `524288` neighMax: ~ + # @schema + # type: [null, integer] + # @schema + # @default -- `16384` + # -- (int) Configures the maximum number of entries for the node table. + nodeMapMax: ~ + # -- Configure the maximum number of entries in endpoint policy map (per endpoint). + # @schema + # type: [null, integer] + # @schema policyMapMax: 16384 # -- (float64) Configure auto-sizing for all BPF maps based on available memory. @@ -800,17 +815,21 @@ encryption: # This option is only effective when encryption.type is set to "wireguard". nodeEncryption: false - # -- Configure the WireGuard Pod2Pod strict mode. + # -- Configure the WireGuard strict mode. strictMode: - # -- Enable WireGuard Pod2Pod strict mode. + # -- Enable WireGuard strict mode. enabled: false - # -- CIDR for the WireGuard Pod2Pod strict mode. - cidr: "" + # -- podCIDRList for the WireGuard strict mode. + podCIDRList: [] + + # -- nodeCIDRList for the WireGuard strict mode. + nodeCIDRList: [] # -- Allow dynamic lookup of remote node identities. # This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. - allowRemoteNodeIdentities: false + # This is also required when control-plane nodes are exempted from node-to-node encryption. + allowRemoteNodeIdentities: true ipsec: # -- Name of the key file inside the Kubernetes secret configured via secretName. @@ -1289,6 +1308,12 @@ hubble: rollingUpdate: maxUnavailable: 1 + # -- Additional hubble-relay volumes. + extraVolumes: [] + + # -- Additional hubble-relay volumeMounts. + extraVolumeMounts: [] + # -- hubble-relay pod security context podSecurityContext: fsGroup: 65532 @@ -2047,6 +2072,10 @@ envoy: # -- Set Envoy upstream HTTP idle connection timeout seconds. # Does not apply to connections with pending requests. Default 60s idleTimeoutDurationSeconds: 60 + # -- Number of trusted hops regarding the x-forwarded-for and related HTTP headers for the ingress L7 policy enforcement Envoy listeners. + xffNumTrustedHopsL7PolicyIngress: 0 + # -- Number of trusted hops regarding the x-forwarded-for and related HTTP headers for the egress L7 policy enforcement Envoy listeners. + xffNumTrustedHopsL7PolicyEgress: 0 # -- Envoy container image. image: @@ -2100,8 +2129,10 @@ envoy: annotations: {} # -- Security Context for cilium-envoy pods. - podSecurityContext: {} - + podSecurityContext: + # -- AppArmorProfile options for the `cilium-agent` and init containers + appArmorProfile: + type: "Unconfined" # -- Annotations to be added to envoy pods podAnnotations: {} @@ -2170,7 +2201,20 @@ envoy: labelSelector: matchLabels: k8s-app: cilium-envoy - + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + k8s-app: cilium + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: cilium.io/no-schedule + operator: NotIn + values: + - "true" # -- Node selector for cilium-envoy. nodeSelector: kubernetes.io/os: linux @@ -2191,12 +2235,16 @@ envoy: # Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy dnsPolicy: ~ + # -- Configure Cilium Envoy Prometheus options. + # Note that some of these apply to either cilium-agent or cilium-envoy. prometheus: # -- Enable prometheus metrics for cilium-envoy enabled: true serviceMonitor: # -- Enable service monitors. # This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) + # Note that this setting applies to both cilium-envoy _and_ cilium-agent + # with Envoy enabled. enabled: false # -- Labels to add to ServiceMonitor cilium-envoy labels: {} @@ -2208,18 +2256,21 @@ envoy: # service monitors configured. # namespace: "" # -- Relabeling configs for the ServiceMonitor cilium-envoy + # or for cilium-agent with Envoy configured. relabelings: - sourceLabels: - __meta_kubernetes_pod_node_name targetLabel: node replacement: ${1} # -- Metrics relabeling configs for the ServiceMonitor cilium-envoy + # or for cilium-agent with Envoy configured. metricRelabelings: ~ # -- Serve prometheus metrics for cilium-envoy on the configured port port: "9964" # -- Enable use of the remote node identity. # ref: https://docs.cilium.io/en/v1.7/install/upgrade/#configmap-remote-node-identity +# Deprecated without replacement in 1.15. To be removed in 1.16. remoteNodeIdentity: true # -- Enable resource quotas for priority classes used in the cluster. @@ -2657,6 +2708,8 @@ nodeinit: override: ~ repository: "${CILIUM_NODEINIT_REPO}" tag: "${CILIUM_NODEINIT_VERSION}" + digest: "${CILIUM_NODEINIT_DIGEST}" + useDigest: true pullPolicy: "${PULL_POLICY}" # -- The priority class to use for the nodeinit pod. @@ -2700,7 +2753,11 @@ nodeinit: # -- Labels to be added to node-init pods. podLabels: {} - + # -- Security Context for cilium-node-init pods. + podSecurityContext: + # -- AppArmorProfile options for the `cilium-node-init` and init containers + appArmorProfile: + type: "Unconfined" # -- nodeinit resource limits & requests # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ resources: @@ -2998,9 +3055,6 @@ clustermesh: # NodePort will be redirected to a local backend, regardless of whether the # destination node belongs to the local or the remote cluster. nodePort: 32379 - # -- Optional loadBalancer IP address to use with type LoadBalancer. - # loadBalancerIP: - # -- Annotations for the clustermesh-apiserver # For GKE LoadBalancer, use annotation cloud.google.com/load-balancer-type: "Internal" # For EKS LoadBalancer, use annotation service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0 @@ -3012,6 +3066,21 @@ clustermesh: # -- The internalTrafficPolicy of service used for apiserver access. internalTrafficPolicy: + # @schema + # type: [null, string] + # @schema + # -- Configure a loadBalancerClass. + # Allows to configure the loadBalancerClass on the clustermesh-apiserver + # LB service in case the Service type is set to LoadBalancer + # (requires Kubernetes 1.24+). + loadBalancerClass: ~ + # @schema + # type: [null, string] + # @schema + # -- Configure a specific loadBalancerIP. + # Allows to configure a specific loadBalancerIP on the clustermesh-apiserver + # LB service in case the Service type is set to LoadBalancer. + loadBalancerIP: ~ # -- Number of replicas run for the clustermesh-apiserver deployment. replicas: 1 @@ -3269,7 +3338,10 @@ cgroup: # memory: 128Mi # -- Configure cgroup root where cgroup2 filesystem is mounted on the host (see also: `cgroup.autoMount`) hostRoot: /run/cilium/cgroupv2 - +# -- Configure sysctl override described in #20072. +sysctlfix: + # -- Enable the sysctl override. When enabled, the init container will mount the /proc of the host so that the `sysctlfix` utility can execute. + enabled: true # -- Configure whether to enable auto detect of terminating state for endpoints # in order to support graceful termination. enableK8sTerminatingEndpoint: true @@ -3282,6 +3354,8 @@ enableK8sTerminatingEndpoint: true agentNotReadyTaintKey: "node.cilium.io/agent-not-ready" dnsProxy: + # -- Timeout (in seconds) when closing the connection between the DNS proxy and the upstream server. If set to 0, the connection is closed immediately (with TCP RST). If set to -1, the connection is closed asynchronously in the background. + socketLingerTimeout: 10 # -- DNS response code for rejecting DNS requests, available options are '[nameError refused]'. dnsRejectResponseCode: refused # -- Allow the DNS proxy to compress responses to endpoints that are larger than 512 Bytes or the EDNS0 option, if present. @@ -3303,6 +3377,8 @@ dnsProxy: proxyPort: 0 # -- The maximum time the DNS proxy holds an allowed DNS response before sending it along. Responses are sent as soon as the datapath is updated with the new IP information. proxyResponseMaxDelay: 100ms + # -- DNS proxy operation mode (true/false, or unset to use version dependent defaults) + # enableTransparentMode: true # -- SCTP Configuration Values sctp: @@ -3342,6 +3418,8 @@ authentication: enabled: true # -- SPIRE namespace to install into namespace: cilium-spire + # -- SPIRE namespace already exists. Set to true if Helm should not create, manage, and import the SPIRE namespace. + existingNamespace: false # -- init container image of SPIRE agent and server initImage: override: ~ @@ -3371,8 +3449,21 @@ authentication: # -- SPIRE Workload Attestor kubelet verification. skipKubeletVerification: true # -- SPIRE agent tolerations configuration + # By default it follows the same tolerations as the agent itself + # to allow the Cilium agent on this node to connect to SPIRE. # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ - tolerations: [] + tolerations: + - key: node.kubernetes.io/not-ready + effect: NoSchedule + - key: node-role.kubernetes.io/master + effect: NoSchedule + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + - key: node.cloudprovider.kubernetes.io/uninitialized + effect: NoSchedule + value: "true" + - key: CriticalAddonsOnly + operator: "Exists" # -- SPIRE agent affinity configuration affinity: {} # -- SPIRE agent nodeSelector configuration diff --git a/internal/constellation/helm/charts/coredns/Chart.yaml b/internal/constellation/helm/charts/coredns/Chart.yaml new file mode 100644 index 000000000..bd531acd7 --- /dev/null +++ b/internal/constellation/helm/charts/coredns/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: kube-dns +version: 0.0.0 diff --git a/internal/constellation/helm/charts/coredns/templates/clusterrole.yaml b/internal/constellation/helm/charts/coredns/templates/clusterrole.yaml new file mode 100644 index 000000000..13d284c3c --- /dev/null +++ b/internal/constellation/helm/charts/coredns/templates/clusterrole.yaml @@ -0,0 +1,23 @@ + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: system:coredns +rules: +- apiGroups: + - "" + resources: + - endpoints + - services + - pods + - namespaces + verbs: + - list + - watch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch diff --git a/internal/constellation/helm/charts/coredns/templates/clusterrolebinding.yaml b/internal/constellation/helm/charts/coredns/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..ab35291a1 --- /dev/null +++ b/internal/constellation/helm/charts/coredns/templates/clusterrolebinding.yaml @@ -0,0 +1,13 @@ + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: system:coredns +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:coredns +subjects: +- kind: ServiceAccount + name: coredns + namespace: kube-system diff --git a/internal/constellation/helm/charts/coredns/templates/configmap.yaml b/internal/constellation/helm/charts/coredns/templates/configmap.yaml new file mode 100644 index 000000000..58a48a318 --- /dev/null +++ b/internal/constellation/helm/charts/coredns/templates/configmap.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +data: + Corefile: | + .:53 { + errors + health { + lameduck 5s + } + ready + kubernetes {{ .Values.dnsDomain }} in-addr.arpa ip6.arpa { + pods insecure + fallthrough in-addr.arpa ip6.arpa + ttl 30 + } + prometheus :9153 + forward . /etc/resolv.conf { + max_concurrent 1000 + } + cache 30 + loop + reload + loadbalance + } +kind: ConfigMap +metadata: + creationTimestamp: null + name: edg-coredns + namespace: kube-system diff --git a/internal/constellation/helm/charts/coredns/templates/deployment.yaml b/internal/constellation/helm/charts/coredns/templates/deployment.yaml new file mode 100644 index 000000000..b7fd735df --- /dev/null +++ b/internal/constellation/helm/charts/coredns/templates/deployment.yaml @@ -0,0 +1,109 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + creationTimestamp: null + labels: + k8s-app: kube-dns + name: coredns + namespace: kube-system +spec: + replicas: 2 + selector: + matchLabels: + k8s-app: kube-dns + strategy: + rollingUpdate: + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + creationTimestamp: null + labels: + k8s-app: kube-dns + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: k8s-app + operator: In + values: + - kube-dns + topologyKey: kubernetes.io/hostname + weight: 100 + containers: + - args: + - -conf + - /etc/coredns/Corefile + image: '{{ .Values.image }}' + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 5 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 60 + successThreshold: 1 + timeoutSeconds: 5 + name: coredns + ports: + - containerPort: 53 + name: dns + protocol: UDP + - containerPort: 53 + name: dns-tcp + protocol: TCP + - containerPort: 9153 + name: metrics + protocol: TCP + readinessProbe: + httpGet: + path: /ready + port: 8181 + scheme: HTTP + resources: + limits: + memory: 170Mi + requests: + cpu: 100m + memory: 70Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + readOnlyRootFilesystem: true + volumeMounts: + - mountPath: /etc/coredns + name: config-volume + readOnly: true + dnsPolicy: Default + nodeSelector: + kubernetes.io/os: linux + priorityClassName: system-cluster-critical + serviceAccountName: coredns + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + - effect: NoSchedule + key: node.cloudprovider.kubernetes.io/uninitialized + value: "true" + - effect: NoExecute + key: node.kubernetes.io/unreachable + operator: Exists + tolerationSeconds: 10 + volumes: + - configMap: + items: + - key: Corefile + path: Corefile + name: edg-coredns + name: config-volume +status: {} diff --git a/internal/constellation/helm/charts/coredns/templates/service.yaml b/internal/constellation/helm/charts/coredns/templates/service.yaml new file mode 100644 index 000000000..ba243aa19 --- /dev/null +++ b/internal/constellation/helm/charts/coredns/templates/service.yaml @@ -0,0 +1,33 @@ + +apiVersion: v1 +kind: Service +metadata: + labels: + k8s-app: kube-dns + kubernetes.io/cluster-service: "true" + kubernetes.io/name: "CoreDNS" + name: kube-dns + namespace: kube-system + annotations: + prometheus.io/port: "9153" + prometheus.io/scrape: "true" + # Without this resourceVersion value, an update of the Service between versions will yield: + # Service "kube-dns" is invalid: metadata.resourceVersion: Invalid value: "": must be specified for an update + resourceVersion: "0" +spec: + clusterIP: "{{ .Values.clusterIP }}" + ports: + - name: dns + port: 53 + protocol: UDP + targetPort: 53 + - name: dns-tcp + port: 53 + protocol: TCP + targetPort: 53 + - name: metrics + port: 9153 + protocol: TCP + targetPort: 9153 + selector: + k8s-app: kube-dns diff --git a/internal/constellation/helm/charts/coredns/templates/serviceaccount.yaml b/internal/constellation/helm/charts/coredns/templates/serviceaccount.yaml new file mode 100644 index 000000000..937b99fa5 --- /dev/null +++ b/internal/constellation/helm/charts/coredns/templates/serviceaccount.yaml @@ -0,0 +1,6 @@ + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: coredns + namespace: kube-system diff --git a/internal/constellation/helm/charts/coredns/values.yaml b/internal/constellation/helm/charts/coredns/values.yaml new file mode 100644 index 000000000..9b3f72414 --- /dev/null +++ b/internal/constellation/helm/charts/coredns/values.yaml @@ -0,0 +1,3 @@ +clusterIP: 10.96.0.10 +dnsDomain: cluster.local +image: registry.k8s.io/coredns/coredns:v1.11.3@sha256:9caabbf6238b189a65d0d6e6ac138de60d6a1c419e5a341fbbb7c78382559c6e diff --git a/internal/constellation/helm/charts/edgeless/csi/Chart.yaml b/internal/constellation/helm/charts/edgeless/csi/Chart.yaml index 3fb20c87e..5301e51db 100644 --- a/internal/constellation/helm/charts/edgeless/csi/Chart.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/Chart.yaml @@ -9,11 +9,11 @@ dependencies: - name: snapshot-crds version: 6.2.2 - name: aws-csi-driver - version: 1.1.0 + version: 1.2.0 tags: - AWS - name: azuredisk-csi-driver - version: v1.3.0 + version: v1.4.0 tags: - Azure - name: cinder-config @@ -21,7 +21,7 @@ dependencies: tags: - OpenStack - name: gcp-compute-persistent-disk-csi-driver - version: 1.3.0 + version: 1.4.0 tags: - GCP - name: openstack-cinder-csi diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/CHANGELOG.md b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/CHANGELOG.md index bc6aa0036..3daf61e5e 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/CHANGELOG.md +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/CHANGELOG.md @@ -1,4 +1,120 @@ # Helm chart +## v2.30.0 +* Bump driver version to `v1.30.0` +* Update voluemessnapshotcontents/status RBAC ([#1991](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1991), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Upgrade dependencies ([#2016](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2016), [@torredil](https://github.com/torredil)) + +## v2.29.1 +* Bump driver version to `v1.29.1` +* Remove `--reuse-values` deprecation warning + +## v2.29.0 +### Urgent Upgrade Notes +*(No, really, you MUST read this before you upgrade)* + +The EBS CSI Driver Helm chart no longer supports upgrading with `--reuse-values`. This chart will not test for `--reuse-values` compatibility and upgrading with `--reuse-values` will likely fail. Users of `--reuse-values` are strongly encouraged to migrate to `--reset-then-reuse-values`. + +For more information see [the deprecation announcement](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues/1864). + +### Other Changes +* Bump driver version to `v1.29.0` and sidecars to latest versions +* Add helm-tester enabled flag ([#1954](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1954), [@nunodomingues-td](https://github.com/nunodomingues-td)) + +## v2.28.1 +* Add `reservedVolumeAttachments` that overrides heuristic-determined reserved attachments via `--reserved-volume-attachments` CLI option from [PR #1919](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1919) through Helm ([#1939](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1939), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Add `additionalArgs` parameter to node daemonSet ([#1939](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1939), [@AndrewSirenko](https://github.com/AndrewSirenko)) + +## v2.28.0 +### Urgent Upgrade Notes +*(No, really, you MUST read this before you upgrade)* + +This is the last minor version of the EBS CSI Driver Helm chart to support upgrading with `--reuse-values`. Future versions of the chart (starting with `v2.29.0`) will not test for `--reuse-values` compatibility and upgrading with `--reuse-values` will likely fail. Users of `--reuse-values` are strongly encouraged to migrate to `--reset-then-reuse-values`. + +For more information see [the deprecation announcement](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues/1864). + +### Other Changes +* Bump driver version to `v1.28.0` and sidecars to latest versions +* Add labels to leases role used by EBS CSI controller ([#1914](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1914), [@cHiv0rz](https://github.com/cHiv0rz)) +* Enforce `linux` and `amd64` node affinity for helm tester pod ([#1922](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1922), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Add configuration for `DaemonSet` annotations ([#1923](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1923), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Incorporate KubeLinter recommended best practices for chart tester pod ([#1924](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1924), [@torredil](https://github.com/torredil)) +* Add configuration for chart tester pod image ([#1928](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1928), [@AndrewSirenko](https://github.com/AndrewSirenko)) + +## v2.27.0 +* Bump driver version to `v1.27.0` +* Add parameters for tuning revisionHistoryLimit and emptyDir volumes ([#1840](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1840), [@bodgit](https://github.com/bodgit)) + +## v2.26.1 +* Bump driver version to `v1.26.1` +* Bump sidecar container versions to fix [restart bug in external attacher, provisioner, resizer, snapshotter, and node-driver-registrar](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues/1875) ([#1886](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1886), [@AndrewSirenko](https://github.com/AndrewSirenko)) + +## v2.26.0 +* Bump driver version to `v1.26.0` +* Bump sidecar container versions ([#1867](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1867), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Add warning about --reuse-values deprecation to NOTES.txt ([#1865](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1865), [@ConnorJC3](https://github.com/ConnorJC3)) + +## v2.25.0 +* Bump driver version to `v1.25.0` +* Update default sidecar timeout values ([#1824](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1824), [@torredil](https://github.com/torredil)) +* Increase default QPS and worker threads of sidecars ([#1834](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1834), [@ConnorJC3](https://github.com/ConnorJC3)) +* Node-driver-registrar sidecar fixes ([#1815](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1815), [@jukie](https://github.com/jukie)) +* Suggest eks.amazonaws.com/role-arn in values.yaml if EKS IAM for SA is used ([#1804](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1804), [@tporeba](https://github.com/tporeba)) + +## v2.24.1 +* Bump driver version to `v1.24.1` +* Upgrade sidecar images + +## v2.24.0 +* Bump driver version to `v1.24.0` +* Add additionalClusterRoleRules to sidecar chart templates. ([#1757](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1757), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Allow passing template value for clusterName ([#1753](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1753), [@monicastanciu](https://github.com/monicastanciu)) +* Make hostNetwork configurable for daemonset ([#1716](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1716), [@bseenu](https://github.com/bseenu)) +* Add labels to volumesnapshotclass ([#1754](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1754), [@fad3t](https://github.com/fad3t)) +* Update default API version for PodDisruptionBudget ([#1751](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1751), [@AndrewSirenko](https://github.com/AndrewSirenko)) + +## v2.23.2 +* Bump driver version to `v1.23.2` +* Upgrade sidecar images + +## v2.23.1 +* Bump driver version to `v1.23.1` + +## v2.23.0 +* Add `node.enableLinux` parameter ([#1732](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1732), [@monicastanciu](https://github.com/monicastanciu)) +* Additional Node DaemonSets bug fixes ([#1739](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1739), [@monicastanciu](https://github.com/monicastanciu)) +* Additional DaemonSets feature ([#1722](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1722), [@ConnorJC3](https://github.com/ConnorJC3)) +* Add doc of chart value additionalArgs ([#1697](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1697), [@zitudu](https://github.com/zitudu)) + +## v2.22.1 +* Bump driver version to `v1.22.1` + +## v2.22.0 +* Default PodDisruptionBudget to policy/v1 ([#1707](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1707), [@iNoahNothing](https://github.com/iNoahNothing)) + +## v2.21.0 +* Bump driver version to `v1.21.0` +* Enable additional volume mounts on node pods ([#1670](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1670), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* Enable customization of aws-secret name and keys in Helm Chart ([#1668](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1668), [@AndrewSirenko](https://github.com/AndrewSirenko)) +* The sidecars have been updated. The new versions are: + - csi-snapshotter: `v6.2.2` + +## v2.20.0 +* Bump driver version to `v1.20.0` +* Enable leader election in csi-resizer sidecar ([#1606](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1606), [@rdpsin](https://github.com/rdpsin)) +* Namespace-scoped leases permissions ([#1614](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1614), [@torredil](https://github.com/torredil)) +* Add additionalArgs parameter for sidecars ([#1627](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1627), [@ConnorJC3](https://github.com/ConnorJC3)) +* Avoid generating manifests with empty envFrom fields ([#1630](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1630), [@mvgmb](https://github.com/mvgmb)) +* Allow to set automountServiceAccountToken in ServiceAccount ([#1619](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1619), [@kahirokunn](https://github.com/kahirokunn)) + +## v2.19.0 +* Bump driver version to `v1.19.0` +* The sidecars have been updated. The new versions are: + - csi-provisioner: `v3.5.0` + - csi-attacher: `v4.3.0` + - livenessprobe: `v2.10.0` + - csi-resizer: `v1.8.0` + - node-driver-registrar: `v2.8.0` +* Remove CPU limits ([#1596](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1596), [@torredil](https://github.com/torredil)) ## v2.18.0 ### Urgent Upgrade Notes diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/Chart.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/Chart.yaml index fc4e85297..c439f3ef6 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/Chart.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -version: 1.1.0 -appVersion: "1.1.0" +version: 1.2.0 +appVersion: "1.2.0" description: AWS Container Storage Interface (CSI) Storage Plugin with on-node encryption support name: aws-csi-driver kubeVersion: ">=1.17.0-0" diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/NOTES.txt b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/NOTES.txt index 5d79084ec..cb3e6cecf 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/NOTES.txt +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/NOTES.txt @@ -2,4 +2,4 @@ To verify that aws-ebs-csi-driver has started, run: kubectl get pod -n {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "aws-ebs-csi-driver.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -NOTE: The [CSI Snapshotter](https://github.com/kubernetes-csi/external-snapshotter) controller and CRDs will no longer be installed as part of this chart and moving forward will be a prerequisite of using the snap shotting functionality. \ No newline at end of file +NOTE: The [CSI Snapshotter](https://github.com/kubernetes-csi/external-snapshotter) controller and CRDs will no longer be installed as part of this chart and moving forward will be a prerequisite of using the snap shotting functionality. diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/_node-windows.tpl b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/_node-windows.tpl new file mode 100644 index 000000000..ab17f71e5 --- /dev/null +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/_node-windows.tpl @@ -0,0 +1,262 @@ +{{- define "node-windows" }} +{{- if .Values.node.enableWindows }} +--- +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: {{ printf "%s-windows" .NodeName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +spec: + {{- if or (kindIs "float64" .Values.node.revisionHistoryLimit) (kindIs "int64" .Values.node.revisionHistoryLimit) }} + revisionHistoryLimit: {{ .Values.node.revisionHistoryLimit }} + {{- end }} + selector: + matchLabels: + app: {{ .NodeName }} + {{- include "aws-ebs-csi-driver.selectorLabels" . | nindent 6 }} + updateStrategy: + {{ toYaml .Values.node.updateStrategy | nindent 4 }} + template: + metadata: + labels: + app: {{ .NodeName }} + {{- include "aws-ebs-csi-driver.labels" . | nindent 8 }} + {{- if .Values.node.podLabels }} + {{- toYaml .Values.node.podLabels | nindent 8 }} + {{- end }} + {{- with .Values.node.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.node.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + nodeSelector: + kubernetes.io/os: windows + {{- with .Values.node.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Values.node.serviceAccount.name }} + priorityClassName: {{ .Values.node.priorityClassName | default "system-node-critical" }} + tolerations: + {{- if .Values.node.tolerateAllTaints }} + - operator: Exists + {{- else }} + {{- with .Values.node.tolerations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.node.windowsHostProcess }} + securityContext: + windowsOptions: + hostProcess: true + runAsUserName: "NT AUTHORITY\\SYSTEM" + hostNetwork: true + {{- end }} + containers: + - name: ebs-plugin + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.node.windowsHostProcess }} + command: + - "aws-ebs-csi-driver.exe" + {{- end }} + args: + - node + - --endpoint=$(CSI_ENDPOINT) + {{- with .Values.node.volumeAttachLimit }} + - --volume-attach-limit={{ . }} + {{- end }} + {{- with .Values.node.loggingFormat }} + - --logging-format={{ . }} + {{- end }} + - --v={{ .Values.node.logLevel }} + {{- if .Values.node.otelTracing }} + - --enable-otel-tracing=true + {{- end}} + {{- if .Values.node.windowsHostProcess }} + - --windows-host-process=true + {{- end }} + env: + - name: CSI_ENDPOINT + {{- if .Values.node.windowsHostProcess }} + value: unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock + {{- else }} + value: unix:/csi/csi.sock + {{- end }} + - name: CSI_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.node.otelTracing }} + - name: OTEL_SERVICE_NAME + value: {{ .otelServiceName }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .otelExporterEndpoint }} + {{- end }} + {{- with .Values.node.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: kubelet-dir + mountPath: C:\var\lib\kubelet + mountPropagation: "None" + - name: plugin-dir + mountPath: C:\csi + {{- if not .Values.node.windowsHostProcess }} + - name: csi-proxy-disk-pipe + mountPath: \\.\pipe\csi-proxy-disk-v1 + - name: csi-proxy-volume-pipe + mountPath: \\.\pipe\csi-proxy-volume-v1 + - name: csi-proxy-filesystem-pipe + mountPath: \\.\pipe\csi-proxy-filesystem-v1 + {{- end }} + ports: + - name: healthz + containerPort: 9808 + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 5 + {{- with .Values.node.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if not .Values.node.windowsHostProcess }} + securityContext: + windowsOptions: + runAsUserName: "ContainerAdministrator" + {{- end }} + lifecycle: + preStop: + exec: + command: ["/bin/aws-ebs-csi-driver", "pre-stop-hook"] + - name: node-driver-registrar + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.nodeDriverRegistrar.image.repository .Values.sidecars.nodeDriverRegistrar.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.nodeDriverRegistrar.image.pullPolicy }} + {{- if .Values.node.windowsHostProcess }} + command: + - "csi-node-driver-registrar.exe" + {{- end }} + args: + - --csi-address=$(ADDRESS) + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + {{- if .Values.node.windowsHostProcess }} + - --plugin-registration-path=$(PLUGIN_REG_DIR) + {{- end }} + - --v={{ .Values.sidecars.nodeDriverRegistrar.logLevel }} + env: + - name: ADDRESS + {{- if .Values.node.windowsHostProcess }} + value: unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock + {{- else }} + value: unix:/csi/csi.sock + {{- end }} + - name: DRIVER_REG_SOCK_PATH + {{- if .Values.node.windowsHostProcess }} + value: C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock + {{- else }} + value: C:\var\lib\kubelet\plugins\ebs.csi.aws.com\csi.sock + {{- end }} + {{- if .Values.node.windowsHostProcess }} + - name: PLUGIN_REG_DIR + value: C:\\var\\lib\\kubelet\\plugins_registry\\ + {{- end }} + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.nodeDriverRegistrar.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + livenessProbe: + exec: + command: + - /csi-node-driver-registrar.exe + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + - --mode=kubelet-registration-probe + initialDelaySeconds: 30 + timeoutSeconds: 15 + periodSeconds: 90 + volumeMounts: + - name: plugin-dir + mountPath: C:\csi + - name: registration-dir + mountPath: C:\registration + - name: probe-dir + mountPath: C:\var\lib\kubelet\plugins\ebs.csi.aws.com + {{- with default .Values.node.resources .Values.sidecars.nodeDriverRegistrar.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: liveness-probe + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.livenessProbe.image.pullPolicy }} + {{- if .Values.node.windowsHostProcess }} + command: + - "livenessprobe.exe" + {{- end }} + args: + {{- if .Values.node.windowsHostProcess }} + - --csi-address=unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock + {{- else }} + - --csi-address=unix:/csi/csi.sock + {{- end }} + volumeMounts: + - name: plugin-dir + mountPath: C:\csi + {{- with default .Values.node.resources .Values.sidecars.livenessProbe.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + volumes: + - name: kubelet-dir + hostPath: + path: C:\var\lib\kubelet + type: Directory + - name: plugin-dir + hostPath: + path: C:\var\lib\kubelet\plugins\ebs.csi.aws.com + type: DirectoryOrCreate + - name: registration-dir + hostPath: + path: C:\var\lib\kubelet\plugins_registry + type: Directory + {{- if not .Values.node.windowsHostProcess }} + - name: csi-proxy-disk-pipe + hostPath: + path: \\.\pipe\csi-proxy-disk-v1 + type: "" + - name: csi-proxy-volume-pipe + hostPath: + path: \\.\pipe\csi-proxy-volume-v1 + type: "" + - name: csi-proxy-filesystem-pipe + hostPath: + path: \\.\pipe\csi-proxy-filesystem-v1 + type: "" + {{- end }} + - name: probe-dir + {{- if .Values.node.probeDirVolume }} + {{- toYaml .Values.node.probeDirVolume | nindent 10 }} + {{- else }} + emptyDir: {} + {{- end }} +{{- end }} +{{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/_node.tpl b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/_node.tpl new file mode 100644 index 000000000..4591f7efe --- /dev/null +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/_node.tpl @@ -0,0 +1,250 @@ +{{- define "node" }} +{{- if or (eq (default true .Values.node.enableLinux) true) }} +--- +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: {{ .NodeName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} + {{- with .Values.node.daemonSetAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if or (kindIs "float64" .Values.node.revisionHistoryLimit) (kindIs "int64" .Values.node.revisionHistoryLimit) }} + revisionHistoryLimit: {{ .Values.node.revisionHistoryLimit }} + {{- end }} + selector: + matchLabels: + app: {{ .NodeName }} + {{- include "aws-ebs-csi-driver.selectorLabels" . | nindent 6 }} + updateStrategy: + {{- toYaml .Values.node.updateStrategy | nindent 4 }} + template: + metadata: + labels: + app: {{ .NodeName }} + {{- include "aws-ebs-csi-driver.labels" . | nindent 8 }} + {{- if .Values.node.podLabels }} + {{- toYaml .Values.node.podLabels | nindent 8 }} + {{- end }} + {{- with .Values.node.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.node.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + nodeSelector: + kubernetes.io/os: linux + {{- with .Values.node.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Values.node.serviceAccount.name }} + priorityClassName: {{ .Values.node.priorityClassName | default "system-node-critical" }} + tolerations: + {{- if .Values.node.tolerateAllTaints }} + - operator: Exists + {{- else }} + {{- with .Values.node.tolerations }} + {{- toYaml . | nindent 8 }} + {{- end }} + - key: "ebs.csi.aws.com/agent-not-ready" + operator: "Exists" + {{- end }} + hostNetwork: {{ .Values.node.hostNetwork }} + {{- with .Values.node.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: ebs-plugin + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - node + - --endpoint=$(CSI_ENDPOINT) + {{- with .Values.node.reservedVolumeAttachments }} + - --reserved-volume-attachments={{ . }} + {{- end }} + {{- with .Values.node.volumeAttachLimit }} + - --volume-attach-limit={{ . }} + {{- end }} + {{- with .Values.node.loggingFormat }} + - --logging-format={{ . }} + {{- end }} + - --v={{ .Values.node.logLevel }} + {{- if .Values.node.otelTracing }} + - --enable-otel-tracing=true + {{- end}} + {{- range .Values.node.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: CSI_ENDPOINT + value: unix:/csi/csi.sock + - name: CSI_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.node.otelTracing }} + - name: OTEL_SERVICE_NAME + value: {{ .otelServiceName }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .otelExporterEndpoint }} + {{- end }} + {{- with .Values.node.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: kubelet-dir + mountPath: {{ .Values.node.kubeletPath }} + mountPropagation: "Bidirectional" + - name: plugin-dir + mountPath: /csi + - name: device-dir + mountPath: /dev + - name: cryptsetup + mountPath: /run/cryptsetup + {{- with .Values.node.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: healthz + containerPort: 9808 + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 5 + {{- with .Values.node.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.node.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + lifecycle: + preStop: + exec: + command: ["/bin/aws-ebs-csi-driver", "pre-stop-hook"] + - name: node-driver-registrar + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.nodeDriverRegistrar.image.repository .Values.sidecars.nodeDriverRegistrar.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.nodeDriverRegistrar.image.pullPolicy }} + args: + - --csi-address=$(ADDRESS) + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + - --v={{ .Values.sidecars.nodeDriverRegistrar.logLevel }} + {{- range .Values.sidecars.nodeDriverRegistrar.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: ADDRESS + value: /csi/csi.sock + - name: DRIVER_REG_SOCK_PATH + value: {{ printf "%s/plugins/ebs.csi.aws.com/csi.sock" (trimSuffix "/" .Values.node.kubeletPath) }} + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.nodeDriverRegistrar.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.nodeDriverRegistrar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: plugin-dir + mountPath: /csi + - name: registration-dir + mountPath: /registration + - name: probe-dir + mountPath: {{ printf "%s/plugins/ebs.csi.aws.com/" (trimSuffix "/" .Values.node.kubeletPath) }} + {{- with default .Values.node.resources .Values.sidecars.nodeDriverRegistrar.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.nodeDriverRegistrar.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: liveness-probe + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.livenessProbe.image.pullPolicy }} + args: + - --csi-address=/csi/csi.sock + {{- range .Values.sidecars.livenessProbe.additionalArgs }} + - {{ . }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: plugin-dir + mountPath: /csi + {{- with default .Values.node.resources .Values.sidecars.livenessProbe.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.livenessProbe.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + volumes: + - name: kubelet-dir + hostPath: + path: {{ .Values.node.kubeletPath }} + type: Directory + - name: plugin-dir + hostPath: + path: {{ printf "%s/plugins/ebs.csi.aws.com/" (trimSuffix "/" .Values.node.kubeletPath) }} + type: DirectoryOrCreate + - name: registration-dir + hostPath: + path: {{ printf "%s/plugins_registry/" (trimSuffix "/" .Values.node.kubeletPath) }} + type: Directory + - name: device-dir + hostPath: + path: /dev + type: Directory + - name: cryptsetup + hostPath: + path: /run/cryptsetup + type: Directory + - name: probe-dir + {{- if .Values.node.probeDirVolume }} + {{- toYaml .Values.node.probeDirVolume | nindent 10 }} + {{- else }} + emptyDir: {} + {{- end }} + {{- with .Values.node.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-attacher.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-attacher.yaml index 816fdf66e..bff6577b3 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-attacher.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-attacher.yaml @@ -21,3 +21,6 @@ rules: - apiGroups: [ "storage.k8s.io" ] resources: [ "volumeattachments/status" ] verbs: [ "patch" ] + {{- with .Values.sidecars.attacher.additionalClusterRoleRules }} + {{- . | toYaml | nindent 2 }} + {{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-csi-node.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-csi-node.yaml index 3ca368efb..2b7295aaf 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-csi-node.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-csi-node.yaml @@ -8,4 +8,10 @@ metadata: rules: - apiGroups: [""] resources: ["nodes"] + verbs: ["get", "patch"] + - apiGroups: ["storage.k8s.io"] + resources: ["volumeattachments"] + verbs: ["get", "list", "watch"] + - apiGroups: ["storage.k8s.io"] + resources: ["csinodes"] verbs: ["get"] diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-provisioner.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-provisioner.yaml index 0fb7ded0f..b67c65844 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-provisioner.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-provisioner.yaml @@ -30,9 +30,12 @@ rules: - apiGroups: [ "" ] resources: [ "nodes" ] verbs: [ "get", "list", "watch" ] - - apiGroups: [ "coordination.k8s.io" ] - resources: [ "leases" ] - verbs: [ "get", "watch", "list", "delete", "update", "create" ] - apiGroups: [ "storage.k8s.io" ] resources: [ "volumeattachments" ] verbs: [ "get", "list", "watch" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "volumeattributesclasses" ] + verbs: [ "get" ] + {{- with .Values.sidecars.provisioner.additionalClusterRoleRules }} + {{- . | toYaml | nindent 2 }} + {{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-resizer.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-resizer.yaml index 065f3aba2..81858af34 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-resizer.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-resizer.yaml @@ -29,3 +29,9 @@ rules: - apiGroups: [ "" ] resources: [ "pods" ] verbs: [ "get", "list", "watch" ] + - apiGroups: [ "storage.k8s.io" ] + resources: [ "volumeattributesclasses" ] + verbs: [ "get", "list", "watch" ] + {{- with .Values.sidecars.resizer.additionalClusterRoleRules }} + {{- . | toYaml | nindent 2 }} + {{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-snapshotter.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-snapshotter.yaml index 38e688a8a..697e818d9 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-snapshotter.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/clusterrole-snapshotter.yaml @@ -24,4 +24,7 @@ rules: verbs: [ "create", "get", "list", "watch", "update", "delete", "patch" ] - apiGroups: [ "snapshot.storage.k8s.io" ] resources: [ "volumesnapshotcontents/status" ] - verbs: [ "update" ] + verbs: [ "update", "patch" ] + {{- with .Values.sidecars.snapshotter.additionalClusterRoleRules }} + {{- . | toYaml | nindent 2 }} + {{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/controller.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/controller.yaml index 0d79331ac..89468b1ca 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/controller.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/controller.yaml @@ -6,8 +6,15 @@ metadata: namespace: {{ .Release.Namespace }} labels: {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} + {{- with .Values.controller.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.controller.replicaCount }} + {{- if or (kindIs "float64" .Values.controller.revisionHistoryLimit) (kindIs "int64" .Values.controller.revisionHistoryLimit) }} + revisionHistoryLimit: {{ .Values.controller.revisionHistoryLimit }} + {{- end }} {{- with .Values.controller.updateStrategy }} strategy: {{- toYaml . | nindent 4 }} @@ -26,7 +33,7 @@ spec: {{- end }} {{- if .Values.controller.podAnnotations }} annotations: - {{- toYaml .Values.controller.podAnnotations | nindent 8 }} + {{- tpl ( .Values.controller.podAnnotations | toYaml ) . | nindent 8 }} {{- end }} spec: nodeSelector: @@ -75,7 +82,7 @@ spec: {{- if .Values.controller.extraVolumeTags }} {{- include "aws-ebs-csi-driver.extra-volume-tags" . | nindent 12 }} {{- end }} - {{- with .Values.controller.k8sTagClusterId }} + {{- with (tpl (default "" .Values.controller.k8sTagClusterId) . ) }} - --k8s-tag-cluster-id={{ . }} {{- end }} {{- if and (.Values.controller.enableMetrics) (not .Values.controller.httpEndpoint) }} @@ -87,9 +94,18 @@ spec: {{- if .Values.controller.sdkDebugLog }} - --aws-sdk-debug-log=true {{- end}} + {{- if .Values.controller.batching }} + - --batching=true + {{- end}} {{- with .Values.controller.loggingFormat }} - --logging-format={{ . }} {{- end }} + {{- with .Values.controller.userAgentExtra }} + - --user-agent-extra={{ . }} + {{- end }} + {{- if .Values.controller.otelTracing }} + - --enable-otel-tracing=true + {{- end}} - --v={{ .Values.controller.logLevel }} {{- range .Values.controller.additionalArgs }} - {{ . }} @@ -101,18 +117,20 @@ spec: valueFrom: fieldRef: fieldPath: spec.nodeName + {{- with .Values.awsAccessSecret }} - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: - name: aws-secret - key: key_id + name: {{ .name }} + key: {{ .keyId }} optional: true - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: - name: aws-secret - key: access_key + name: {{ .name }} + key: {{ .accessKey }} optional: true + {{- end }} - name: AWS_EC2_ENDPOINT valueFrom: configMapKeyRef: @@ -129,10 +147,16 @@ spec: {{- with .Values.controller.env }} {{- . | toYaml | nindent 12 }} {{- end }} - envFrom: - {{- with .Values.controller.envFrom }} - {{- . | toYaml | nindent 12 }} + {{- with .Values.controller.otelTracing }} + - name: OTEL_SERVICE_NAME + value: {{ .otelServiceName }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .otelExporterEndpoint }} {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ @@ -176,6 +200,9 @@ spec: image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.provisioner.image.repository .Values.sidecars.provisioner.image.tag }} imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.provisioner.image.pullPolicy }} args: + {{- if not (regexMatch "(-timeout)" (join " " .Values.sidecars.provisioner.additionalArgs)) }} + - --timeout=60s + {{- end }} - --csi-address=$(ADDRESS) - --v={{ .Values.sidecars.provisioner.logLevel }} - --feature-gates=Topology=true @@ -195,6 +222,14 @@ spec: {{- end }} {{- end }} - --default-fstype={{ .Values.controller.defaultFsType }} + {{- if not (regexMatch "(-kube-api-qps)|(-kube-api-burst)|(-worker-threads)" (join " " .Values.sidecars.provisioner.additionalArgs)) }} + - --kube-api-qps=20 + - --kube-api-burst=100 + - --worker-threads=100 + {{- end }} + {{- range .Values.sidecars.provisioner.additionalArgs }} + - {{ . }} + {{- end }} env: - name: ADDRESS value: /var/lib/csi/sockets/pluginproxy/csi.sock @@ -204,10 +239,10 @@ spec: {{- with .Values.sidecars.provisioner.env }} {{- . | toYaml | nindent 12 }} {{- end }} + {{- with .Values.controller.envFrom }} envFrom: - {{- with .Values.controller.envFrom }} {{- . | toYaml | nindent 12 }} - {{- end }} + {{- end }} volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ @@ -223,6 +258,9 @@ spec: image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.attacher.image.repository .Values.sidecars.attacher.image.tag }} imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.attacher.image.pullPolicy }} args: + {{- if not (regexMatch "(-timeout)" (join " " .Values.sidecars.attacher.additionalArgs)) }} + - --timeout=60s + {{- end }} - --csi-address=$(ADDRESS) - --v={{ .Values.sidecars.attacher.logLevel }} - --leader-election={{ .Values.sidecars.attacher.leaderElection.enabled | required "leader election state for csi-attacher is required, must be set to true || false." }} @@ -237,6 +275,14 @@ spec: - --leader-election-retry-period={{ .Values.sidecars.attacher.leaderElection.retryPeriod }} {{- end }} {{- end }} + {{- if not (regexMatch "(-kube-api-qps)|(-kube-api-burst)|(-worker-threads)" (join " " .Values.sidecars.attacher.additionalArgs)) }} + - --kube-api-qps=20 + - --kube-api-burst=100 + - --worker-threads=100 + {{- end }} + {{- range .Values.sidecars.attacher.additionalArgs }} + - {{ . }} + {{- end }} env: - name: ADDRESS value: /var/lib/csi/sockets/pluginproxy/csi.sock @@ -246,10 +292,10 @@ spec: {{- with .Values.sidecars.attacher.env }} {{- . | toYaml | nindent 12 }} {{- end }} + {{- with .Values.controller.envFrom }} envFrom: - {{- with .Values.controller.envFrom }} {{- . | toYaml | nindent 12 }} - {{- end }} + {{- end }} volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ @@ -271,6 +317,14 @@ spec: {{- if .Values.controller.extraCreateMetadata }} - --extra-create-metadata {{- end}} + {{- if not (regexMatch "(-kube-api-qps)|(-kube-api-burst)|(-worker-threads)" (join " " .Values.sidecars.snapshotter.additionalArgs)) }} + - --kube-api-qps=20 + - --kube-api-burst=100 + - --worker-threads=100 + {{- end }} + {{- range .Values.sidecars.snapshotter.additionalArgs }} + - {{ . }} + {{- end }} env: - name: ADDRESS value: /var/lib/csi/sockets/pluginproxy/csi.sock @@ -280,10 +334,10 @@ spec: {{- with .Values.sidecars.snapshotter.env }} {{- . | toYaml | nindent 12 }} {{- end }} + {{- with .Values.controller.envFrom }} envFrom: - {{- with .Values.controller.envFrom }} {{- . | toYaml | nindent 12 }} - {{- end }} + {{- end }} volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ @@ -296,13 +350,94 @@ spec: {{- toYaml . | nindent 12 }} {{- end }} {{- end }} + {{- if (.Values.controller.volumeModificationFeature).enabled }} + - name: volumemodifier + image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.volumemodifier.image.repository .Values.sidecars.volumemodifier.image.tag }} + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.volumemodifier.image.pullPolicy }} + args: + {{- if not (regexMatch "(-timeout)" (join " " .Values.sidecars.volumemodifier.additionalArgs)) }} + - --timeout=60s + {{- end }} + - --csi-address=$(ADDRESS) + - --v={{ .Values.sidecars.volumemodifier.logLevel }} + - --leader-election={{ .Values.sidecars.volumemodifier.leaderElection.enabled | required "leader election state for csi-volumemodifier is required, must be set to true || false." }} + {{- if .Values.sidecars.volumemodifier.leaderElection.enabled }} + {{- if .Values.sidecars.volumemodifier.leaderElection.leaseDuration }} + - --leader-election-lease-duration={{ .Values.sidecars.volumemodifier.leaderElection.leaseDuration }} + {{- end }} + {{- if .Values.sidecars.volumemodifier.leaderElection.renewDeadline}} + - --leader-election-renew-deadline={{ .Values.sidecars.volumemodifier.leaderElection.renewDeadline }} + {{- end }} + {{- if .Values.sidecars.volumemodifier.leaderElection.retryPeriod }} + - --leader-election-retry-period={{ .Values.sidecars.volumemodifier.leaderElection.retryPeriod }} + {{- end }} + {{- end }} + {{- range .Values.sidecars.volumemodifier.additionalArgs }} + - {{ . }} + {{- end }} + env: + - name: ADDRESS + value: /var/lib/csi/sockets/pluginproxy/csi.sock + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.proxy.http_proxy }} + {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.volumemodifier.env }} + {{- . | toYaml | nindent 12 }} + {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: socket-dir + mountPath: /var/lib/csi/sockets/pluginproxy/ + {{- with default .Values.controller.resources .Values.sidecars.volumemodifier.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.sidecars.volumemodifier.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} - name: csi-resizer image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.resizer.image.repository .Values.sidecars.resizer.image.tag }} imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.resizer.image.pullPolicy }} args: + {{- if not (regexMatch "(-timeout)" (join " " .Values.sidecars.resizer.additionalArgs)) }} + - --timeout=60s + {{- end }} - --csi-address=$(ADDRESS) - --v={{ .Values.sidecars.resizer.logLevel }} - --handle-volume-inuse-error=false + {{- with .Values.sidecars.resizer.leaderElection }} + - --leader-election={{ .enabled | default true }} + {{- if .leaseDuration }} + - --leader-election-lease-duration={{ .leaseDuration }} + {{- end }} + {{- if .renewDeadline }} + - --leader-election-renew-deadline={{ .renewDeadline }} + {{- end }} + {{- if .retryPeriod }} + - --leader-election-retry-period={{ .retryPeriod }} + {{- end }} + {{- end }} + {{- if not (regexMatch "(-kube-api-qps)|(-kube-api-burst)|(-workers)" (join " " .Values.sidecars.resizer.additionalArgs)) }} + - --kube-api-qps=20 + - --kube-api-burst=100 + - --workers=100 + {{- end }} + {{- range .Values.sidecars.resizer.additionalArgs }} + - {{ . }} + {{- end }} env: - name: ADDRESS value: /var/lib/csi/sockets/pluginproxy/csi.sock @@ -312,10 +447,10 @@ spec: {{- with .Values.sidecars.resizer.env }} {{- . | toYaml | nindent 12 }} {{- end }} + {{- with .Values.controller.envFrom }} envFrom: - {{- with .Values.controller.envFrom }} {{- . | toYaml | nindent 12 }} - {{- end }} + {{- end }} volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ @@ -332,10 +467,13 @@ spec: imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.livenessProbe.image.pullPolicy }} args: - --csi-address=/csi/csi.sock - envFrom: - {{- with .Values.controller.envFrom }} - {{- . | toYaml | nindent 12 }} + {{- range .Values.sidecars.livenessProbe.additionalArgs }} + - {{ . }} {{- end }} + {{- with .Values.controller.envFrom }} + envFrom: + {{- . | toYaml | nindent 12 }} + {{- end }} volumeMounts: - name: socket-dir mountPath: /csi @@ -355,7 +493,15 @@ spec: {{- end }} volumes: - name: socket-dir + {{- if .Values.controller.socketDirVolume }} + {{- toYaml .Values.controller.socketDirVolume | nindent 10 }} + {{- else }} emptyDir: {} + {{- end }} {{- with .Values.controller.volumes }} {{- toYaml . | nindent 8 }} {{- end }} + {{- if .Values.controller.dnsConfig }} + dnsConfig: + {{- toYaml .Values.controller.dnsConfig | nindent 4 }} + {{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/ebs-csi-default-sc.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/ebs-csi-default-sc.yaml new file mode 100644 index 000000000..a58595726 --- /dev/null +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/ebs-csi-default-sc.yaml @@ -0,0 +1,11 @@ +{{- if .Values.defaultStorageClass.enabled }} +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: ebs-csi-default-sc + annotations: + storageclass.kubernetes.io/is-default-class: "true" +provisioner: ebs.csi.aws.com +volumeBindingMode: WaitForFirstConsumer +allowVolumeExpansion: true +{{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/metrics.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/metrics.yaml index 1dcdf4ddc..d68bd7ab9 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/metrics.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/metrics.yaml @@ -37,6 +37,6 @@ spec: endpoints: - targetPort: 3301 path: /metrics - interval: 15s + interval: {{ .Values.controller.serviceMonitor.interval | default "15s"}} {{- end }} {{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/node-windows.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/node-windows.yaml index 921b51cfb..9a2c2c81a 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/node-windows.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/node-windows.yaml @@ -1,184 +1,13 @@ -{{- if .Values.node.enableWindows }} -kind: DaemonSet -apiVersion: apps/v1 -metadata: - name: ebs-csi-node-windows - namespace: {{ .Release.Namespace }} - labels: - {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} -spec: - selector: - matchLabels: - app: ebs-csi-node - {{- include "aws-ebs-csi-driver.selectorLabels" . | nindent 6 }} - updateStrategy: - {{ toYaml .Values.node.updateStrategy | nindent 4 }} - template: - metadata: - labels: - app: ebs-csi-node - {{- include "aws-ebs-csi-driver.labels" . | nindent 8 }} - {{- if .Values.node.podLabels }} - {{- toYaml .Values.node.podLabels | nindent 8 }} - {{- end }} - {{- with .Values.node.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- with .Values.node.affinity }} - affinity: {{- toYaml . | nindent 8 }} - {{- end }} - nodeSelector: - kubernetes.io/os: windows - {{- with .Values.node.nodeSelector }} - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ .Values.node.serviceAccount.name }} - priorityClassName: {{ .Values.node.priorityClassName | default "system-node-critical" }} - tolerations: - {{- if .Values.node.tolerateAllTaints }} - - operator: Exists - {{- else }} - {{- with .Values.node.tolerations }} - {{- toYaml . | nindent 8 }} - {{- end }} - {{- end }} - containers: - - name: ebs-plugin - image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }} - imagePullPolicy: {{ .Values.image.pullPolicy }} - args: - - node - - --endpoint=$(CSI_ENDPOINT) - {{- with .Values.node.volumeAttachLimit }} - - --volume-attach-limit={{ . }} - {{- end }} - {{- with .Values.node.loggingFormat }} - - --logging-format={{ . }} - {{- end }} - - --v={{ .Values.node.logLevel }} - env: - - name: CSI_ENDPOINT - value: unix:/csi/csi.sock - - name: CSI_NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - {{- if .Values.proxy.http_proxy }} - {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} - {{- end }} - {{- with .Values.node.env }} - {{- . | toYaml | nindent 12 }} - {{- end }} - volumeMounts: - - name: kubelet-dir - mountPath: C:\var\lib\kubelet - mountPropagation: "None" - - name: plugin-dir - mountPath: C:\csi - - name: csi-proxy-disk-pipe - mountPath: \\.\pipe\csi-proxy-disk-v1 - - name: csi-proxy-volume-pipe - mountPath: \\.\pipe\csi-proxy-volume-v1 - - name: csi-proxy-filesystem-pipe - mountPath: \\.\pipe\csi-proxy-filesystem-v1 - ports: - - name: healthz - containerPort: 9808 - protocol: TCP - livenessProbe: - httpGet: - path: /healthz - port: healthz - initialDelaySeconds: 10 - timeoutSeconds: 3 - periodSeconds: 10 - failureThreshold: 5 - {{- with .Values.node.resources }} - resources: - {{- toYaml . | nindent 12 }} - {{- end }} - - name: node-driver-registrar - image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.nodeDriverRegistrar.image.repository .Values.sidecars.nodeDriverRegistrar.image.tag }} - imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.nodeDriverRegistrar.image.pullPolicy }} - args: - - --csi-address=$(ADDRESS) - - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) - - --v={{ .Values.sidecars.nodeDriverRegistrar.logLevel }} - env: - - name: ADDRESS - value: unix:/csi/csi.sock - - name: DRIVER_REG_SOCK_PATH - value: C:\var\lib\kubelet\plugins\aws.csi.confidential.cloud\csi.sock - {{- if .Values.proxy.http_proxy }} - {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} - {{- end }} - {{- with .Values.sidecars.nodeDriverRegistrar.env }} - {{- . | toYaml | nindent 12 }} - {{- end }} - livenessProbe: - exec: - command: - - /csi-node-driver-registrar.exe - - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) - - --mode=kubelet-registration-probe - initialDelaySeconds: 30 - timeoutSeconds: 15 - volumeMounts: - - name: plugin-dir - mountPath: C:\csi - - name: registration-dir - mountPath: C:\registration - - name: probe-dir - mountPath: C:\var\lib\kubelet\plugins\aws.csi.confidential.cloud - {{- with default .Values.node.resources .Values.sidecars.nodeDriverRegistrar.resources }} - resources: - {{- toYaml . | nindent 12 }} - {{- end }} - - name: liveness-probe - image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} - imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.livenessProbe.image.pullPolicy }} - args: - - --csi-address=unix:/csi/csi.sock - volumeMounts: - - name: plugin-dir - mountPath: C:\csi - {{- with default .Values.node.resources .Values.sidecars.livenessProbe.resources }} - resources: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- range .Values.imagePullSecrets }} - - name: {{ . }} - {{- end }} - {{- end }} - volumes: - - name: kubelet-dir - hostPath: - path: C:\var\lib\kubelet - type: Directory - - name: plugin-dir - hostPath: - path: C:\var\lib\kubelet\plugins\aws.csi.confidential.cloud - type: DirectoryOrCreate - - name: registration-dir - hostPath: - path: C:\var\lib\kubelet\plugins_registry - type: Directory - - name: csi-proxy-disk-pipe - hostPath: - path: \\.\pipe\csi-proxy-disk-v1 - type: "" - - name: csi-proxy-volume-pipe - hostPath: - path: \\.\pipe\csi-proxy-volume-v1 - type: "" - - name: csi-proxy-filesystem-pipe - hostPath: - path: \\.\pipe\csi-proxy-filesystem-v1 - type: "" - - name: probe-dir - emptyDir: {} +{{$defaultArgs := dict + "NodeName" "ebs-csi-node" +}} +{{- include "node-windows" (deepCopy $ | mustMerge $defaultArgs) -}} +{{- range $name, $values := .Values.additionalDaemonSets }} +{{$args := dict + "NodeName" (printf "ebs-csi-node-%s" $name) + "Values" (dict + "node" (deepCopy $.Values.node | mustMerge $values) + ) +}} +{{- include "node-windows" (deepCopy $ | mustMerge $args) -}} {{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/node.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/node.yaml index ecc6412d8..a891513b6 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/node.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/node.yaml @@ -1,206 +1,46 @@ -# Node Service -kind: DaemonSet -apiVersion: apps/v1 -metadata: - name: ebs-csi-node - namespace: {{ .Release.Namespace }} - labels: - {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} -spec: - selector: - matchLabels: - app: ebs-csi-node - {{- include "aws-ebs-csi-driver.selectorLabels" . | nindent 6 }} - updateStrategy: - {{- toYaml .Values.node.updateStrategy | nindent 4 }} - template: - metadata: - labels: - app: ebs-csi-node - {{- include "aws-ebs-csi-driver.labels" . | nindent 8 }} - {{- if .Values.node.podLabels }} - {{- toYaml .Values.node.podLabels | nindent 8 }} - {{- end }} - {{- with .Values.node.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- with .Values.node.affinity }} - affinity: {{- toYaml . | nindent 8 }} - {{- end }} - nodeSelector: - kubernetes.io/os: linux - {{- with .Values.node.nodeSelector }} - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ .Values.node.serviceAccount.name }} - priorityClassName: {{ .Values.node.priorityClassName | default "system-node-critical" }} - tolerations: - {{- if .Values.node.tolerateAllTaints }} - - operator: Exists - {{- else }} - {{- with .Values.node.tolerations }} - {{- toYaml . | nindent 8 }} - {{- end }} - {{- end }} - {{- with .Values.node.securityContext }} - securityContext: - {{- toYaml . | nindent 8 }} - {{- end }} - containers: - - name: ebs-plugin - image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }} - imagePullPolicy: {{ .Values.image.pullPolicy }} - args: - - node - - --endpoint=$(CSI_ENDPOINT) - {{- with .Values.node.volumeAttachLimit }} - - --volume-attach-limit={{ . }} - {{- end }} - {{- with .Values.node.loggingFormat }} - - --logging-format={{ . }} - {{- end }} - - "--kms-addr={{ .Values.kms.keyServiceName }}.{{ .Values.kms.keyServiceNamespace | default .Release.Namespace }}:{{ .Values.kms.keyServicePort }}" - - --v={{ .Values.node.logLevel }} - env: - - name: CSI_ENDPOINT - value: unix:/csi/csi.sock - - name: CSI_NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - {{- if .Values.proxy.http_proxy }} - {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} - {{- end }} - {{- with .Values.node.env }} - {{- . | toYaml | nindent 12 }} - {{- end }} - envFrom: - {{- with .Values.controller.envFrom }} - {{- . | toYaml | nindent 12 }} - {{- end }} - volumeMounts: - - name: kubelet-dir - mountPath: {{ .Values.node.kubeletPath }} - mountPropagation: "Bidirectional" - - name: plugin-dir - mountPath: /csi - - name: device-dir - mountPath: /dev - - name: cryptsetup - mountPath: /run/cryptsetup - ports: - - name: healthz - containerPort: 9808 - protocol: TCP - livenessProbe: - httpGet: - path: /healthz - port: healthz - initialDelaySeconds: 10 - timeoutSeconds: 3 - periodSeconds: 10 - failureThreshold: 5 - {{- with .Values.node.resources }} - resources: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.node.containerSecurityContext }} - securityContext: - {{- toYaml . | nindent 12 }} - {{- end }} - - name: node-driver-registrar - image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.nodeDriverRegistrar.image.repository .Values.sidecars.nodeDriverRegistrar.image.tag }} - imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.nodeDriverRegistrar.image.pullPolicy }} - args: - - --csi-address=$(ADDRESS) - - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) - - --v={{ .Values.sidecars.nodeDriverRegistrar.logLevel }} - env: - - name: ADDRESS - value: /csi/csi.sock - - name: DRIVER_REG_SOCK_PATH - value: {{ printf "%s/plugins/aws.csi.confidential.cloud/csi.sock" (trimSuffix "/" .Values.node.kubeletPath) }} - {{- if .Values.proxy.http_proxy }} - {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }} - {{- end }} - {{- with .Values.sidecars.nodeDriverRegistrar.env }} - {{- . | toYaml | nindent 12 }} - {{- end }} - envFrom: - {{- with .Values.controller.envFrom }} - {{- . | toYaml | nindent 12 }} - {{- end }} - livenessProbe: - exec: - command: - - /csi-node-driver-registrar - - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) - - --mode=kubelet-registration-probe - initialDelaySeconds: 30 - timeoutSeconds: 15 - volumeMounts: - - name: plugin-dir - mountPath: /csi - - name: registration-dir - mountPath: /registration - - name: probe-dir - mountPath: {{ printf "%s/plugins/aws.csi.confidential.cloud/" (trimSuffix "/" .Values.node.kubeletPath) }} - {{- with default .Values.node.resources .Values.sidecars.nodeDriverRegistrar.resources }} - resources: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.sidecars.nodeDriverRegistrar.securityContext }} - securityContext: - {{- toYaml . | nindent 12 }} - {{- end }} - - name: liveness-probe - image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }} - imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.livenessProbe.image.pullPolicy }} - args: - - --csi-address=/csi/csi.sock - envFrom: - {{- with .Values.controller.envFrom }} - {{- . | toYaml | nindent 12 }} - {{- end }} - volumeMounts: - - name: plugin-dir - mountPath: /csi - {{- with default .Values.node.resources .Values.sidecars.livenessProbe.resources }} - resources: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.sidecars.livenessProbe.securityContext }} - securityContext: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- range .Values.imagePullSecrets }} - - name: {{ . }} - {{- end }} - {{- end }} - volumes: - - name: kubelet-dir - hostPath: - path: {{ .Values.node.kubeletPath }} - type: Directory - - name: plugin-dir - hostPath: - path: {{ printf "%s/plugins/aws.csi.confidential.cloud/" (trimSuffix "/" .Values.node.kubeletPath) }} - type: DirectoryOrCreate - - name: registration-dir - hostPath: - path: {{ printf "%s/plugins_registry/" (trimSuffix "/" .Values.node.kubeletPath) }} - type: Directory - - name: device-dir - hostPath: - path: /dev - type: Directory - - name: probe-dir - emptyDir: {} - - name: cryptsetup - hostPath: - path: /run/cryptsetup - type: Directory +{{$defaultArgs := dict + "NodeName" "ebs-csi-node" +}} +{{- include "node" (deepCopy $ | mustMerge $defaultArgs) -}} +{{- range $name, $values := .Values.additionalDaemonSets }} +{{$args := dict + "NodeName" (printf "ebs-csi-node-%s" $name) + "Values" (dict + "node" (deepCopy $.Values.node | mustMerge $values) + ) +}} +{{- include "node" (deepCopy $ | mustMerge $args) -}} +{{- end }} +{{- if .Values.a1CompatibilityDaemonSet }} +{{$args := dict + "NodeName" "ebs-csi-node-a1compat" + "Values" (dict + "image" (dict + "tag" (printf "%s-a1compat" (default (printf "v%s" .Chart.AppVersion) (.Values.image.tag | toString))) + ) + "node" (dict + "affinity" (dict + "nodeAffinity" (dict + "requiredDuringSchedulingIgnoredDuringExecution" (dict + "nodeSelectorTerms" (list + (dict "matchExpressions" (list + (dict + "key" "eks.amazonaws.com/compute-type" + "operator" "NotIn" + "values" (list "fargate") + ) + (dict + "key" "node.kubernetes.io/instance-type" + "operator" "In" + "values" (list "a1.medium" "a1.large" "a1.xlarge" "a1.2xlarge" "a1.4xlarge") + ) + )) + ) + ) + ) + ) + ) + ) +}} +{{- include "node" (deepCopy $ | mustMerge $args) -}} +{{- end }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/poddisruptionbudget-controller.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/poddisruptionbudget-controller.yaml index 6f73fa222..0a1e97cc0 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/poddisruptionbudget-controller.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/poddisruptionbudget-controller.yaml @@ -1,8 +1,4 @@ -{{- if .Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} apiVersion: policy/v1 -{{- else }} -apiVersion: policy/v1beta1 -{{- end }} kind: PodDisruptionBudget metadata: name: ebs-csi-controller diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/role-leases.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/role-leases.yaml new file mode 100644 index 000000000..1ec62bb49 --- /dev/null +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/role-leases.yaml @@ -0,0 +1,11 @@ +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + namespace: {{ .Release.Namespace }} + name: ebs-csi-leases-role + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +rules: +- apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "watch", "list", "delete", "update", "create"] diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/rolebinding-leases.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/rolebinding-leases.yaml new file mode 100644 index 000000000..88fded8a3 --- /dev/null +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/rolebinding-leases.yaml @@ -0,0 +1,15 @@ +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ebs-csi-leases-rolebinding + namespace: {{ .Release.Namespace }} + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +subjects: +- kind: ServiceAccount + name: {{ .Values.controller.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: ebs-csi-leases-role + apiGroup: rbac.authorization.k8s.io diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/serviceaccount-csi-controller.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/serviceaccount-csi-controller.yaml index a5b1102b4..d819f5493 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/serviceaccount-csi-controller.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/serviceaccount-csi-controller.yaml @@ -15,4 +15,7 @@ metadata: #annotations: # eks.amazonaws.com/role-arn: arn::iam:::role/ebs-csi-role {{- end }} +{{- if .Values.controller.serviceAccount.automountServiceAccountToken }} +automountServiceAccountToken: {{ .Values.controller.serviceAccount.automountServiceAccountToken }} +{{- end }} {{- end -}} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/serviceaccount-csi-node.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/serviceaccount-csi-node.yaml index fb85abedf..9f3c7c7e1 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/serviceaccount-csi-node.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/serviceaccount-csi-node.yaml @@ -10,4 +10,7 @@ metadata: annotations: {{- toYaml . | nindent 4 }} {{- end }} +{{- if .Values.node.serviceAccount.automountServiceAccountToken }} +automountServiceAccountToken: {{ .Values.node.serviceAccount.automountServiceAccountToken }} +{{- end }} {{- end -}} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/volumesnapshotclass.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/volumesnapshotclass.yaml index 0db3046aa..59551898e 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/volumesnapshotclass.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/templates/volumesnapshotclass.yaml @@ -8,6 +8,9 @@ metadata: {{- with .annotations }} annotations: {{- . | toYaml | trim | nindent 4 }} {{- end }} + {{- with .labels }} + labels: {{- . | toYaml | trim | nindent 4 }} + {{- end }} driver: aws.csi.confidential.cloud deletionPolicy: {{ .deletionPolicy }} {{- with .parameters }} diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/values.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/values.yaml index defdd4d83..0c4a68857 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/values.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/aws-csi-driver/values.yaml @@ -5,7 +5,7 @@ image: repository: ghcr.io/edgelesssys/constellation/aws-csi-driver # Overrides the image tag whose default is v{{ .Chart.AppVersion }} - tag: "v1.1.0@sha256:3e2c394f2397455516948efcc9a4b87cbaeabf14df31702d5905ce08a53995f2" + tag: "v1.2.0@sha256:9477e8ed37989c46963d57d24de5ddbc7ab965b1685d709d06c1ae536b23b5b1" pullPolicy: Always # -- Custom labels to add into metadata @@ -24,8 +24,12 @@ sidecars: image: pullPolicy: IfNotPresent repository: public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner - tag: "v3.4.1-eks-1-26-7@sha256:adfcb04433d1824f62dde0365877d0f7b7a2eaebc45670cbab7e0c1f07ba0607" + tag: "v4.0.1-eks-1-30-4@sha256:0cf0d02211632c6b947f110e9f3f13f782eea1cfb7b990191d78ad032b2c2d77" logLevel: 2 + # Additional parameters provided by external-provisioner. + additionalArgs: [] + # Grant additional permissions to external-provisioner + additionalClusterRoleRules: resources: {} # Tune leader lease election for csi-provisioner. # Leader election is on by default. @@ -45,7 +49,7 @@ sidecars: image: pullPolicy: IfNotPresent repository: public.ecr.aws/eks-distro/kubernetes-csi/external-attacher - tag: "v4.2.0-eks-1-26-7@sha256:4b0d6e8758a0213ec942381b9577d2b3e971b545dc9e3fb59973f7992763d85f" + tag: "v4.5.1-eks-1-30-4@sha256:d68034351f65101d2a8506a5c583c5c923238aa93ba9719e779c0eb6a4b33993" # Tune leader lease election for csi-attacher. # Leader election is on by default. leaderElection: @@ -57,6 +61,10 @@ sidecars: # renewDeadline: "10s" # retryPeriod: "5s" logLevel: 2 + # Additional parameters provided by external-attacher. + additionalArgs: [] + # Grant additional permissions to external-attacher + additionalClusterRoleRules: [] resources: {} securityContext: readOnlyRootFilesystem: true @@ -68,8 +76,12 @@ sidecars: image: pullPolicy: IfNotPresent repository: public.ecr.aws/eks-distro/kubernetes-csi/external-snapshotter/csi-snapshotter - tag: "v6.2.1-eks-1-26-7@sha256:b8071f45885f1838387edb04a1d164680dcec8d656de682624ddc59d30ba660b" + tag: "v7.0.2-eks-1-30-4@sha256:9a33488c2cd691d4df454fbc0118e532cbd8aacf99856bdf395507fdae2421dc" logLevel: 2 + # Additional parameters provided by csi-snapshotter. + additionalArgs: [] + # Grant additional permissions to csi-snapshotter + additionalClusterRoleRules: [] resources: {} securityContext: readOnlyRootFilesystem: true @@ -78,7 +90,9 @@ sidecars: image: pullPolicy: IfNotPresent repository: public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe - tag: "v2.9.0-eks-1-26-7@sha256:d9e11b42ae5f4f2f7ea9034e68040997cdbb04ae9e188aa897f76ae92698d78a" + tag: "v2.12.0-eks-1-30-4@sha256:665d64a8e1124ecd95e08626ddd140154be30a95c6574d423d66cf262d28cc9c" + # Additional parameters provided by livenessprobe. + additionalArgs: [] resources: {} securityContext: readOnlyRootFilesystem: true @@ -88,8 +102,22 @@ sidecars: image: pullPolicy: IfNotPresent repository: public.ecr.aws/eks-distro/kubernetes-csi/external-resizer - tag: "v1.7.0-eks-1-26-7@sha256:81672f19d1da5cdff8d2068d8d69776067a1e5c31537ab3282d95dff34d581b6" + tag: "v1.10.1-eks-1-30-4@sha256:2aef6bf851fc3fa8e03c7a3efc9d3adb2ae1cb1746f88fb8a7559f8ca44bf188" + # Tune leader lease election for csi-resizer. + # Leader election is on by default. + leaderElection: + enabled: true + # Optional values to tune lease behavior. + # The arguments provided must be in an acceptable time.ParseDuration format. + # Ref: https://pkg.go.dev/flag#Duration + # leaseDuration: "15s" + # renewDeadline: "10s" + # retryPeriod: "5s" logLevel: 2 + # Additional parameters provided by external-resizer. + additionalArgs: [] + # Grant additional permissions to external-resizer + additionalClusterRoleRules: [] resources: {} securityContext: readOnlyRootFilesystem: true @@ -99,8 +127,40 @@ sidecars: image: pullPolicy: IfNotPresent repository: public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar - tag: "v2.7.0-eks-1-26-7@sha256:6ad0cae2ae91453f283a44e9b430e475b8a9fa3d606aec9a8b09596fffbcd2c9" + tag: "v2.10.1-eks-1-30-4@sha256:518ed9cba6258735a25d2b896dc65d34a41e22f6785550a7e24e2f2dbd6a48b5" logLevel: 2 + # Additional parameters provided by node-driver-registrar. + additionalArgs: [] + resources: {} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + livenessProbe: + exec: + command: + - /csi-node-driver-registrar + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + - --mode=kubelet-registration-probe + initialDelaySeconds: 30 + periodSeconds: 90 + timeoutSeconds: 15 + volumemodifier: + env: [] + image: + pullPolicy: IfNotPresent + repository: public.ecr.aws/ebs-csi-driver/volume-modifier-for-k8s + tag: "v0.3.0@sha256:c9e4e64e721b8fea4ba34502ac9f8fb83bd1571117276f553ac4595e0c5a3bf8" + leaderElection: + enabled: true + # Optional values to tune lease behavior. + # The arguments provided must be in an acceptable time.ParseDuration format. + # Ref: https://pkg.go.dev/flag#Duration + # leaseDuration: "15s" + # renewDeadline: "10s" + # retryPeriod: "5s" + logLevel: 2 + # Additional parameters provided by volume-modifier-for-k8s. + additionalArgs: [] resources: {} securityContext: readOnlyRootFilesystem: true @@ -114,7 +174,16 @@ imagePullSecrets: [] nameOverride: fullnameOverride: +awsAccessSecret: + name: aws-secret + keyId: key_id + accessKey: access_key + controller: + batching: true + volumeModificationFeature: + enabled: false + # Additional parameters provided by aws-ebs-csi-driver controller. additionalArgs: [] sdkDebugLog: false loggingFormat: text @@ -165,12 +234,15 @@ controller: # Additional labels for ServiceMonitor object labels: release: prometheus + interval: "15s" # If set to true, AWS API call metrics will be exported to the following # TCP endpoint: "0.0.0.0:3301" # --- # ID of the Kubernetes cluster used for tagging provisioned EBS volumes (optional). k8sTagClusterId: logLevel: 2 + userAgentExtra: "helm" + deploymentAnnotations: {} nodeSelector: node-role.kubernetes.io/control-plane: "" podAnnotations: {} @@ -182,6 +254,9 @@ controller: # region: us-east-1 region: replicaCount: 2 + revisionHistoryLimit: 10 + socketDirVolume: + emptyDir: {} updateStrategy: type: RollingUpdate rollingUpdate: @@ -195,13 +270,15 @@ controller: cpu: 10m memory: 40Mi limits: - cpu: 100m memory: 256Mi serviceAccount: # A service account will be created for you if set to true. Set to false if you want to use your own. create: true name: ebs-csi-controller-sa annotations: {} + ## Enable if EKS IAM for SA is used + # eks.amazonaws.com/role-arn: arn::iam:::role/ebs-csi-role + automountServiceAccountToken: true tolerations: - key: CriticalAddonsOnly operator: Exists @@ -235,8 +312,18 @@ controller: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 + # Add additional volume mounts on the controller with controller.volumes and controller.volumeMounts volumes: [] + # Add additional volumes to be mounted onto the controller: + # - name: custom-dir + # hostPath: + # path: /path/to/dir + # type: Directory volumeMounts: [] + # And add mount paths for those additional volumes: + # - name: custom-dir + # mountPath: /mount/path + # --- # securityContext on the controller container (see sidecars for securityContext on sidecar containers) containerSecurityContext: readOnlyRootFilesystem: true @@ -249,6 +336,13 @@ controller: # - name: wait # image: busybox # command: [ 'sh', '-c', "sleep 20" ] + # Enable opentelemetry tracing for the plugin running on the daemonset + otelTracing: {} + # otelServiceName: ebs-csi-controller + # otelExporterEndpoint: "http://localhost:4317" + + # Enable dnsConfig for the controller and node pods + dnsConfig: {} node: env: [] @@ -257,16 +351,26 @@ node: loggingFormat: text logLevel: 2 priorityClassName: + additionalArgs: [] affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - - matchExpressions: - - key: eks.amazonaws.com/compute-type - operator: NotIn - values: - - fargate + - matchExpressions: + - key: eks.amazonaws.com/compute-type + operator: NotIn + values: + - fargate + - key: node.kubernetes.io/instance-type + operator: NotIn + values: + - a1.medium + - a1.large + - a1.xlarge + - a1.2xlarge + - a1.4xlarge nodeSelector: {} + daemonSetAnnotations: {} podAnnotations: {} podLabels: {} tolerateAllTaints: true @@ -279,19 +383,32 @@ node: cpu: 10m memory: 40Mi limits: - cpu: 100m memory: 256Mi + revisionHistoryLimit: 10 + probeDirVolume: + emptyDir: {} serviceAccount: create: true name: ebs-csi-node-sa annotations: {} + ## Enable if EKS IAM for SA is used + # eks.amazonaws.com/role-arn: arn::iam:::role/ebs-csi-role + automountServiceAccountToken: true + # Enable the linux daemonset creation + enableLinux: true enableWindows: false + # The number of attachment slots to reserve for system use (and not to be used for CSI volumes) + # When this parameter is not specified (or set to -1), the EBS CSI Driver will attempt to determine the number of reserved slots via heuristic + # Cannot be specified at the same time as `node.volumeAttachLimit` + reservedVolumeAttachments: # The "maximum number of attachable volumes" per node + # Cannot be specified at the same time as `node.reservedVolumeAttachments` volumeAttachLimit: updateStrategy: type: RollingUpdate rollingUpdate: maxUnavailable: "10%" + hostNetwork: false # securityContext on the node pod securityContext: # The node pod must be run as root to bind to the registration/driver sockets @@ -299,10 +416,38 @@ node: runAsUser: 0 runAsGroup: 0 fsGroup: 0 + # Add additional volume mounts on the node pods with node.volumes and node.volumeMounts + volumes: [] + # Add additional volumes to be mounted onto the node pods: + # - name: custom-dir + # hostPath: + # path: /path/to/dir + # type: Directory + volumeMounts: [] + # And add mount paths for those additional volumes: + # - name: custom-dir + # mountPath: /mount/path + # --- # securityContext on the node container (see sidecars for securityContext on sidecar containers) containerSecurityContext: readOnlyRootFilesystem: true privileged: true + # Enable opentelemetry tracing for the plugin running on the daemonset + otelTracing: {} + # otelServiceName: ebs-csi-node + # otelExporterEndpoint: "http://localhost:4317" + +additionalDaemonSets: + # Additional node DaemonSets, using the node config structure + # See docs/additional-daemonsets.md for more information + # + # example: + # nodeSelector: + # node.kubernetes.io/instance-type: c5.large + # volumeAttachLimit: 15 + +# Enable compatibility for the A1 instance family via use of an AL2-based image in a separate DaemonSet +# a1CompatibilityDaemonSet: true # Create Constellation default StorageClasses createStorageClass: true @@ -323,12 +468,18 @@ storageClasses: [] # parameters: # encrypted: "true" +defaultStorageClass: + enabled: false + volumeSnapshotClasses: [] # Add VolumeSnapshotClass resources like: # - name: ebs-vsc # # annotation metadata # annotations: # snapshot.storage.kubernetes.io/is-default-class: "true" +# # label metadata +# labels: +# my-label-is: supercool # # deletionPolicy must be specified # deletionPolicy: Delete # parameters: @@ -337,3 +488,8 @@ volumeSnapshotClasses: [] # Intended for use with older clusters that cannot easily replace the CSIDriver object # This parameter should always be false for new installations useOldCSIDriver: false + +helmTester: + enabled: true + # Supply a custom image to the ebs-csi-driver-test pod in helm-tester.yaml + image: "gcr.io/k8s-staging-test-infra/kubekins-e2e:v20240311-b09cdeb92c-master" diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/Chart.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/Chart.yaml index fbab5e66d..3ce5248a0 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/Chart.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: "v1.3.0" +appVersion: "v1.4.0" description: Azure disk Container Storage Interface (CSI) Storage Plugin with on-node encryption support name: azuredisk-csi-driver -version: v1.3.0 +version: v1.4.0 diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/templates/csi-azuredisk-controller.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/templates/csi-azuredisk-controller.yaml index f7ac6f2db..645a4da75 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/templates/csi-azuredisk-controller.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/templates/csi-azuredisk-controller.yaml @@ -120,6 +120,7 @@ spec: - "-leader-election" - "--leader-election-namespace={{ .Release.Namespace }}" - "-v=2" + - "--timeout=1200s" env: - name: ADDRESS value: /csi/csi.sock @@ -157,7 +158,11 @@ spec: args: - --csi-address=/csi/csi.sock - --probe-timeout=3s +{{- if eq .Values.controller.hostNetwork true }} + - --http-endpoint=localhost:{{ .Values.controller.livenessProbe.healthPort }} +{{- else }} - --health-port={{ .Values.controller.livenessProbe.healthPort }} +{{- end }} - --v=2 volumeMounts: - name: socket-dir @@ -197,18 +202,29 @@ spec: - "--enable-traffic-manager={{ .Values.controller.enableTrafficManager }}" - "--traffic-manager-port={{ .Values.controller.trafficManagerPort }}" - "--enable-otel-tracing={{ .Values.controller.otelTracing.enabled }}" + - "--check-disk-lun-collision=true" + {{- range $value := .Values.controller.extraArgs }} + - {{ $value | quote }} + {{- end }} ports: - - containerPort: {{ .Values.controller.livenessProbe.healthPort }} - name: healthz - protocol: TCP - containerPort: {{ .Values.controller.metricsPort }} name: metrics protocol: TCP +{{- if ne .Values.controller.hostNetwork true }} + - containerPort: {{ .Values.controller.livenessProbe.healthPort }} + name: healthz + protocol: TCP +{{- end }} livenessProbe: failureThreshold: 5 httpGet: path: /healthz +{{- if eq .Values.controller.hostNetwork true }} + host: localhost + port: {{ .Values.controller.livenessProbe.healthPort }} +{{- else }} port: healthz +{{- end }} initialDelaySeconds: 30 timeoutSeconds: 10 periodSeconds: 30 diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/templates/csi-azuredisk-node.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/templates/csi-azuredisk-node.yaml index 50d3b795c..9d9c368d9 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/templates/csi-azuredisk-node.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/templates/csi-azuredisk-node.yaml @@ -74,7 +74,11 @@ spec: args: - --csi-address=/csi/csi.sock - --probe-timeout=3s +{{- if eq .Values.linux.hostNetwork true }} + - --http-endpoint=localhost:{{ .Values.node.livenessProbe.healthPort }} +{{- else }} - --health-port={{ .Values.node.livenessProbe.healthPort }} +{{- end }} - --v=2 resources: {{- toYaml .Values.linux.resources.livenessProbe | nindent 12 }} - name: node-driver-registrar @@ -131,15 +135,22 @@ spec: - "--get-nodeid-from-imds={{ .Values.node.getNodeIDFromIMDS }}" - "--enable-otel-tracing={{ .Values.linux.otelTracing.enabled }}" - "--kms-addr={{ .Values.global.keyServiceName }}.{{ .Values.global.keyServiceNamespace | default .Release.Namespace }}:{{ .Values.global.keyServicePort }}" +{{- if ne .Values.linux.hostNetwork true }} ports: - containerPort: {{ .Values.node.livenessProbe.healthPort }} name: healthz protocol: TCP +{{- end }} livenessProbe: failureThreshold: 5 httpGet: path: /healthz +{{- if eq .Values.linux.hostNetwork true }} + host: localhost + port: {{ .Values.node.livenessProbe.healthPort }} +{{- else }} port: healthz +{{- end }} initialDelaySeconds: 30 timeoutSeconds: 10 periodSeconds: 30 diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/values.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/values.yaml index 944663770..18faf65c3 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/values.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/azuredisk-csi-driver/values.yaml @@ -2,27 +2,27 @@ image: baseRepo: mcr.microsoft.com azuredisk: repository: ghcr.io/edgelesssys/constellation/azure-csi-driver - tag: v1.3.0@sha256:1e798f066ef78c293c4c87a31677f8948be4c8709980135969b73a9d7a46ca71 + tag: v1.4.0@sha256:e41b09d2735cb7410e2bf7abe9ca2166aa5a949d6c6e2ac570773b5d041797f1 pullPolicy: IfNotPresent csiProvisioner: repository: /oss/kubernetes-csi/csi-provisioner - tag: v3.5.0@sha256:fdf70099aa1538d1c2164976cf6d158ef8b3a5ee63db10bf0085de4ec66f59b4 + tag: v4.0.0@sha256:beadfb2cfa02f8bbb2efd88261a673023527cf51ebe7894daef82c4d928264a5 pullPolicy: IfNotPresent csiAttacher: repository: /oss/kubernetes-csi/csi-attacher - tag: v4.3.0@sha256:4306b80bfe8caea3fe53f6d1c15807c745be3072553ff508fc4f61da8f4a0c10 + tag: v4.5.0@sha256:172a9140780701b2223b7296729fc6cc3be8c86d0cfd2d0452e495f5ea28f51f pullPolicy: IfNotPresent csiResizer: repository: /oss/kubernetes-csi/csi-resizer - tag: v1.8.0@sha256:6f0e8c9f3d0bdcf7a5fb5e404276ffac624033099d7687c8080692bcb6d13cd1 + tag: v1.9.3@sha256:e20dc798f529436d2c861dd66bc7fcfa17623b562a2a65474aab38fb77c9824a pullPolicy: IfNotPresent livenessProbe: repository: /oss/kubernetes-csi/livenessprobe - tag: v2.10.0@sha256:3aeac313cffdb7db80b733539427f2533a3f662bf538e7b6434b0f898ceb701b + tag: v2.12.0@sha256:c762188c45d1b9bc9144b694b85313d5e49c741935a81d5b94fd7db978a40ae1 pullPolicy: IfNotPresent nodeDriverRegistrar: repository: /oss/kubernetes-csi/csi-node-driver-registrar - tag: v2.8.0@sha256:af6bf1b5ff310d4dc02cf8276be9b06014318f7ee31238b5fa278febd1a10ca9 + tag: v2.10.0@sha256:136e3a4a5897f111d1dedd404a5717ee7ff2f215e5fe878abdf4ce00c2292280 pullPolicy: IfNotPresent serviceAccount: @@ -140,11 +140,11 @@ snapshot: image: csiSnapshotter: repository: /oss/kubernetes-csi/csi-snapshotter - tag: v6.2.2 + tag: v6.3.3 pullPolicy: IfNotPresent csiSnapshotController: repository: /oss/kubernetes-csi/snapshot-controller - tag: v6.2.2 + tag: v6.3.3 pullPolicy: IfNotPresent snapshotController: name: csi-snapshot-controller diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/gcp-compute-persistent-disk-csi-driver/Chart.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/gcp-compute-persistent-disk-csi-driver/Chart.yaml index ed8008238..0380cc531 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/gcp-compute-persistent-disk-csi-driver/Chart.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/gcp-compute-persistent-disk-csi-driver/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -version: 1.3.0 -appVersion: "v1.3.0" +version: 1.4.0 +appVersion: "v1.4.0" description: GCP Compute Persistent Disk Container Storage Interface (CSI) Storage Plugin with on-node encryption support name: gcp-compute-persistent-disk-csi-driver diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/gcp-compute-persistent-disk-csi-driver/values.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/gcp-compute-persistent-disk-csi-driver/values.yaml index e620dde5a..2ac7e6b5e 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/gcp-compute-persistent-disk-csi-driver/values.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/gcp-compute-persistent-disk-csi-driver/values.yaml @@ -1,28 +1,28 @@ image: csiProvisioner: repo: registry.k8s.io/sig-storage/csi-provisioner - tag: v3.4.0@sha256:e468dddcd275163a042ab297b2d8c2aca50d5e148d2d22f3b6ba119e2f31fa79 + tag: v3.6.3@sha256:10624570c0aceb03f55f1eb07147b0c537e4676869cca2e9bd4bab113f810ac4 pullPolicy: IfNotPresent csiAttacher: repo: registry.k8s.io/sig-storage/csi-attacher - tag: v4.2.0@sha256:34cf9b32736c6624fc9787fb149ea6e0fbeb45415707ac2f6440ac960f1116e6 + tag: v4.4.3@sha256:d7325367ab72b2d469a5091d87b4fc01142d2d13d1a28b2defbbe3e6fdbc4611 pullPolicy: IfNotPresent csiResizer: repo: registry.k8s.io/sig-storage/csi-resizer - tag: v1.7.0@sha256:3a7bdf5d105783d05d0962fa06ca53032b01694556e633f27366201c2881e01d + tag: v1.9.3@sha256:3c116f543f0590aeff3299c8bb0683f250817d11a77d9e9071b15a0bffdabcd9 pullPolicy: IfNotPresent csiSnapshotter: repo: registry.k8s.io/sig-storage/csi-snapshotter - tag: v6.1.0@sha256:291334908ddf71a4661fd7f6d9d97274de8a5378a2b6fdfeb2ce73414a34f82f + tag: v6.3.3@sha256:f1bd6ee18c4021c1c94f29edfab89b49b6a4d1b800936c19dbef2d75f8202f2d pullPolicy: IfNotPresent csiNodeRegistrar: repo: registry.k8s.io/sig-storage/csi-node-driver-registrar - tag: v2.7.0@sha256:4a4cae5118c4404e35d66059346b7fa0835d7e6319ff45ed73f4bba335cf5183 + tag: v2.9.3@sha256:0f64602ea791246712b51df334bbd701a0f31df9950a4cb9c28c059f367baa9e pullPolicy: IfNotPresent gcepdDriver: repo: ghcr.io/edgelesssys/constellation/gcp-csi-driver # CSI driver version is independent of Constellation releases - tag: v1.3.0@sha256:0ecb68f348ed6c287075db00f9c5ea731e7e2db9f2f7511b65391fb6856fe11a + tag: v1.4.0@sha256:53d608aa03dd07059bc04e1f8c64e2feb6fceff50fb0cbe276d31a8652a19bac pullPolicy: IfNotPresent csiController: diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/Chart.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/Chart.yaml index a6aacc946..be3dde48a 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/Chart.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/Chart.yaml @@ -1,6 +1,9 @@ apiVersion: v2 name: snapshot-controller -description: A chart to deploy the CSI snapshot controller and webhook +description: | + A chart to deploy the CSI snapshot controller and webhook + Snapshot controller source: https://github.com/kubernetes-csi/external-snapshotter/tree/v8.0.1/deploy/kubernetes/snapshot-controller + Snapshot validating webhook source: https://github.com/kubernetes-csi/external-snapshotter/tree/v8.0.1/deploy/kubernetes/webhook-example type: application -version: 6.2.2 -appVersion: "6.2.2" +version: 8.0.1 +appVersion: "8.0.1" diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/admission-configuration.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/admission-configuration.yaml index 95e26f473..ab6159704 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/admission-configuration.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/admission-configuration.yaml @@ -1,3 +1,6 @@ +# Snapshot validating webhook configuration +# Adapted from https://github.com/kubernetes-csi/external-snapshotter/tree/v8.0.1/deploy/kubernetes/webhook-example +# to use cert-manager for serving certificates apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: @@ -10,7 +13,7 @@ webhooks: - apiGroups: ["snapshot.storage.k8s.io"] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] - resources: ["volumesnapshots", "volumesnapshotcontents", "volumesnapshotclasses"] + resources: ["volumesnapshotclasses"] scope: "*" clientConfig: service: diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/serving-cert.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/serving-cert.yaml index 93c24cec6..00a1935e4 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/serving-cert.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/serving-cert.yaml @@ -6,7 +6,7 @@ metadata: spec: dnsNames: - 'snapshot-validation-service.{{ .Release.Namespace }}.svc' - - 'snapshot-validation-service.{{ .Release.Namespace }}.svc.{{ .Values.kubernetesClusterDomain }}' + - 'snapshot-validation-service.{{ .Release.Namespace }}.svc.cluster.local' issuerRef: kind: Issuer name: snapshot-validation-selfsigned-issuer diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/snapshot-controller.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/snapshot-controller.yaml index ae8dbcc4e..bd244b0db 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/snapshot-controller.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/snapshot-controller.yaml @@ -16,10 +16,11 @@ spec: selector: matchLabels: app: snapshot-controller - # the snapshot controller won't be marked as ready if the v1 CRDs are unavailable - # in #504 the snapshot-controller will exit after around 7.5 seconds if it - # can't find the v1 CRDs so this value should be greater than that - minReadySeconds: 15 + # The snapshot controller won't be marked as ready if the v1 CRDs are unavailable. + # The flag --retry-crd-interval-max is used to determine how long the controller + # will wait for the CRDs to become available before exiting. The default is 30 seconds + # so minReadySeconds should be set slightly higher than the flag value. + minReadySeconds: 35 strategy: rollingUpdate: maxSurge: 0 diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/snapshot-webhook.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/snapshot-webhook.yaml index 861f284d7..8c93b51fc 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/snapshot-webhook.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/templates/snapshot-webhook.yaml @@ -1,3 +1,6 @@ +# Snapshot validating webhook configuration +# Adapted from https://github.com/kubernetes-csi/external-snapshotter/tree/v8.0.1/deploy/kubernetes/webhook-example +# to use cert-manager for serving certificates --- apiVersion: apps/v1 kind: Deployment diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/values.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/values.yaml index 9c2f219b5..b03a97492 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/values.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-controller/values.yaml @@ -1,15 +1,14 @@ -kubernetesClusterDomain: cluster.local snapshotController: replicas: 2 snapshotController: image: repository: registry.k8s.io/sig-storage/snapshot-controller - tag: v6.2.2@sha256:fb95b65bb88f319f0f7d5397c401a654164f11a191f466b4026fa36085c7141b + tag: v8.1.0@sha256:a8a6749641849a6d7e560d26647e88dbd605a75cbff1823568ab90287ea29038 imagePullPolicy: IfNotPresent snapshotWebhook: replicas: 1 webhook: image: repository: registry.k8s.io/sig-storage/snapshot-validation-webhook - tag: v6.2.2@sha256:b5be1e04b7c43352f83e135bd772de05437f8f3a20cb9437875d1a0d4f127440 + tag: v8.1.0@sha256:35fa940f062222dfa3257e0c74837a22c35976be899bab6103b433bab0e03a81 imagePullPolicy: IfNotPresent diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/Chart.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/Chart.yaml index fd0fc7ae2..aa7a27fe1 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/Chart.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/Chart.yaml @@ -1,6 +1,7 @@ apiVersion: v2 name: snapshot-crds -description: A chart to deploy CSI snapshot CRDs +description: "A chart to deploy CSI snapshot CRDs. Source: https://github.com/kubernetes-csi/external-snapshotter/tree/v8.0.1/client/config/crd" + type: application -version: 6.2.2 -appVersion: "6.2.2" +version: 8.0.1 +appVersion: "8.0.1" diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshotclasses.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshotclasses.yaml index 56a8e1487..8164952a4 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshotclasses.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshotclasses.yaml @@ -3,9 +3,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/814" - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.15.0 name: volumesnapshotclasses.snapshot.storage.k8s.io spec: group: snapshot.storage.k8s.io @@ -34,42 +33,52 @@ spec: name: v1 schema: openAPIV3Schema: - description: VolumeSnapshotClass specifies parameters that a underlying storage - system uses when creating a volume snapshot. A specific VolumeSnapshotClass - is used by specifying its name in a VolumeSnapshot object. VolumeSnapshotClasses - are non-namespaced + description: |- + VolumeSnapshotClass specifies parameters that a underlying storage system uses when + creating a volume snapshot. A specific VolumeSnapshotClass is used by specifying its + name in a VolumeSnapshot object. + VolumeSnapshotClasses are non-namespaced properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string deletionPolicy: - description: deletionPolicy determines whether a VolumeSnapshotContent - created through the VolumeSnapshotClass should be deleted when its bound - VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". - "Retain" means that the VolumeSnapshotContent and its physical snapshot - on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent - and its physical snapshot on underlying storage system are deleted. + description: |- + deletionPolicy determines whether a VolumeSnapshotContent created through + the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. + Supported values are "Retain" and "Delete". + "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. + "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. Required. enum: - Delete - Retain type: string driver: - description: driver is the name of the storage driver that handles this - VolumeSnapshotClass. Required. + description: |- + driver is the name of the storage driver that handles this VolumeSnapshotClass. + Required. type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string + metadata: + type: object parameters: additionalProperties: type: string - description: parameters is a key-value map with storage driver specific - parameters for creating snapshots. These values are opaque to Kubernetes. + description: |- + parameters is a key-value map with storage driver specific parameters for creating snapshots. + These values are opaque to Kubernetes. type: object required: - deletionPolicy diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshotcontents.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshotcontents.yaml index d6181ed93..cd0c879fc 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshotcontents.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshotcontents.yaml @@ -3,9 +3,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 - api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/814" - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.15.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/955" name: volumesnapshotcontents.snapshot.storage.k8s.io spec: group: snapshot.storage.k8s.io @@ -48,7 +47,8 @@ spec: jsonPath: .spec.volumeSnapshotRef.name name: VolumeSnapshot type: string - - description: Namespace of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. + - description: Namespace of the VolumeSnapshot object to which this VolumeSnapshotContent + object is bound. jsonPath: .spec.volumeSnapshotRef.namespace name: VolumeSnapshotNamespace type: string @@ -58,152 +58,206 @@ spec: name: v1 schema: openAPIV3Schema: - description: VolumeSnapshotContent represents the actual "on-disk" snapshot - object in the underlying storage system + description: |- + VolumeSnapshotContent represents the actual "on-disk" snapshot object in the + underlying storage system properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string + metadata: + type: object spec: - description: spec defines properties of a VolumeSnapshotContent created - by the underlying storage system. Required. + description: |- + spec defines properties of a VolumeSnapshotContent created by the underlying storage system. + Required. properties: deletionPolicy: - description: deletionPolicy determines whether this VolumeSnapshotContent - and its physical snapshot on the underlying storage system should - be deleted when its bound VolumeSnapshot is deleted. Supported values - are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent - and its physical snapshot on underlying storage system are kept. - "Delete" means that the VolumeSnapshotContent and its physical snapshot - on underlying storage system are deleted. For dynamically provisioned - snapshots, this field will automatically be filled in by the CSI - snapshotter sidecar with the "DeletionPolicy" field defined in the - corresponding VolumeSnapshotClass. For pre-existing snapshots, users - MUST specify this field when creating the VolumeSnapshotContent - object. Required. + description: |- + deletionPolicy determines whether this VolumeSnapshotContent and its physical snapshot on + the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. + Supported values are "Retain" and "Delete". + "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. + "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. + For dynamically provisioned snapshots, this field will automatically be filled in by the + CSI snapshotter sidecar with the "DeletionPolicy" field defined in the corresponding + VolumeSnapshotClass. + For pre-existing snapshots, users MUST specify this field when creating the + VolumeSnapshotContent object. + Required. enum: - Delete - Retain type: string driver: - description: driver is the name of the CSI driver used to create the - physical snapshot on the underlying storage system. This MUST be - the same as the name returned by the CSI GetPluginName() call for - that driver. Required. + description: |- + driver is the name of the CSI driver used to create the physical snapshot on + the underlying storage system. + This MUST be the same as the name returned by the CSI GetPluginName() call for + that driver. + Required. type: string source: - description: source specifies whether the snapshot is (or should be) - dynamically provisioned or already exists, and just requires a Kubernetes - object representation. This field is immutable after creation. Required. + description: |- + source specifies whether the snapshot is (or should be) dynamically provisioned + or already exists, and just requires a Kubernetes object representation. + This field is immutable after creation. + Required. properties: snapshotHandle: - description: snapshotHandle specifies the CSI "snapshot_id" of - a pre-existing snapshot on the underlying storage system for - which a Kubernetes object representation was (or should be) - created. This field is immutable. - type: string - volumeHandle: - description: volumeHandle specifies the CSI "volume_id" of the - volume from which a snapshot should be dynamically taken from. + description: |- + snapshotHandle specifies the CSI "snapshot_id" of a pre-existing snapshot on + the underlying storage system for which a Kubernetes object representation + was (or should be) created. This field is immutable. type: string + x-kubernetes-validations: + - message: snapshotHandle is immutable + rule: self == oldSelf + volumeHandle: + description: |- + volumeHandle specifies the CSI "volume_id" of the volume from which a snapshot + should be dynamically taken from. + This field is immutable. + type: string + x-kubernetes-validations: + - message: volumeHandle is immutable + rule: self == oldSelf type: object - oneOf: - - required: ["snapshotHandle"] - - required: ["volumeHandle"] + x-kubernetes-validations: + - message: volumeHandle is required once set + rule: '!has(oldSelf.volumeHandle) || has(self.volumeHandle)' + - message: snapshotHandle is required once set + rule: '!has(oldSelf.snapshotHandle) || has(self.snapshotHandle)' + - message: exactly one of volumeHandle and snapshotHandle must be + set + rule: (has(self.volumeHandle) && !has(self.snapshotHandle)) || (!has(self.volumeHandle) + && has(self.snapshotHandle)) sourceVolumeMode: - description: SourceVolumeMode is the mode of the volume whose snapshot - is taken. Can be either “Filesystem” or “Block”. If not specified, - it indicates the source volume's mode is unknown. This field is - immutable. This field is an alpha field. + description: |- + SourceVolumeMode is the mode of the volume whose snapshot is taken. + Can be either “Filesystem” or “Block”. + If not specified, it indicates the source volume's mode is unknown. + This field is immutable. + This field is an alpha field. type: string + x-kubernetes-validations: + - message: sourceVolumeMode is immutable + rule: self == oldSelf volumeSnapshotClassName: - description: name of the VolumeSnapshotClass from which this snapshot - was (or will be) created. Note that after provisioning, the VolumeSnapshotClass - may be deleted or recreated with different set of values, and as - such, should not be referenced post-snapshot creation. + description: |- + name of the VolumeSnapshotClass from which this snapshot was (or will be) + created. + Note that after provisioning, the VolumeSnapshotClass may be deleted or + recreated with different set of values, and as such, should not be referenced + post-snapshot creation. type: string volumeSnapshotRef: - description: volumeSnapshotRef specifies the VolumeSnapshot object - to which this VolumeSnapshotContent object is bound. VolumeSnapshot.Spec.VolumeSnapshotContentName - field must reference to this VolumeSnapshotContent's name for the - bidirectional binding to be valid. For a pre-existing VolumeSnapshotContent - object, name and namespace of the VolumeSnapshot object MUST be - provided for binding to happen. This field is immutable after creation. + description: |- + volumeSnapshotRef specifies the VolumeSnapshot object to which this + VolumeSnapshotContent object is bound. + VolumeSnapshot.Spec.VolumeSnapshotContentName field must reference to + this VolumeSnapshotContent's name for the bidirectional binding to be valid. + For a pre-existing VolumeSnapshotContent object, name and namespace of the + VolumeSnapshot object MUST be provided for binding to happen. + This field is immutable after creation. Required. properties: apiVersion: description: API version of the referent. type: string fieldPath: - description: 'If referring to a piece of an object instead of - an entire object, this string should contain a valid JSON/Go - field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within - a pod, this would take on a value like: "spec.containers{name}" - (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" - (container with index 2 in this pod). This syntax is chosen - only to have some well-defined way of referencing a part of - an object. TODO: this design is not final and this field is - subject to change in the future.' + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. type: string kind: - description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string namespace: - description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ type: string resourceVersion: - description: 'Specific resourceVersion to which this reference - is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency type: string uid: - description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids type: string type: object x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: both spec.volumeSnapshotRef.name and spec.volumeSnapshotRef.namespace + must be set + rule: has(self.name) && has(self.__namespace__) required: - deletionPolicy - driver - source - volumeSnapshotRef type: object + x-kubernetes-validations: + - message: sourceVolumeMode is required once set + rule: '!has(oldSelf.sourceVolumeMode) || has(self.sourceVolumeMode)' status: description: status represents the current information of a snapshot. properties: creationTime: - description: creationTime is the timestamp when the point-in-time - snapshot is taken by the underlying storage system. In dynamic snapshot - creation case, this field will be filled in by the CSI snapshotter - sidecar with the "creation_time" value returned from CSI "CreateSnapshot" - gRPC call. For a pre-existing snapshot, this field will be filled - with the "creation_time" value returned from the CSI "ListSnapshots" - gRPC call if the driver supports it. If not specified, it indicates - the creation time is unknown. The format of this field is a Unix - nanoseconds time encoded as an int64. On Unix, the command `date - +%s%N` returns the current time in nanoseconds since 1970-01-01 - 00:00:00 UTC. + description: |- + creationTime is the timestamp when the point-in-time snapshot is taken + by the underlying storage system. + In dynamic snapshot creation case, this field will be filled in by the + CSI snapshotter sidecar with the "creation_time" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "creation_time" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. + If not specified, it indicates the creation time is unknown. + The format of this field is a Unix nanoseconds time encoded as an int64. + On Unix, the command `date +%s%N` returns the current time in nanoseconds + since 1970-01-01 00:00:00 UTC. format: int64 type: integer error: - description: error is the last observed error during snapshot creation, - if any. Upon success after retry, this error field will be cleared. + description: |- + error is the last observed error during snapshot creation, if any. + Upon success after retry, this error field will be cleared. properties: message: - description: 'message is a string detailing the encountered error - during snapshot creation if specified. NOTE: message may be - logged, and it should not contain sensitive information.' + description: |- + message is a string detailing the encountered error during snapshot + creation if specified. + NOTE: message may be logged, and it should not contain sensitive + information. type: string time: description: time is the timestamp when the error was encountered. @@ -211,38 +265,40 @@ spec: type: string type: object readyToUse: - description: readyToUse indicates if a snapshot is ready to be used - to restore a volume. In dynamic snapshot creation case, this field - will be filled in by the CSI snapshotter sidecar with the "ready_to_use" - value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing - snapshot, this field will be filled with the "ready_to_use" value - returned from the CSI "ListSnapshots" gRPC call if the driver supports - it, otherwise, this field will be set to "True". If not specified, - it means the readiness of a snapshot is unknown. + description: |- + readyToUse indicates if a snapshot is ready to be used to restore a volume. + In dynamic snapshot creation case, this field will be filled in by the + CSI snapshotter sidecar with the "ready_to_use" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "ready_to_use" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, + otherwise, this field will be set to "True". + If not specified, it means the readiness of a snapshot is unknown. type: boolean restoreSize: - description: restoreSize represents the complete size of the snapshot - in bytes. In dynamic snapshot creation case, this field will be - filled in by the CSI snapshotter sidecar with the "size_bytes" value - returned from CSI "CreateSnapshot" gRPC call. For a pre-existing - snapshot, this field will be filled with the "size_bytes" value - returned from the CSI "ListSnapshots" gRPC call if the driver supports - it. When restoring a volume from this snapshot, the size of the - volume MUST NOT be smaller than the restoreSize if it is specified, - otherwise the restoration will fail. If not specified, it indicates - that the size is unknown. + description: |- + restoreSize represents the complete size of the snapshot in bytes. + In dynamic snapshot creation case, this field will be filled in by the + CSI snapshotter sidecar with the "size_bytes" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "size_bytes" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. + When restoring a volume from this snapshot, the size of the volume MUST NOT + be smaller than the restoreSize if it is specified, otherwise the restoration will fail. + If not specified, it indicates that the size is unknown. format: int64 minimum: 0 type: integer snapshotHandle: - description: snapshotHandle is the CSI "snapshot_id" of a snapshot - on the underlying storage system. If not specified, it indicates - that dynamic snapshot creation has either failed or it is still - in progress. + description: |- + snapshotHandle is the CSI "snapshot_id" of a snapshot on the underlying storage system. + If not specified, it indicates that dynamic snapshot creation has either failed + or it is still in progress. type: string - volumeGroupSnapshotContentName: - description: VolumeGroupSnapshotContentName is the name of the VolumeGroupSnapshotContent - of which this VolumeSnapshotContent is a part of. + volumeGroupSnapshotHandle: + description: |- + VolumeGroupSnapshotHandle is the CSI "group_snapshot_id" of a group snapshot + on the underlying storage system. type: string type: object required: diff --git a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshots.yaml b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshots.yaml index 3e7f99663..6b96d7082 100644 --- a/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshots.yaml +++ b/internal/constellation/helm/charts/edgeless/csi/charts/snapshot-crds/templates/volumesnapshots.yaml @@ -3,9 +3,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.3 + controller-gen.kubebuilder.io/version: v0.15.0 api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/814" - creationTimestamp: null name: volumesnapshots.snapshot.storage.k8s.io spec: group: snapshot.storage.k8s.io @@ -61,103 +60,140 @@ spec: name: v1 schema: openAPIV3Schema: - description: VolumeSnapshot is a user's request for either creating a point-in-time + description: |- + VolumeSnapshot is a user's request for either creating a point-in-time snapshot of a persistent volume, or binding to a pre-existing snapshot. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string + metadata: + type: object spec: - description: 'spec defines the desired characteristics of a snapshot requested - by a user. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots - Required.' + description: |- + spec defines the desired characteristics of a snapshot requested by a user. + More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots + Required. properties: source: - description: source specifies where a snapshot will be created from. - This field is immutable after creation. Required. + description: |- + source specifies where a snapshot will be created from. + This field is immutable after creation. + Required. properties: persistentVolumeClaimName: - description: persistentVolumeClaimName specifies the name of the - PersistentVolumeClaim object representing the volume from which - a snapshot should be created. This PVC is assumed to be in the - same namespace as the VolumeSnapshot object. This field should - be set if the snapshot does not exists, and needs to be created. + description: |- + persistentVolumeClaimName specifies the name of the PersistentVolumeClaim + object representing the volume from which a snapshot should be created. + This PVC is assumed to be in the same namespace as the VolumeSnapshot + object. + This field should be set if the snapshot does not exists, and needs to be + created. This field is immutable. type: string + x-kubernetes-validations: + - message: persistentVolumeClaimName is immutable + rule: self == oldSelf volumeSnapshotContentName: - description: volumeSnapshotContentName specifies the name of a - pre-existing VolumeSnapshotContent object representing an existing - volume snapshot. This field should be set if the snapshot already - exists and only needs a representation in Kubernetes. This field - is immutable. + description: |- + volumeSnapshotContentName specifies the name of a pre-existing VolumeSnapshotContent + object representing an existing volume snapshot. + This field should be set if the snapshot already exists and only needs a representation in Kubernetes. + This field is immutable. type: string + x-kubernetes-validations: + - message: volumeSnapshotContentName is immutable + rule: self == oldSelf type: object - oneOf: - - required: ["persistentVolumeClaimName"] - - required: ["volumeSnapshotContentName"] + x-kubernetes-validations: + - message: persistentVolumeClaimName is required once set + rule: '!has(oldSelf.persistentVolumeClaimName) || has(self.persistentVolumeClaimName)' + - message: volumeSnapshotContentName is required once set + rule: '!has(oldSelf.volumeSnapshotContentName) || has(self.volumeSnapshotContentName)' + - message: exactly one of volumeSnapshotContentName and persistentVolumeClaimName + must be set + rule: (has(self.volumeSnapshotContentName) && !has(self.persistentVolumeClaimName)) + || (!has(self.volumeSnapshotContentName) && has(self.persistentVolumeClaimName)) volumeSnapshotClassName: - description: 'VolumeSnapshotClassName is the name of the VolumeSnapshotClass - requested by the VolumeSnapshot. VolumeSnapshotClassName may be - left nil to indicate that the default SnapshotClass should be used. - A given cluster may have multiple default Volume SnapshotClasses: - one default per CSI Driver. If a VolumeSnapshot does not specify - a SnapshotClass, VolumeSnapshotSource will be checked to figure - out what the associated CSI Driver is, and the default VolumeSnapshotClass - associated with that CSI Driver will be used. If more than one VolumeSnapshotClass - exist for a given CSI Driver and more than one have been marked - as default, CreateSnapshot will fail and generate an event. Empty - string is not allowed for this field.' + description: |- + VolumeSnapshotClassName is the name of the VolumeSnapshotClass + requested by the VolumeSnapshot. + VolumeSnapshotClassName may be left nil to indicate that the default + SnapshotClass should be used. + A given cluster may have multiple default Volume SnapshotClasses: one + default per CSI Driver. If a VolumeSnapshot does not specify a SnapshotClass, + VolumeSnapshotSource will be checked to figure out what the associated + CSI Driver is, and the default VolumeSnapshotClass associated with that + CSI Driver will be used. If more than one VolumeSnapshotClass exist for + a given CSI Driver and more than one have been marked as default, + CreateSnapshot will fail and generate an event. + Empty string is not allowed for this field. type: string + x-kubernetes-validations: + - message: volumeSnapshotClassName must not be the empty string when + set + rule: size(self) > 0 required: - source type: object status: - description: status represents the current information of a snapshot. - Consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent - objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent - point at each other) before using this object. + description: |- + status represents the current information of a snapshot. + Consumers must verify binding between VolumeSnapshot and + VolumeSnapshotContent objects is successful (by validating that both + VolumeSnapshot and VolumeSnapshotContent point at each other) before + using this object. properties: boundVolumeSnapshotContentName: - description: 'boundVolumeSnapshotContentName is the name of the VolumeSnapshotContent - object to which this VolumeSnapshot object intends to bind to. If - not specified, it indicates that the VolumeSnapshot object has not - been successfully bound to a VolumeSnapshotContent object yet. NOTE: - To avoid possible security issues, consumers must verify binding - between VolumeSnapshot and VolumeSnapshotContent objects is successful - (by validating that both VolumeSnapshot and VolumeSnapshotContent - point at each other) before using this object.' + description: |- + boundVolumeSnapshotContentName is the name of the VolumeSnapshotContent + object to which this VolumeSnapshot object intends to bind to. + If not specified, it indicates that the VolumeSnapshot object has not been + successfully bound to a VolumeSnapshotContent object yet. + NOTE: To avoid possible security issues, consumers must verify binding between + VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that + both VolumeSnapshot and VolumeSnapshotContent point at each other) before using + this object. type: string creationTime: - description: creationTime is the timestamp when the point-in-time - snapshot is taken by the underlying storage system. In dynamic snapshot - creation case, this field will be filled in by the snapshot controller - with the "creation_time" value returned from CSI "CreateSnapshot" - gRPC call. For a pre-existing snapshot, this field will be filled - with the "creation_time" value returned from the CSI "ListSnapshots" - gRPC call if the driver supports it. If not specified, it may indicate - that the creation time of the snapshot is unknown. + description: |- + creationTime is the timestamp when the point-in-time snapshot is taken + by the underlying storage system. + In dynamic snapshot creation case, this field will be filled in by the + snapshot controller with the "creation_time" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "creation_time" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. + If not specified, it may indicate that the creation time of the snapshot is unknown. format: date-time type: string error: - description: error is the last observed error during snapshot creation, - if any. This field could be helpful to upper level controllers(i.e., - application controller) to decide whether they should continue on - waiting for the snapshot to be created based on the type of error - reported. The snapshot controller will keep retrying when an error - occurs during the snapshot creation. Upon success, this error field - will be cleared. + description: |- + error is the last observed error during snapshot creation, if any. + This field could be helpful to upper level controllers(i.e., application controller) + to decide whether they should continue on waiting for the snapshot to be created + based on the type of error reported. + The snapshot controller will keep retrying when an error occurs during the + snapshot creation. Upon success, this error field will be cleared. properties: message: - description: 'message is a string detailing the encountered error - during snapshot creation if specified. NOTE: message may be - logged, and it should not contain sensitive information.' + description: |- + message is a string detailing the encountered error during snapshot + creation if specified. + NOTE: message may be logged, and it should not contain sensitive + information. type: string time: description: time is the timestamp when the error was encountered. @@ -165,32 +201,35 @@ spec: type: string type: object readyToUse: - description: readyToUse indicates if the snapshot is ready to be used - to restore a volume. In dynamic snapshot creation case, this field - will be filled in by the snapshot controller with the "ready_to_use" - value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing - snapshot, this field will be filled with the "ready_to_use" value - returned from the CSI "ListSnapshots" gRPC call if the driver supports - it, otherwise, this field will be set to "True". If not specified, - it means the readiness of a snapshot is unknown. + description: |- + readyToUse indicates if the snapshot is ready to be used to restore a volume. + In dynamic snapshot creation case, this field will be filled in by the + snapshot controller with the "ready_to_use" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "ready_to_use" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, + otherwise, this field will be set to "True". + If not specified, it means the readiness of a snapshot is unknown. type: boolean restoreSize: type: string - description: restoreSize represents the minimum size of volume required - to create a volume from this snapshot. In dynamic snapshot creation - case, this field will be filled in by the snapshot controller with - the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. - For a pre-existing snapshot, this field will be filled with the - "size_bytes" value returned from the CSI "ListSnapshots" gRPC call - if the driver supports it. When restoring a volume from this snapshot, - the size of the volume MUST NOT be smaller than the restoreSize - if it is specified, otherwise the restoration will fail. If not - specified, it indicates that the size is unknown. + description: |- + restoreSize represents the minimum size of volume required to create a volume + from this snapshot. + In dynamic snapshot creation case, this field will be filled in by the + snapshot controller with the "size_bytes" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "size_bytes" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. + When restoring a volume from this snapshot, the size of the volume MUST NOT + be smaller than the restoreSize if it is specified, otherwise the restoration will fail. + If not specified, it indicates that the size is unknown. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true volumeGroupSnapshotName: - description: VolumeGroupSnapshotName is the name of the VolumeGroupSnapshot - of which this VolumeSnapshot is a part of. + description: |- + VolumeGroupSnapshotName is the name of the VolumeGroupSnapshot of which this + VolumeSnapshot is a part of. type: string type: object required: diff --git a/internal/constellation/helm/charts/edgeless/operators/charts/node-maintenance-operator/templates/manager-rbac.yaml b/internal/constellation/helm/charts/edgeless/operators/charts/node-maintenance-operator/templates/manager-rbac.yaml index 52b9e568a..c5d5a211b 100644 --- a/internal/constellation/helm/charts/edgeless/operators/charts/node-maintenance-operator/templates/manager-rbac.yaml +++ b/internal/constellation/helm/charts/edgeless/operators/charts/node-maintenance-operator/templates/manager-rbac.yaml @@ -12,7 +12,13 @@ rules: resources: - namespaces verbs: + - create + - delete - get + - list + - patch + - update + - watch - apiGroups: - "" resources: diff --git a/internal/constellation/helm/cilium.patch b/internal/constellation/helm/cilium.patch deleted file mode 100644 index cc12f4cb5..000000000 --- a/internal/constellation/helm/cilium.patch +++ /dev/null @@ -1,103 +0,0 @@ -diff --git a/install/kubernetes/cilium/templates/cilium-configmap.yaml b/install/kubernetes/cilium/templates/cilium-configmap.yaml -index 4ac3b006e3..3541e3d380 100644 ---- a/install/kubernetes/cilium/templates/cilium-configmap.yaml -+++ b/install/kubernetes/cilium/templates/cilium-configmap.yaml -@@ -608,7 +608,9 @@ data: - {{- if .Values.encryption.strictMode.enabled }} - enable-encryption-strict-mode: {{ .Values.encryption.strictMode.enabled | quote }} - -- encryption-strict-mode-cidr: {{ .Values.encryption.strictMode.cidr | quote }} -+ encryption-strict-mode-node-cidrs: {{ .Values.encryption.strictMode.nodeCIDRList | join " " | quote }} -+ -+ encryption-strict-mode-pod-cidrs: {{ .Values.encryption.strictMode.podCIDRList | join " " | quote }} - - encryption-strict-mode-allow-remote-node-identities: {{ .Values.encryption.strictMode.allowRemoteNodeIdentities | quote }} - {{- end }} -diff --git a/install/kubernetes/cilium/values.yaml b/install/kubernetes/cilium/values.yaml -index c00e9af831..4661c16f56 100644 ---- a/install/kubernetes/cilium/values.yaml -+++ b/install/kubernetes/cilium/values.yaml -@@ -794,17 +794,21 @@ encryption: - # This option is only effective when encryption.type is set to "wireguard". - nodeEncryption: false - -- # -- Configure the WireGuard Pod2Pod strict mode. -+ # -- Configure the WireGuard strict mode. - strictMode: -- # -- Enable WireGuard Pod2Pod strict mode. -+ # -- Enable WireGuard strict mode. - enabled: false -+ -+ # -- podCIDRList for the WireGuard strict mode. -+ podCIDRList: [] - -- # -- CIDR for the WireGuard Pod2Pod strict mode. -- cidr: "" -+ # -- nodeCIDRList for the WireGuard strict mode. -+ nodeCIDRList: [] - - # -- Allow dynamic lookup of remote node identities. - # This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. -- allowRemoteNodeIdentities: false -+ # This is also required when control-plane nodes are exempted from node-to-node encryption. -+ allowRemoteNodeIdentities: true - - ipsec: - # -- Name of the key file inside the Kubernetes secret configured via secretName. -diff --git a/install/kubernetes/cilium/Chart.yaml b/install/kubernetes/cilium/Chart.yaml -index 256a79542..3f3fc714b 100644 ---- a/install/kubernetes/cilium/Chart.yaml -+++ b/install/kubernetes/cilium/Chart.yaml -@@ -2,8 +2,8 @@ apiVersion: v2 - name: cilium - displayName: Cilium - home: https://cilium.io/ --version: 1.15.0-pre.3 --appVersion: 1.15.0-pre.3 -+version: 1.15.0-pre.3-edg.3 -+appVersion: 1.15.0-pre.3-edg.3 - kubeVersion: ">= 1.16.0-0" - icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg - description: eBPF-based Networking, Security, and Observability -diff --git a/install/kubernetes/cilium/templates/cilium-agent/daemonset.yaml b/install/kubernetes/cilium/templates/cilium-agent/daemonset.yaml -index f6b493cb7..50b80267a 100644 ---- a/install/kubernetes/cilium/templates/cilium-agent/daemonset.yaml -+++ b/install/kubernetes/cilium/templates/cilium-agent/daemonset.yaml -@@ -715,6 +715,37 @@ spec: - - name: cni-path - mountPath: /host/opt/cni/bin - {{- end }} # .Values.cni.install -+ - name: firewall-pods -+ image: ghcr.io/edgelesssys/cilium/cilium:v1.15.0-pre.3-edg.2@sha256:c21b7fbbb084a128a479d6170e5f89ad2768dfecb4af10ee6a99ffe5d1a11749 -+ imagePullPolicy: IfNotPresent -+ command: -+ - /bin/bash -+ - -exc -+ - | -+ pref=32 -+ interface=$(ip route | awk '/^default/ { print $5 }') -+ tc qdisc add dev "${interface}" clsact || true -+ tc filter del dev "${interface}" ingress pref "${pref}" 2>/dev/null || true -+ handle=0 -+ for cidr in ${POD_CIDRS}; do -+ handle=$((handle + 1)) -+ tc filter replace dev "${interface}" ingress pref "${pref}" handle "${handle}" protocol ip flower dst_ip "${cidr}" action drop -+ done -+ env: -+ - name: POD_CIDRS -+ valueFrom: -+ configMapKeyRef: -+ key: encryption-strict-mode-pod-cidrs -+ name: cilium-config -+ optional: true -+ resources: -+ requests: -+ cpu: 100m -+ memory: 20Mi -+ securityContext: -+ capabilities: -+ add: -+ - NET_ADMIN - restartPolicy: Always - priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.priorityClassName "system-node-critical") }} - serviceAccount: {{ .Values.serviceAccounts.cilium.name | quote }} diff --git a/internal/constellation/helm/corednsgen/BUILD.bazel b/internal/constellation/helm/corednsgen/BUILD.bazel new file mode 100644 index 000000000..4dbc61a61 --- /dev/null +++ b/internal/constellation/helm/corednsgen/BUILD.bazel @@ -0,0 +1,26 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "corednsgen_lib", + srcs = ["corednsgen.go"], + importpath = "github.com/edgelesssys/constellation/v2/internal/constellation/helm/corednsgen", + visibility = ["//visibility:private"], + deps = [ + "//internal/versions", + "@com_github_regclient_regclient//:regclient", + "@com_github_regclient_regclient//types/ref", + "@io_k8s_api//apps/v1:apps", + "@io_k8s_api//core/v1:core", + "@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm", + "@io_k8s_kubernetes//cmd/kubeadm/app/images", + "@io_k8s_kubernetes//cmd/kubeadm/app/phases/addons/dns", + "@io_k8s_kubernetes//cmd/kubeadm/app/util", + "@io_k8s_sigs_yaml//:yaml", + ], +) + +go_binary( + name = "corednsgen", + embed = [":corednsgen_lib"], + visibility = ["//:__subpackages__"], +) diff --git a/internal/constellation/helm/corednsgen/corednsgen.go b/internal/constellation/helm/corednsgen/corednsgen.go new file mode 100644 index 000000000..5c7bc08f2 --- /dev/null +++ b/internal/constellation/helm/corednsgen/corednsgen.go @@ -0,0 +1,181 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +// corednsgen synthesizes a Helm chart from the resource templates embedded in +// kubeadm and writes it to the `charts` directory underneath the current +// working directory. This removes the existing `coredns` subdirectory! +package main + +import ( + "context" + "flag" + "fmt" + "log" + "os" + "path/filepath" + + "github.com/edgelesssys/constellation/v2/internal/versions" + "github.com/regclient/regclient" + "github.com/regclient/regclient/types/ref" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/images" + kubedns "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + "sigs.k8s.io/yaml" +) + +const configMapName = "edg-coredns" + +var chartDir = flag.String("charts", "./charts", "target directory to create charts in") + +func main() { + flag.Parse() + + if err := os.RemoveAll(filepath.Join(*chartDir, "coredns")); err != nil { + log.Fatalf("Could not remove chart dir: %v", err) + } + + writeFileRelativeToChartDir(chartYAML(), "Chart.yaml") + writeFileRelativeToChartDir(valuesYAML(), "values.yaml") + + writeTemplate(kubedns.CoreDNSServiceAccount, "serviceaccount.yaml") + writeTemplate(kubedns.CoreDNSClusterRole, "clusterrole.yaml") + writeTemplate(kubedns.CoreDNSClusterRoleBinding, "clusterrolebinding.yaml") + writeTemplate(kubedns.CoreDNSService, "service.yaml") + + writeFileRelativeToChartDir(patchedConfigMap(), "templates", "configmap.yaml") + writeFileRelativeToChartDir(patchedDeployment(), "templates", "deployment.yaml") +} + +func chartYAML() []byte { + chart := map[string]string{ + "apiVersion": "v2", + "name": "kube-dns", + "version": "0.0.0", + } + data, err := yaml.Marshal(chart) + if err != nil { + log.Fatalf("Could not marshal Chart.yaml: %v", err) + } + return data +} + +func valuesYAML() []byte { + cfg := &kubeadm.ClusterConfiguration{ + KubernetesVersion: string(versions.Default), + ImageRepository: "registry.k8s.io", + } + img := images.GetDNSImage(cfg) + ref, err := ref.New(img) + if err != nil { + log.Fatalf("Could not parse image reference: %v", err) + } + + rc := regclient.New() + m, err := rc.ManifestGet(context.Background(), ref) + if err != nil { + log.Fatalf("Could not get image manifest: %v", err) + } + + values := map[string]string{ + "clusterIP": "10.96.0.10", + "dnsDomain": "cluster.local", + "image": fmt.Sprintf("%s/%s:%s@%s", ref.Registry, ref.Repository, ref.Tag, m.GetDescriptor().Digest.String()), + } + data, err := yaml.Marshal(values) + if err != nil { + log.Fatalf("Could not marshal values.yaml: %v", err) + } + return data +} + +// patchedConfigMap renames the CoreDNS ConfigMap such that kubeadm does not find it. +// +// See https://github.com/kubernetes/kubeadm/issues/2846#issuecomment-1899942683. +func patchedConfigMap() []byte { + var cm corev1.ConfigMap + if err := yaml.Unmarshal(parseTemplate(kubedns.CoreDNSConfigMap), &cm); err != nil { + log.Fatalf("Could not parse configmap: %v", err) + } + + cm.Name = configMapName + + out, err := yaml.Marshal(cm) + if err != nil { + log.Fatalf("Could not marshal patched deployment: %v", err) + } + return out +} + +// patchedDeployment extracts the CoreDNS Deployment from kubeadm, adds necessary tolerations and updates the ConfigMap reference. +func patchedDeployment() []byte { + var d appsv1.Deployment + if err := yaml.Unmarshal(parseTemplate(kubedns.CoreDNSDeployment), &d); err != nil { + log.Fatalf("Could not parse deployment: %v", err) + } + + tolerations := []corev1.Toleration{ + {Key: "node.cloudprovider.kubernetes.io/uninitialized", Value: "true", Effect: corev1.TaintEffectNoSchedule}, + {Key: "node.kubernetes.io/unreachable", Operator: corev1.TolerationOpExists, Effect: corev1.TaintEffectNoExecute, TolerationSeconds: toPtr(int64(10))}, + } + d.Spec.Template.Spec.Tolerations = append(d.Spec.Template.Spec.Tolerations, tolerations...) + + for i, vol := range d.Spec.Template.Spec.Volumes { + if vol.ConfigMap != nil { + vol.ConfigMap.Name = configMapName + } + d.Spec.Template.Spec.Volumes[i] = vol + } + + out, err := yaml.Marshal(d) + if err != nil { + log.Fatalf("Could not marshal patched deployment: %v", err) + } + return out +} + +func writeFileRelativeToChartDir(content []byte, pathElements ...string) { + p := filepath.Join(append([]string{*chartDir, "coredns"}, pathElements...)...) + d := filepath.Dir(p) + if err := os.MkdirAll(d, 0o755); err != nil { + log.Fatalf("Could not create dir %q: %v", d, err) + } + if err := os.WriteFile(p, content, 0o644); err != nil { + log.Fatalf("Could not write file %q: %v", p, err) + } +} + +// parseTemplate replaces the Go template placeholders in kubeadm resources +// with fixed values or Helm value placeholders. +func parseTemplate(tmpl string) []byte { + vars := struct { + DeploymentName, Image, ControlPlaneTaintKey, DNSDomain, DNSIP string + Replicas *int32 + }{ + DeploymentName: "coredns", + DNSDomain: `{{ .Values.dnsDomain }}`, + DNSIP: `"{{ .Values.clusterIP }}"`, + Image: `"{{ .Values.image }}"`, + ControlPlaneTaintKey: "node-role.kubernetes.io/control-plane", + Replicas: toPtr(int32(2)), + } + data, err := kubeadmutil.ParseTemplate(tmpl, vars) + if err != nil { + log.Fatalf("Could not interpolate template: %v", err) + } + return data +} + +func writeTemplate(tmpl string, name string) { + data := parseTemplate(tmpl) + writeFileRelativeToChartDir(data, "templates", name) +} + +func toPtr[T any](v T) *T { + return &v +} diff --git a/internal/constellation/helm/generateCertManager.sh b/internal/constellation/helm/generateCertManager.sh index 02b98676e..80df82775 100755 --- a/internal/constellation/helm/generateCertManager.sh +++ b/internal/constellation/helm/generateCertManager.sh @@ -5,7 +5,7 @@ set -o errtrace shopt -s inherit_errexit echo "Pulling cert-manager Helm chart..." -version="1.12.6" +version="1.15.0" function cleanup { rm -rf "charts/cert-manager/README.md" "charts/cert-manager-v${version}.tgz" @@ -38,7 +38,7 @@ yq eval -i '.cainjector.image.digest = "sha256:'"${v}"'"' charts/cert-manager/va v=$(get_sha256_hash "cert-manager-acmesolver") yq eval -i '.acmesolver.image.digest = "sha256:'"${v}"'"' charts/cert-manager/values.yaml -v=$(get_sha256_hash "cert-manager-ctl") +v=$(get_sha256_hash "cert-manager-startupapicheck") yq eval -i '.startupapicheck.image.digest = "sha256:'"${v}"'"' charts/cert-manager/values.yaml echo # final newline diff --git a/internal/constellation/helm/generateCilium.sh b/internal/constellation/helm/generateCilium.sh index df2a625bd..0517552ba 100755 --- a/internal/constellation/helm/generateCilium.sh +++ b/internal/constellation/helm/generateCilium.sh @@ -21,14 +21,13 @@ git clone \ --no-checkout \ --sparse \ --depth 1 \ - -b 1.15.0-pre.3 \ - https://github.com/cilium/cilium.git + -b v1.15.8-edg.0 \ + https://github.com/edgelesssys/cilium.git cd cilium git sparse-checkout add install/kubernetes/cilium git checkout -git apply "${calldir}/cilium.patch" cp -r install/kubernetes/cilium "${calldir}/charts" echo # final newline diff --git a/internal/constellation/helm/helm.go b/internal/constellation/helm/helm.go index dcc994c6c..474044138 100644 --- a/internal/constellation/helm/helm.go +++ b/internal/constellation/helm/helm.go @@ -91,6 +91,7 @@ type Options struct { HelmWaitMode WaitMode ApplyTimeout time.Duration OpenStackValues *OpenStackValues + ServiceCIDR string } // PrepareApply loads the charts and returns the executor to apply them. @@ -114,7 +115,8 @@ func (h Client) loadReleases( ) ([]release, error) { helmLoader := newLoader(flags.CSP, flags.AttestationVariant, flags.K8sVersion, stateFile, h.cliVersion) h.log.Debug("Created new Helm loader") - return helmLoader.loadReleases(flags.Conformance, flags.DeployCSIDriver, flags.HelmWaitMode, secret, serviceAccURI, flags.OpenStackValues) + // TODO(burgerdev): pass down the entire flags struct + return helmLoader.loadReleases(flags.Conformance, flags.DeployCSIDriver, flags.HelmWaitMode, secret, serviceAccURI, flags.OpenStackValues, flags.ServiceCIDR) } // Applier runs the Helm actions. diff --git a/internal/constellation/helm/helm_test.go b/internal/constellation/helm/helm_test.go index cd8aab6a6..e22a5fb21 100644 --- a/internal/constellation/helm/helm_test.go +++ b/internal/constellation/helm/helm_test.go @@ -194,11 +194,12 @@ func TestHelmApply(t *testing.T) { awsLbVersion = *tc.clusterAWSLBVersion } - certManagerVersion := "v1.12.6" // current version + certManagerVersion := "v1.15.0" // current version if tc.clusterCertManagerVersion != nil { certManagerVersion = *tc.clusterCertManagerVersion } - helmListVersion(lister, "cilium", "v1.15.0-pre.3-edg.3") + helmListVersion(lister, "cilium", "v1.15.8-edg.0") + helmListVersion(lister, "coredns", "v0.0.0") helmListVersion(lister, "cert-manager", certManagerVersion) helmListVersion(lister, "constellation-services", tc.clusterMicroServiceVersion) helmListVersion(lister, "constellation-operators", tc.clusterMicroServiceVersion) diff --git a/internal/constellation/helm/loader.go b/internal/constellation/helm/loader.go index a3c6a50fa..dfbe31209 100644 --- a/internal/constellation/helm/loader.go +++ b/internal/constellation/helm/loader.go @@ -15,9 +15,9 @@ import ( "strings" "github.com/pkg/errors" - "helm.sh/helm/pkg/ignore" "helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chart/loader" + "helm.sh/helm/v3/pkg/ignore" "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" @@ -31,6 +31,7 @@ import ( // Run `go generate` to download (and patch) upstream helm charts. //go:generate ./generateCilium.sh +//go:generate go run ./corednsgen/ //go:generate ./update-csi-charts.sh //go:generate ./generateCertManager.sh //go:generate ./update-aws-load-balancer-chart.sh @@ -46,6 +47,7 @@ type chartInfo struct { var ( // Charts we fetch from an upstream with real versions. + coreDNSInfo = chartInfo{releaseName: "coredns", chartName: "coredns", path: "charts/coredns"} ciliumInfo = chartInfo{releaseName: "cilium", chartName: "cilium", path: "charts/cilium"} certManagerInfo = chartInfo{releaseName: "cert-manager", chartName: "cert-manager", path: "charts/cert-manager"} awsLBControllerInfo = chartInfo{releaseName: "aws-load-balancer-controller", chartName: "aws-load-balancer-controller", path: "charts/aws-load-balancer-controller"} @@ -124,7 +126,7 @@ type OpenStackValues struct { // loadReleases loads the embedded helm charts and returns them as a HelmReleases object. func (i *chartLoader) loadReleases(conformanceMode, deployCSIDriver bool, helmWaitMode WaitMode, masterSecret uri.MasterSecret, - serviceAccURI string, openStackValues *OpenStackValues, + serviceAccURI string, openStackValues *OpenStackValues, serviceCIDR string, ) (releaseApplyOrder, error) { ciliumRelease, err := i.loadRelease(ciliumInfo, helmWaitMode) if err != nil { @@ -133,6 +135,16 @@ func (i *chartLoader) loadReleases(conformanceMode, deployCSIDriver bool, helmWa ciliumVals := extraCiliumValues(i.csp, conformanceMode, i.stateFile.Infrastructure) ciliumRelease.values = mergeMaps(ciliumRelease.values, ciliumVals) + coreDNSRelease, err := i.loadRelease(coreDNSInfo, helmWaitMode) + if err != nil { + return nil, fmt.Errorf("loading coredns: %w", err) + } + coreDNSVals, err := extraCoreDNSValues(serviceCIDR) + if err != nil { + return nil, fmt.Errorf("loading coredns values: %w", err) + } + coreDNSRelease.values = mergeMaps(coreDNSRelease.values, coreDNSVals) + certManagerRelease, err := i.loadRelease(certManagerInfo, helmWaitMode) if err != nil { return nil, fmt.Errorf("loading cert-manager: %w", err) @@ -156,7 +168,7 @@ func (i *chartLoader) loadReleases(conformanceMode, deployCSIDriver bool, helmWa } conServicesRelease.values = mergeMaps(conServicesRelease.values, svcVals) - releases := releaseApplyOrder{ciliumRelease, conServicesRelease, certManagerRelease, operatorRelease} + releases := releaseApplyOrder{ciliumRelease, coreDNSRelease, conServicesRelease, certManagerRelease, operatorRelease} if deployCSIDriver { csiRelease, err := i.loadRelease(csiInfo, WaitModeNone) if err != nil { @@ -224,6 +236,8 @@ func (i *chartLoader) loadRelease(info chartInfo, helmWaitMode WaitMode) (releas values = i.loadAWSLBControllerValues() case csiInfo.releaseName: values = i.loadCSIValues() + default: + values = map[string]any{} } // Charts we package ourselves have version 0.0.0. @@ -367,16 +381,18 @@ func (i *chartLoader) loadCiliumValues(cloudprovider.Provider) (map[string]any, "image": map[string]any{ "repository": "ghcr.io/edgelesssys/cilium/cilium", "suffix": "", - "tag": "v1.15.0-pre.3-edg.2", - "digest": "sha256:c21b7fbbb084a128a479d6170e5f89ad2768dfecb4af10ee6a99ffe5d1a11749", + "tag": "v1.15.8-edg.0", + "digest": "sha256:67aedd821a732e9ba3e34d200c389122384b70c05ba9a5ffb6ad813a53f2d4db", "useDigest": true, }, "operator": map[string]any{ "image": map[string]any{ - "repository": "ghcr.io/edgelesssys/cilium/operator", - "suffix": "", - "tag": "v1.15.0-pre.3-edg.2", - "genericDigest": "sha256:4ea9de5cfeb4554b82b509f0de41120a90e35a15e81a04f76c4cb405ddea3e7c", + "repository": "ghcr.io/edgelesssys/cilium/operator", + "suffix": "", + "tag": "v1.15.8-edg.0", + // Careful: this is the digest of ghcr.io/.../operator-generic! + // See magic image manipulation in ./helm/charts/cilium/templates/cilium-operator/_helpers.tpl. + "genericDigest": "sha256:dd41e2a65c607ac929d872f10b9d0c3eff88aafa99e7c062e9c240b14943dd2e", "useDigest": true, }, "podDisruptionBudget": map[string]any{ diff --git a/internal/constellation/helm/loader_test.go b/internal/constellation/helm/loader_test.go index 762f544b3..765bbf221 100644 --- a/internal/constellation/helm/loader_test.go +++ b/internal/constellation/helm/loader_test.go @@ -94,7 +94,7 @@ func TestLoadReleases(t *testing.T) { helmReleases, err := chartLoader.loadReleases( true, false, WaitModeAtomic, uri.MasterSecret{Key: []byte("secret"), Salt: []byte("masterSalt")}, - fakeServiceAccURI(cloudprovider.GCP), nil, + fakeServiceAccURI(cloudprovider.GCP), nil, "172.16.128.0/17", ) require.NoError(err) for _, release := range helmReleases { @@ -260,6 +260,55 @@ func TestConstellationServices(t *testing.T) { } } +func TestExtraCoreDNSValues(t *testing.T) { + testCases := map[string]struct { + cidr string + wantIP string + wantUnset bool + wantErr bool + }{ + "default": { + cidr: "10.96.0.0/12", + wantIP: "10.96.0.10", + }, + "custom": { + cidr: "172.16.128.0/17", + wantIP: "172.16.128.10", + }, + "too small": { + cidr: "172.16.0.0/30", + wantErr: true, + }, + "bad ip": { + cidr: "cluster.local", + wantErr: true, + }, + "v6": { + cidr: "fd12:3456:789a:100::/56", + wantIP: "fd12:3456:789a:100::a", + }, + "no ip": { + wantUnset: true, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + values, err := extraCoreDNSValues(tc.cidr) + if tc.wantErr { + assert.Error(t, err) + return + } + ip, ok := values["clusterIP"] + if tc.wantUnset { + assert.False(t, ok) + return + } + assert.Equal(t, tc.wantIP, ip) + }) + } +} + // TestOperators checks if the rendered constellation-services chart produces the expected yaml files. func TestOperators(t *testing.T) { testCases := map[string]struct { diff --git a/internal/constellation/helm/overrides.go b/internal/constellation/helm/overrides.go index 2ef690935..fdadaac88 100644 --- a/internal/constellation/helm/overrides.go +++ b/internal/constellation/helm/overrides.go @@ -21,8 +21,21 @@ import ( "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constellation/state" "github.com/edgelesssys/constellation/v2/internal/kms/uri" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) +func extraCoreDNSValues(serviceCIDR string) (map[string]any, error) { + if serviceCIDR == "" { + return map[string]any{}, nil + } + ip, err := kubeadmconstants.GetDNSIP(serviceCIDR) + if err != nil { + return nil, fmt.Errorf("calculating DNS service IP: %w", err) + } + + return map[string]any{"clusterIP": ip.String()}, nil +} + // TODO(malt3): switch over to DNS name on AWS and Azure // soon as every apiserver certificate of every control-plane node // has the dns endpoint in its SAN list. @@ -73,7 +86,6 @@ func extraCiliumValues(provider cloudprovider.Provider, conformanceMode bool, ou // Since there should always be workarounds, we only support this mode to // pass the K8s conformance tests. It is not supported to switch to or from // this mode after Constellation has been initialized. - // This only works for the K8s conformance tests up to K8s 1.28. if conformanceMode { extraVals["kubeProxyReplacementHealthzBindAddr"] = "" extraVals["kubeProxyReplacement"] = "false" @@ -87,6 +99,9 @@ func extraCiliumValues(provider cloudprovider.Provider, conformanceMode bool, ou extraVals["bpf"] = map[string]any{ "masquerade": false, } + extraVals["k8s"] = map[string]any{ + "serviceProxyName": "cilium", + } } return extraVals @@ -228,7 +243,7 @@ func getCCMConfig(azureState state.Azure, serviceAccURI string) ([]byte, error) ResourceGroup: azureState.ResourceGroup, LoadBalancerSku: "standard", SecurityGroupName: azureState.NetworkSecurityGroupName, - LoadBalancerName: azureState.LoadBalancerName, + LoadBalancerName: "kubernetes-lb", UseInstanceMetadata: true, VMType: "vmss", Location: creds.Location, diff --git a/internal/constellation/helm/testdata/AWS/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml b/internal/constellation/helm/testdata/AWS/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml index fa9f582a4..e364d1498 100644 --- a/internal/constellation/helm/testdata/AWS/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml +++ b/internal/constellation/helm/testdata/AWS/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml @@ -15,7 +15,13 @@ rules: resources: - namespaces verbs: + - create + - delete - get + - list + - patch + - update + - watch - apiGroups: - "" resources: diff --git a/internal/constellation/helm/testdata/Azure/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml b/internal/constellation/helm/testdata/Azure/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml index fa9f582a4..e364d1498 100644 --- a/internal/constellation/helm/testdata/Azure/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml +++ b/internal/constellation/helm/testdata/Azure/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml @@ -15,7 +15,13 @@ rules: resources: - namespaces verbs: + - create + - delete - get + - list + - patch + - update + - watch - apiGroups: - "" resources: diff --git a/internal/constellation/helm/testdata/GCP/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml b/internal/constellation/helm/testdata/GCP/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml index fa9f582a4..e364d1498 100644 --- a/internal/constellation/helm/testdata/GCP/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml +++ b/internal/constellation/helm/testdata/GCP/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml @@ -15,7 +15,13 @@ rules: resources: - namespaces verbs: + - create + - delete - get + - list + - patch + - update + - watch - apiGroups: - "" resources: diff --git a/internal/constellation/helm/testdata/OpenStack/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml b/internal/constellation/helm/testdata/OpenStack/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml index fa9f582a4..e364d1498 100644 --- a/internal/constellation/helm/testdata/OpenStack/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml +++ b/internal/constellation/helm/testdata/OpenStack/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml @@ -15,7 +15,13 @@ rules: resources: - namespaces verbs: + - create + - delete - get + - list + - patch + - update + - watch - apiGroups: - "" resources: diff --git a/internal/constellation/helm/testdata/QEMU/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml b/internal/constellation/helm/testdata/QEMU/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml index fa9f582a4..e364d1498 100644 --- a/internal/constellation/helm/testdata/QEMU/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml +++ b/internal/constellation/helm/testdata/QEMU/constellation-operators/charts/node-maintenance-operator/templates/manager-rbac.yaml @@ -15,7 +15,13 @@ rules: resources: - namespaces verbs: + - create + - delete - get + - list + - patch + - update + - watch - apiGroups: - "" resources: diff --git a/internal/constellation/helm/update-csi-charts.sh b/internal/constellation/helm/update-csi-charts.sh index 96dba4a02..de3486226 100755 --- a/internal/constellation/helm/update-csi-charts.sh +++ b/internal/constellation/helm/update-csi-charts.sh @@ -68,13 +68,13 @@ download_chart() { } ## AWS CSI Driver -download_chart "https://github.com/edgelesssys/constellation-aws-ebs-csi-driver" "v1.1.1" "charts/aws-ebs-csi-driver" "aws-csi-driver" +download_chart "https://github.com/edgelesssys/constellation-aws-ebs-csi-driver" "v1.2.0" "charts/aws-ebs-csi-driver" "aws-csi-driver" ## Azure CSI Driver -download_chart "https://github.com/edgelesssys/constellation-azuredisk-csi-driver" "v1.3.0" "charts/edgeless" "azuredisk-csi-driver" +download_chart "https://github.com/edgelesssys/constellation-azuredisk-csi-driver" "v1.4.0" "charts/edgeless" "azuredisk-csi-driver" ## GCP CSI Driver -download_chart "https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver" "v1.3.0" "charts" "gcp-compute-persistent-disk-csi-driver" +download_chart "https://github.com/edgelesssys/constellation-gcp-compute-persistent-disk-csi-driver" "v1.4.0" "charts" "gcp-compute-persistent-disk-csi-driver" ## OpenStack CSI Driver (cinder) download_chart "https://github.com/edgelesssys/constellation-cloud-provider-openstack" "v1.0.2" "charts/cinder-csi-plugin" "openstack-cinder-csi" diff --git a/internal/grpc/atlscredentials/BUILD.bazel b/internal/grpc/atlscredentials/BUILD.bazel index 8f16bd02f..c69ef3bda 100644 --- a/internal/grpc/atlscredentials/BUILD.bazel +++ b/internal/grpc/atlscredentials/BUILD.bazel @@ -21,7 +21,7 @@ go_test( "//internal/atls", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//test/bufconn", "@org_uber_go_goleak//:goleak", ], diff --git a/internal/grpc/atlscredentials/atlscredentials_test.go b/internal/grpc/atlscredentials/atlscredentials_test.go index a9ddaa6ac..5753eb631 100644 --- a/internal/grpc/atlscredentials/atlscredentials_test.go +++ b/internal/grpc/atlscredentials/atlscredentials_test.go @@ -66,7 +66,7 @@ func TestATLSCredentials(t *testing.T) { go func() { var err error defer func() { errChan <- err }() - conn, err := grpc.DialContext(context.Background(), "", grpc.WithContextDialer(func(_ context.Context, _ string) (net.Conn, error) { + conn, err := grpc.NewClient("192.0.2.1", grpc.WithContextDialer(func(_ context.Context, _ string) (net.Conn, error) { return lis.Dial() }), grpc.WithTransportCredentials(clientCreds)) require.NoError(err) diff --git a/internal/grpc/dialer/BUILD.bazel b/internal/grpc/dialer/BUILD.bazel index b8428ba2d..9dc1aaf8f 100644 --- a/internal/grpc/dialer/BUILD.bazel +++ b/internal/grpc/dialer/BUILD.bazel @@ -9,7 +9,7 @@ go_library( deps = [ "//internal/atls", "//internal/grpc/atlscredentials", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//credentials/insecure", ], ) @@ -25,7 +25,7 @@ go_test( "//internal/grpc/testdialer", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//interop/grpc_testing", "@org_uber_go_goleak//:goleak", ], diff --git a/internal/grpc/dialer/dialer.go b/internal/grpc/dialer/dialer.go index 8c42f4041..44bf33d87 100644 --- a/internal/grpc/dialer/dialer.go +++ b/internal/grpc/dialer/dialer.go @@ -34,14 +34,14 @@ func New(issuer atls.Issuer, validator atls.Validator, netDialer NetDialer) *Dia } // Dial creates a new grpc client connection to the given target using the atls validator. -func (d *Dialer) Dial(ctx context.Context, target string) (*grpc.ClientConn, error) { +func (d *Dialer) Dial(target string) (*grpc.ClientConn, error) { var validators []atls.Validator if d.validator != nil { validators = append(validators, d.validator) } credentials := atlscredentials.New(d.issuer, validators) - return grpc.DialContext(ctx, target, + return grpc.NewClient(target, d.grpcWithDialer(), grpc.WithTransportCredentials(credentials), ) @@ -49,18 +49,18 @@ func (d *Dialer) Dial(ctx context.Context, target string) (*grpc.ClientConn, err // DialInsecure creates a new grpc client connection to the given target without using encryption or verification. // Only use this method when using another kind of encryption / verification (VPN, etc). -func (d *Dialer) DialInsecure(ctx context.Context, target string) (*grpc.ClientConn, error) { - return grpc.DialContext(ctx, target, +func (d *Dialer) DialInsecure(target string) (*grpc.ClientConn, error) { + return grpc.NewClient(target, d.grpcWithDialer(), grpc.WithTransportCredentials(insecure.NewCredentials()), ) } // DialNoVerify creates a new grpc client connection to the given target without verifying the server's attestation. -func (d *Dialer) DialNoVerify(ctx context.Context, target string) (*grpc.ClientConn, error) { +func (d *Dialer) DialNoVerify(target string) (*grpc.ClientConn, error) { credentials := atlscredentials.New(nil, nil) - return grpc.DialContext(ctx, target, + return grpc.NewClient(target, d.grpcWithDialer(), grpc.WithTransportCredentials(credentials), ) diff --git a/internal/grpc/dialer/dialer_test.go b/internal/grpc/dialer/dialer_test.go index c137ee727..6c93c64f9 100644 --- a/internal/grpc/dialer/dialer_test.go +++ b/internal/grpc/dialer/dialer_test.go @@ -28,42 +28,42 @@ func TestMain(m *testing.M) { func TestDial(t *testing.T) { testCases := map[string]struct { tls bool - dialFn func(dialer *Dialer, ctx context.Context, target string) (*grpc.ClientConn, error) + dialFn func(dialer *Dialer, target string) (*grpc.ClientConn, error) wantErr bool }{ "Dial with tls on server works": { tls: true, - dialFn: func(dialer *Dialer, ctx context.Context, target string) (*grpc.ClientConn, error) { - return dialer.Dial(ctx, target) + dialFn: func(dialer *Dialer, target string) (*grpc.ClientConn, error) { + return dialer.Dial(target) }, }, "Dial without tls on server fails": { - dialFn: func(dialer *Dialer, ctx context.Context, target string) (*grpc.ClientConn, error) { - return dialer.Dial(ctx, target) + dialFn: func(dialer *Dialer, target string) (*grpc.ClientConn, error) { + return dialer.Dial(target) }, wantErr: true, }, "DialNoVerify with tls on server works": { tls: true, - dialFn: func(dialer *Dialer, ctx context.Context, target string) (*grpc.ClientConn, error) { - return dialer.DialNoVerify(ctx, target) + dialFn: func(dialer *Dialer, target string) (*grpc.ClientConn, error) { + return dialer.DialNoVerify(target) }, }, "DialNoVerify without tls on server fails": { - dialFn: func(dialer *Dialer, ctx context.Context, target string) (*grpc.ClientConn, error) { - return dialer.DialNoVerify(ctx, target) + dialFn: func(dialer *Dialer, target string) (*grpc.ClientConn, error) { + return dialer.DialNoVerify(target) }, wantErr: true, }, "DialInsecure without tls on server works": { - dialFn: func(dialer *Dialer, ctx context.Context, target string) (*grpc.ClientConn, error) { - return dialer.DialInsecure(ctx, target) + dialFn: func(dialer *Dialer, target string) (*grpc.ClientConn, error) { + return dialer.DialInsecure(target) }, }, "DialInsecure with tls on server fails": { tls: true, - dialFn: func(dialer *Dialer, ctx context.Context, target string) (*grpc.ClientConn, error) { - return dialer.DialInsecure(ctx, target) + dialFn: func(dialer *Dialer, target string) (*grpc.ClientConn, error) { + return dialer.DialInsecure(target) }, wantErr: true, }, @@ -81,7 +81,7 @@ func TestDial(t *testing.T) { grpc_testing.RegisterTestServiceServer(server, api) go server.Serve(netDialer.GetListener("192.0.2.1:1234")) defer server.Stop() - conn, err := tc.dialFn(dialer, context.Background(), "192.0.2.1:1234") + conn, err := tc.dialFn(dialer, "192.0.2.1:1234") require.NoError(err) defer conn.Close() diff --git a/internal/kubernetes/kubectl/kubectl.go b/internal/kubernetes/kubectl/kubectl.go index f61488082..dae2e2db6 100644 --- a/internal/kubernetes/kubectl/kubectl.go +++ b/internal/kubernetes/kubectl/kubectl.go @@ -188,65 +188,6 @@ func (k *Kubectl) PatchFirstNodePodCIDR(ctx context.Context, firstNodePodCIDR st return err } -// EnforceCoreDNSSpread adds a pod anti-affinity to the CoreDNS deployment to ensure that -// CoreDNS pods are spread across nodes. -func (k *Kubectl) EnforceCoreDNSSpread(ctx context.Context) error { - // allow CoreDNS Pods to run on uninitialized nodes, which is required by cloud-controller-manager - tolerationSeconds := int64(10) - tolerations := []corev1.Toleration{ - { - Key: "node.cloudprovider.kubernetes.io/uninitialized", - Value: "true", - Effect: corev1.TaintEffectNoSchedule, - }, - { - Key: "node.kubernetes.io/unreachable", - Operator: corev1.TolerationOpExists, - Effect: corev1.TaintEffectNoExecute, - TolerationSeconds: &tolerationSeconds, - }, - } - - deployments := k.AppsV1().Deployments("kube-system") - // retry resource update if an error occurs - return retry.RetryOnConflict(retry.DefaultRetry, func() error { - result, err := deployments.Get(ctx, "coredns", metav1.GetOptions{}) - if err != nil { - return fmt.Errorf("failed to get Deployment to add toleration: %w", err) - } - - result.Spec.Template.Spec.Tolerations = append(result.Spec.Template.Spec.Tolerations, tolerations...) - - if result.Spec.Template.Spec.Affinity == nil { - result.Spec.Template.Spec.Affinity = &corev1.Affinity{} - } - if result.Spec.Template.Spec.Affinity.PodAntiAffinity == nil { - result.Spec.Template.Spec.Affinity.PodAntiAffinity = &corev1.PodAntiAffinity{} - } - result.Spec.Template.Spec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution = []corev1.WeightedPodAffinityTerm{} - if result.Spec.Template.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil { - result.Spec.Template.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution = []corev1.PodAffinityTerm{} - } - - result.Spec.Template.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution = append(result.Spec.Template.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution, - corev1.PodAffinityTerm{ - LabelSelector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{ - { - Key: "k8s-app", - Operator: metav1.LabelSelectorOpIn, - Values: []string{"kube-dns"}, - }, - }, - }, - TopologyKey: "kubernetes.io/hostname", - }) - - _, err = deployments.Update(ctx, result, metav1.UpdateOptions{}) - return err - }) -} - // AddNodeSelectorsToDeployment adds [K8s selectors] to the deployment, identified // by name and namespace. // diff --git a/internal/logger/BUILD.bazel b/internal/logger/BUILD.bazel index 4b8daad96..10f753f44 100644 --- a/internal/logger/BUILD.bazel +++ b/internal/logger/BUILD.bazel @@ -12,7 +12,7 @@ go_library( visibility = ["//:__subpackages__"], deps = [ "@com_github_grpc_ecosystem_go_grpc_middleware_v2//interceptors/logging", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//grpclog", ], ) diff --git a/internal/logger/grpclogger.go b/internal/logger/grpclogger.go index 716b0e495..d67e4af8e 100644 --- a/internal/logger/grpclogger.go +++ b/internal/logger/grpclogger.go @@ -19,24 +19,28 @@ import ( func replaceGRPCLogger(log *slog.Logger) { gl := &grpcLogger{ - logger: log.With(slog.String("system", "grpc"), slog.Bool("grpc_log", true)), + logger: log, verbosity: 0, } grpclog.SetLoggerV2(gl) } func (l *grpcLogger) log(level slog.Level, args ...interface{}) { - var pcs [1]uintptr - runtime.Callers(3, pcs[:]) - r := slog.NewRecord(time.Now(), level, fmt.Sprint(args...), pcs[0]) - _ = l.logger.Handler().Handle(context.Background(), r) + if l.logger.Enabled(context.Background(), level) { + var pcs [1]uintptr + runtime.Callers(3, pcs[:]) + r := slog.NewRecord(time.Now(), level, fmt.Sprint(args...), pcs[0]) + _ = l.logger.Handler().Handle(context.Background(), r) + } } func (l *grpcLogger) logf(level slog.Level, format string, args ...interface{}) { - var pcs [1]uintptr - runtime.Callers(3, pcs[:]) - r := slog.NewRecord(time.Now(), level, fmt.Sprintf(format, args...), pcs[0]) - _ = l.logger.Handler().Handle(context.Background(), r) + if l.logger.Enabled(context.Background(), level) { + var pcs [1]uintptr + runtime.Callers(3, pcs[:]) + r := slog.NewRecord(time.Now(), level, fmt.Sprintf(format, args...), pcs[0]) + _ = l.logger.Handler().Handle(context.Background(), r) + } } type grpcLogger struct { diff --git a/internal/logger/levelhandler.go b/internal/logger/levelhandler.go index f0e4e1544..201bc90a0 100644 --- a/internal/logger/levelhandler.go +++ b/internal/logger/levelhandler.go @@ -13,45 +13,45 @@ import ( // LevelHandler copied from the official LevelHandler example in the slog package documentation. -// LevelHandler wraps a Handler with an Enabled method +// levelHandler wraps a Handler with an Enabled method // that returns false for levels below a minimum. -type LevelHandler struct { +type levelHandler struct { level slog.Leveler handler slog.Handler } -// NewLevelHandler returns a LevelHandler with the given level. +// newLevelHandler returns a LevelHandler with the given level. // All methods except Enabled delegate to h. -func NewLevelHandler(level slog.Leveler, h slog.Handler) *LevelHandler { +func newLevelHandler(level slog.Leveler, h slog.Handler) *levelHandler { // Optimization: avoid chains of LevelHandlers. - if lh, ok := h.(*LevelHandler); ok { + if lh, ok := h.(*levelHandler); ok { h = lh.Handler() } - return &LevelHandler{level, h} + return &levelHandler{level, h} } // Enabled implements Handler.Enabled by reporting whether // level is at least as large as h's level. -func (h *LevelHandler) Enabled(_ context.Context, level slog.Level) bool { +func (h *levelHandler) Enabled(_ context.Context, level slog.Level) bool { return level >= h.level.Level() } // Handle implements Handler.Handle. -func (h *LevelHandler) Handle(ctx context.Context, r slog.Record) error { +func (h *levelHandler) Handle(ctx context.Context, r slog.Record) error { return h.handler.Handle(ctx, r) } // WithAttrs implements Handler.WithAttrs. -func (h *LevelHandler) WithAttrs(attrs []slog.Attr) slog.Handler { - return NewLevelHandler(h.level, h.handler.WithAttrs(attrs)) +func (h *levelHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + return newLevelHandler(h.level, h.handler.WithAttrs(attrs)) } // WithGroup implements Handler.WithGroup. -func (h *LevelHandler) WithGroup(name string) slog.Handler { - return NewLevelHandler(h.level, h.handler.WithGroup(name)) +func (h *levelHandler) WithGroup(name string) slog.Handler { + return newLevelHandler(h.level, h.handler.WithGroup(name)) } // Handler returns the Handler wrapped by h. -func (h *LevelHandler) Handler() slog.Handler { +func (h *levelHandler) Handler() slog.Handler { return h.handler } diff --git a/internal/logger/log.go b/internal/logger/log.go index d8d62b13a..0b6426b6e 100644 --- a/internal/logger/log.go +++ b/internal/logger/log.go @@ -35,6 +35,11 @@ import ( "google.golang.org/grpc" ) +// GRPCLogger returns a logger at warn level for gRPC logging. +func GRPCLogger(l *slog.Logger) *slog.Logger { + return slog.New(newLevelHandler(slog.LevelWarn, l.Handler())).WithGroup("gRPC") +} + // ReplaceGRPCLogger replaces grpc's internal logger with the given logger. func ReplaceGRPCLogger(l *slog.Logger) { replaceGRPCLogger(l) diff --git a/internal/maa/patch.go b/internal/maa/patch.go index 5dfed9435..d9ac35b4c 100644 --- a/internal/maa/patch.go +++ b/internal/maa/patch.go @@ -9,6 +9,7 @@ import ( "context" "encoding/base64" "fmt" + "io" "net/http" "github.com/Azure/azure-sdk-for-go/profiles/latest/attestation/attestation" @@ -55,10 +56,11 @@ func (p AzurePolicyPatcher) Patch(ctx context.Context, attestationURL string) er if err != nil { return fmt.Errorf("sending request: %w", err) } - resp.Body.Close() + defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return fmt.Errorf("updating attestation policy: unexpected status code: %s", resp.Status) + body, _ := io.ReadAll(resp.Body) + return fmt.Errorf("updating attestation policy: unexpected status code: %s: %s", resp.Status, string(body)) } return nil diff --git a/internal/osimage/uplosi/uplosiupload.go b/internal/osimage/uplosi/uplosiupload.go index 2b54b2c33..588f332aa 100644 --- a/internal/osimage/uplosi/uplosiupload.go +++ b/internal/osimage/uplosi/uplosiupload.go @@ -255,7 +255,7 @@ func azureReplicationRegions(attestationVariant string) []string { case "azure-tdx": return []string{"northeurope", "westeurope", "centralus", "eastus2"} case "azure-sev-snp": - return []string{"northeurope", "westeurope", "germanywestcentral", "eastus", "westus", "southeastasia"} + return []string{"northeurope", "westeurope", "germanywestcentral", "eastus", "eastus2", "westus", "southeastasia"} } return nil } diff --git a/internal/verify/verify.go b/internal/verify/verify.go index d674c4237..27e5db853 100644 --- a/internal/verify/verify.go +++ b/internal/verify/verify.go @@ -157,7 +157,7 @@ func getCertChain(cfg config.AttestationCfg) ([]byte, error) { return certChain, nil } -// FormatString builds a string representation of a report that is inteded for console output. +// FormatString builds a string representation of a report that is intended for console output. func (r *Report) FormatString(b *strings.Builder) (string, error) { if len(r.ReportSigner) != 1 { return "", fmt.Errorf("expected exactly one report signing certificate, found %d", len(r.ReportSigner)) diff --git a/internal/versions/components/components.pb.go b/internal/versions/components/components.pb.go index c3436fa85..92b834075 100644 --- a/internal/versions/components/components.pb.go +++ b/internal/versions/components/components.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.1 -// protoc v4.22.1 +// protoc-gen-go v1.35.1 +// protoc v5.29.0--rc2 // source: internal/versions/components/components.proto package components @@ -33,11 +33,9 @@ type Component struct { func (x *Component) Reset() { *x = Component{} - if protoimpl.UnsafeEnabled { - mi := &file_internal_versions_components_components_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_internal_versions_components_components_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Component) String() string { @@ -48,7 +46,7 @@ func (*Component) ProtoMessage() {} func (x *Component) ProtoReflect() protoreflect.Message { mi := &file_internal_versions_components_components_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -125,7 +123,7 @@ func file_internal_versions_components_components_proto_rawDescGZIP() []byte { } var file_internal_versions_components_components_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_internal_versions_components_components_proto_goTypes = []interface{}{ +var file_internal_versions_components_components_proto_goTypes = []any{ (*Component)(nil), // 0: components.Component } var file_internal_versions_components_components_proto_depIdxs = []int32{ @@ -141,20 +139,6 @@ func file_internal_versions_components_components_proto_init() { if File_internal_versions_components_components_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_internal_versions_components_components_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Component); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/internal/versions/versions.go b/internal/versions/versions.go index fabf426be..7bf21840b 100644 --- a/internal/versions/versions.go +++ b/internal/versions/versions.go @@ -100,12 +100,12 @@ func ResolveK8sPatchVersion(k8sVersion string) (string, error) { // supported patch version as PATCH. func k8sVersionFromMajorMinor(version string) string { switch version { - case semver.MajorMinor(string(V1_27)): - return string(V1_27) case semver.MajorMinor(string(V1_28)): return string(V1_28) case semver.MajorMinor(string(V1_29)): return string(V1_29) + case semver.MajorMinor(string(V1_30)): + return string(V1_30) default: return "" } @@ -169,26 +169,26 @@ const ( // GcpGuestImage image for GCP guest agent. // Check for new versions at https://github.com/GoogleCloudPlatform/guest-agent/releases and update in /.github/workflows/build-gcp-guest-agent.yml. - GcpGuestImage = "ghcr.io/edgelesssys/gcp-guest-agent:v20240314.0.0@sha256:56f5f5250056174c82cffe6b3190838f4e001cf6375eeea0b7847d679e0a600f" // renovate:container + GcpGuestImage = "ghcr.io/edgelesssys/gcp-guest-agent:v20240816.0.0@sha256:a6f871346da12d95a1961cb247343ccaa708039f49999ce56d00e35f3f701b97" // renovate:container // NodeMaintenanceOperatorImage is the image for the node maintenance operator. - NodeMaintenanceOperatorImage = "quay.io/medik8s/node-maintenance-operator:v0.15.0@sha256:8cb8dad93283268282c30e75c68f4bd76b28def4b68b563d2f9db9c74225d634" // renovate:container + NodeMaintenanceOperatorImage = "quay.io/medik8s/node-maintenance-operator:v0.17.0@sha256:bf1c5758b3d266dd6234422d156c67ffdd47f50f70ce17d5cef1de6065030337" // renovate:container // LogstashImage is the container image of logstash, used for log collection by debugd. - LogstashImage = "ghcr.io/edgelesssys/constellation/logstash-debugd:v2.17.0-pre.0.20240513104207-d76c9ac82de7@sha256:e7d77bea381354c58fd9783eb9e2b846b14ea846d531eb3c54d5dd89917908c4" // renovate:container + LogstashImage = "ghcr.io/edgelesssys/constellation/logstash-debugd:v2.17.0-pre.0.20240627193502-8aed4bb0fe45@sha256:d6c5a06049e5c1b9d7ba4b83367fa0c06ba2d1b65e1d299f3e00f465f310642b" // renovate:container // FilebeatImage is the container image of filebeat, used for log collection by debugd. - FilebeatImage = "ghcr.io/edgelesssys/constellation/filebeat-debugd:v2.17.0-pre.0.20240513104207-d76c9ac82de7@sha256:6567d682385c06b49f6d56fdf3f20d5c24809bbfced15b816f4717bf837fc776" // renovate:container + FilebeatImage = "ghcr.io/edgelesssys/constellation/filebeat-debugd:v2.17.0-pre.0.20240627193502-8aed4bb0fe45@sha256:606adccf544a15e6b9ae9e11eec707668660bc1af346ff72559404e36da5baa2" // renovate:container // MetricbeatImage is the container image of filebeat, used for log collection by debugd. - MetricbeatImage = "ghcr.io/edgelesssys/constellation/metricbeat-debugd:v2.17.0-pre.0.20240513104207-d76c9ac82de7@sha256:d16fe0371fbb383ca3cfa70d4d10ea5124fd87054bfac189ce5458ba350bb25d" // renovate:container + MetricbeatImage = "ghcr.io/edgelesssys/constellation/metricbeat-debugd:v2.17.0-pre.0.20240627193502-8aed4bb0fe45@sha256:690b9d36cc334a7f83b58ca905169bb9f1c955b7a436c0044a07f4ce15a90594" // renovate:container // currently supported versions. //nolint:revive - V1_27 ValidK8sVersion = "v1.27.13" // renovate:kubernetes-release + V1_28 ValidK8sVersion = "v1.28.14" // renovate:kubernetes-release //nolint:revive - V1_28 ValidK8sVersion = "v1.28.9" // renovate:kubernetes-release + V1_29 ValidK8sVersion = "v1.29.9" // renovate:kubernetes-release //nolint:revive - V1_29 ValidK8sVersion = "v1.29.4" // renovate:kubernetes-release + V1_30 ValidK8sVersion = "v1.30.5" // renovate:kubernetes-release // Default k8s version deployed by Constellation. - Default ValidK8sVersion = V1_28 + Default ValidK8sVersion = V1_29 ) // Regenerate the hashes by running go generate. @@ -197,206 +197,206 @@ const ( // VersionConfigs holds download URLs for all required kubernetes components for every supported version. var VersionConfigs = map[ValidK8sVersion]KubernetesVersion{ - V1_27: { - ClusterVersion: "v1.27.13", // renovate:kubernetes-release - KubernetesComponents: components.Components{ - { - Url: "https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz", // renovate:cni-plugins-release - Hash: "sha256:c2485ddb3ffc176578ae30ae58137f0b88e50f7c7f2af7d53a569276b2949a33", - InstallPath: constants.CniPluginsDir, - Extract: true, - }, - { - Url: "https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.28.0/crictl-v1.28.0-linux-amd64.tar.gz", // renovate:crictl-release - Hash: "sha256:8dc78774f7cbeaf787994d386eec663f0a3cf24de1ea4893598096cb39ef2508", - InstallPath: constants.BinDir, - Extract: true, - }, - { - Url: "https://storage.googleapis.com/kubernetes-release/release/v1.27.13/bin/linux/amd64/kubelet", // renovate:kubernetes-release - Hash: "sha256:ed68df2a77f3057ab47f57eacb6e9310e91731e4f43c58a3c3b5c857d78d0080", - InstallPath: constants.KubeletPath, - Extract: false, - }, - { - Url: "https://storage.googleapis.com/kubernetes-release/release/v1.27.13/bin/linux/amd64/kubeadm", // renovate:kubernetes-release - Hash: "sha256:b88c30b7067f095b7fa02c5560cc50d6e69a5a9fecc606ef477dc7efc86453b9", - InstallPath: constants.KubeadmPath, - Extract: false, - }, - { - Url: "https://storage.googleapis.com/kubernetes-release/release/v1.27.13/bin/linux/amd64/kubectl", // renovate:kubernetes-release - Hash: "sha256:e991f163197cbd85bbff22f656a74d48b69db5addfa43cc04cca0cf5328f57f1", - InstallPath: constants.KubectlPath, - Extract: false, - }, - { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtYXBpc2VydmVyOnYxLjI3LjEzQHNoYTI1Njo3YTM0YmZlYjcxOWMyNmEwOWJmMjZiZjUxYjhiZjM0N2Q0MWY0ZWQ1ZTMwZTkzNGY2Y2E3M2FjMTk3MjA3NGE3In1d", - InstallPath: patchFilePath("kube-apiserver"), - }, - { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtY29udHJvbGxlci1tYW5hZ2VyOnYxLjI3LjEzQHNoYTI1Njo5NGVmNzdkZDQxNzYzZjMwZDNkOGViNWNhNWZhNzIwZjI4OWMyNGZlNTc5NGE3YTYyZTJkYTEwODJiOTVkMjhlIn1d", - InstallPath: patchFilePath("kube-controller-manager"), - }, - { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtc2NoZWR1bGVyOnYxLjI3LjEzQHNoYTI1NjpkMTA4NDI0NTk5ZmI3NjI1NDQxNmIwYTU2MDlkYjUzMGE4YmQzNzJhNzg4N2ZiNTYzNjc1MzI4ODU5YmRmZWIyIn1d", - InstallPath: patchFilePath("kube-scheduler"), - }, - { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2V0Y2Q6My41LjEyLTBAc2hhMjU2OjQ0YThlMjRkY2JiYTM0NzBlZTFmZWUyMWQ1ZTg4ZDEyOGM5MzZlOWI1NWQ0YmM1MWZiZWY4MDg2ZjhlZDEyM2IifV0=", - InstallPath: patchFilePath("etcd"), - }, - }, - // CloudControllerManagerImageAWS is the CCM image used on AWS. - CloudControllerManagerImageAWS: "registry.k8s.io/provider-aws/cloud-controller-manager:v1.27.6@sha256:1891fb7f0cef58a657854ce553fcbda1a98b7a7418a17688055ca014f6451f2b", // renovate:container - // CloudControllerManagerImageAzure is the CCM image used on Azure. - // Check for newer versions at https://github.com/kubernetes-sigs/cloud-provider-azure/blob/master/README.md. - CloudControllerManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-controller-manager:v1.27.17@sha256:fc2eb36fbf5ba8e854da02574ce434a7a02669180fdb6dba4c068a072985ac47", // renovate:container - // CloudNodeManagerImageAzure is the cloud-node-manager image used on Azure. - // Check for newer versions at https://github.com/kubernetes-sigs/cloud-provider-azure/blob/master/README.md. - CloudNodeManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-node-manager:v1.27.17@sha256:f7ba1998387e669f148b70e5ca7269d75fd9e10cd638ae107f8da0540f6d0ac1", // renovate:container - // CloudControllerManagerImageGCP is the CCM image used on GCP. - // TODO(3u13r): use newer "cloud-provider-gcp" from https://github.com/kubernetes/cloud-provider-gcp when newer releases are available. - CloudControllerManagerImageGCP: "ghcr.io/edgelesssys/cloud-provider-gcp:v27.1.6@sha256:b097b4e5382ea1987db5996a9eaffb94fa224639b3464876f0b1b17f64509ac4", // renovate:container - // CloudControllerManagerImageOpenStack is the CCM image used on OpenStack. - CloudControllerManagerImageOpenStack: "docker.io/k8scloudprovider/openstack-cloud-controller-manager:v1.26.4@sha256:05e846fb13481b6dbe4a1e50491feb219e8f5101af6cf662a086115735624db0", // renovate:container - // External service image. Depends on k8s version. - // Check for new versions at https://github.com/kubernetes/autoscaler/releases. - ClusterAutoscalerImage: "registry.k8s.io/autoscaling/cluster-autoscaler:v1.27.5@sha256:410ffc3f7307b6173c630de8de6e40175376c8c170d64b6c8b6e4baadda020df", // renovate:container - }, V1_28: { - ClusterVersion: "v1.28.9", // renovate:kubernetes-release + ClusterVersion: "v1.28.14", // renovate:kubernetes-release KubernetesComponents: components.Components{ { - Url: "https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz", // renovate:cni-plugins-release - Hash: "sha256:c2485ddb3ffc176578ae30ae58137f0b88e50f7c7f2af7d53a569276b2949a33", + Url: "https://github.com/containernetworking/plugins/releases/download/v1.6.0/cni-plugins-linux-amd64-v1.6.0.tgz", // renovate:cni-plugins-release + Hash: "sha256:682b49ff8933a997a52107161f1745f8312364b4c7f605ccdf7a77499130d89d", InstallPath: constants.CniPluginsDir, Extract: true, }, { - Url: "https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.28.0/crictl-v1.28.0-linux-amd64.tar.gz", // renovate:crictl-release - Hash: "sha256:8dc78774f7cbeaf787994d386eec663f0a3cf24de1ea4893598096cb39ef2508", + Url: "https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.31.1/crictl-v1.31.1-linux-amd64.tar.gz", // renovate:crictl-release + Hash: "sha256:0a03ba6b1e4c253d63627f8d210b2ea07675a8712587e697657b236d06d7d231", InstallPath: constants.BinDir, Extract: true, }, { - Url: "https://storage.googleapis.com/kubernetes-release/release/v1.28.9/bin/linux/amd64/kubelet", // renovate:kubernetes-release - Hash: "sha256:f3af46cff11c675a80d91ebb38ebc4e85a9f813ce93e56ee131e7fea1491b786", + Url: "https://dl.k8s.io/v1.28.14/bin/linux/amd64/kubelet", // renovate:kubernetes-release + Hash: "sha256:783b94ac980e9813626c51b0bc92b0b25bc8a61eec447b1c48aa5eaba1016b5f", InstallPath: constants.KubeletPath, Extract: false, }, { - Url: "https://storage.googleapis.com/kubernetes-release/release/v1.28.9/bin/linux/amd64/kubeadm", // renovate:kubernetes-release - Hash: "sha256:a4d8acf0a74cb1d07d96a1a34148f54c6420874221af16d8ec902d9bffc7ef89", + Url: "https://dl.k8s.io/v1.28.14/bin/linux/amd64/kubeadm", // renovate:kubernetes-release + Hash: "sha256:2fd2f8269a3baa8248f598cfbea8d2234291726fd534d17211b55a1ffb6b8c9b", InstallPath: constants.KubeadmPath, Extract: false, }, { - Url: "https://storage.googleapis.com/kubernetes-release/release/v1.28.9/bin/linux/amd64/kubectl", // renovate:kubernetes-release - Hash: "sha256:b4693d0b22f509250694b10c7727c42b427d570af04f2065fe23a55d6c0051f1", + Url: "https://dl.k8s.io/v1.28.14/bin/linux/amd64/kubectl", // renovate:kubernetes-release + Hash: "sha256:e1e8c08f7fc0b47e5d89422e573c3a2e658d95f1ee0c7ea6c8cb38f37140e607", InstallPath: constants.KubectlPath, Extract: false, }, { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtYXBpc2VydmVyOnYxLjI4LjlAc2hhMjU2OjdkMTFjNjJiMjRjZjVkM2ViMWZmZDZhYzMxNWU2MzI4ZmExYWUyMzk2ZDQ1NzJkNDY3NDA0M2U5YTdkZDRlYzIifV0=", + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtYXBpc2VydmVyOnYxLjI4LjE0QHNoYTI1NjpkYWEyNTI3YjlhMzlkZjA3OGFmN2JjZGRjZjk2YTM2OTdjYWI0YjNkNTdlYmRkNGU0ZTFiODAwZmEzNzczMGZiIn1d", InstallPath: patchFilePath("kube-apiserver"), }, { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtY29udHJvbGxlci1tYW5hZ2VyOnYxLjI4LjlAc2hhMjU2OmZmNmRhMTYxNGIyMTJjNGNiMDI3ZGI2NjQwYzJmMDAyYTA3MjNiMzg1N2JlOWE2OWUzZWM2YWQ0ZWE4YTVlMWMifV0=", + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtY29udHJvbGxlci1tYW5hZ2VyOnYxLjI4LjE0QHNoYTI1NjoxZWE4NjcwYmRhYTc3MTY1MmNhNjBmNzc2NzJmYmYxOWI5ZGVlMGJkZmNmY2Q0MzgxMjg2YWY2M2JlYTlmMzcwIn1d", InstallPath: patchFilePath("kube-controller-manager"), }, { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtc2NoZWR1bGVyOnYxLjI4LjlAc2hhMjU2OmMyZDJmOTcyM2M0MjU0MDEwYjE4Y2YzODcwYjdmMTZkNzE3MTlkNTlhOWMxNGY5NWNjNWZhMmU1MjRkODU4NjkifV0=", + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtc2NoZWR1bGVyOnYxLjI4LjE0QHNoYTI1NjpiODc3ZjgzMzJiNDY4MzQ0ZGNiOWE1NWE4YzhiMzliMGJlODkxMDQyNWMzMDUxYWExYWZlOGQ1MWY3ZWQ5OWVkIn1d", InstallPath: patchFilePath("kube-scheduler"), }, { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2V0Y2Q6My41LjEyLTBAc2hhMjU2OjQ0YThlMjRkY2JiYTM0NzBlZTFmZWUyMWQ1ZTg4ZDEyOGM5MzZlOWI1NWQ0YmM1MWZiZWY4MDg2ZjhlZDEyM2IifV0=", + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2V0Y2Q6My41LjE1LTBAc2hhMjU2OmE2ZGM2M2U2ZThjZmEwMzA3ZDc4NTE3NjJmYTZiNjI5YWZiMThmMjhkOGFhM2ZhYjVhNmU5MWI0YWY2MDAyNmEifV0=", InstallPath: patchFilePath("etcd"), }, }, // CloudControllerManagerImageAWS is the CCM image used on AWS. - CloudControllerManagerImageAWS: "registry.k8s.io/provider-aws/cloud-controller-manager:v1.28.5@sha256:ac0579afacbf2db0e9b2dda6c777c3f27ce877c17dc29db623998ab09858ac0e", // renovate:container + // Check for newer versions at https://github.com/kubernetes/cloud-provider-aws/releases. + CloudControllerManagerImageAWS: "registry.k8s.io/provider-aws/cloud-controller-manager:v1.28.9@sha256:168905b591796fbd07cb35cd0e3f206fdb7efb30e325c9bf7fa70d1b48989f73", // renovate:container // CloudControllerManagerImageAzure is the CCM image used on Azure. // Check for newer versions at https://github.com/kubernetes-sigs/cloud-provider-azure/blob/master/README.md. - CloudControllerManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-controller-manager:v1.27.17@sha256:fc2eb36fbf5ba8e854da02574ce434a7a02669180fdb6dba4c068a072985ac47", // renovate:container + CloudControllerManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-controller-manager:v1.28.13@sha256:8b853f4f54a09c363806714189435933a8575ac6dca27e991976bd685603113e", // renovate:container // CloudNodeManagerImageAzure is the cloud-node-manager image used on Azure. // Check for newer versions at https://github.com/kubernetes-sigs/cloud-provider-azure/blob/master/README.md. - CloudNodeManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-node-manager:v1.27.17@sha256:f7ba1998387e669f148b70e5ca7269d75fd9e10cd638ae107f8da0540f6d0ac1", // renovate:container + CloudNodeManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-node-manager:v1.28.13@sha256:525ca9c8a44bbdfa9acc0a417776bb822a1bbdaaf27d9776b8dcf5b3519c346a", // renovate:container // CloudControllerManagerImageGCP is the CCM image used on GCP. - // TODO(3u13r): use newer "cloud-provider-gcp" from https://github.com/kubernetes/cloud-provider-gcp when newer releases are available. - CloudControllerManagerImageGCP: "ghcr.io/edgelesssys/cloud-provider-gcp:v27.1.6@sha256:b097b4e5382ea1987db5996a9eaffb94fa224639b3464876f0b1b17f64509ac4", // renovate:container + CloudControllerManagerImageGCP: "ghcr.io/edgelesssys/cloud-provider-gcp:v28.10.0@sha256:f3b6fa7faea27b4a303c91b3bc7ee192b050e21e27579e9f3da90ae4ba38e626", // renovate:container // CloudControllerManagerImageOpenStack is the CCM image used on OpenStack. CloudControllerManagerImageOpenStack: "docker.io/k8scloudprovider/openstack-cloud-controller-manager:v1.26.4@sha256:05e846fb13481b6dbe4a1e50491feb219e8f5101af6cf662a086115735624db0", // renovate:container // External service image. Depends on k8s version. // Check for new versions at https://github.com/kubernetes/autoscaler/releases. - ClusterAutoscalerImage: "registry.k8s.io/autoscaling/cluster-autoscaler:v1.27.5@sha256:410ffc3f7307b6173c630de8de6e40175376c8c170d64b6c8b6e4baadda020df", // renovate:container + ClusterAutoscalerImage: "registry.k8s.io/autoscaling/cluster-autoscaler:v1.28.6@sha256:acfc7fe7543f4cf2fcf8156145925bee76eb6c602bb0b8e155456c6818fe8335", // renovate:container }, V1_29: { - ClusterVersion: "v1.29.4", // renovate:kubernetes-release + ClusterVersion: "v1.29.9", // renovate:kubernetes-release KubernetesComponents: components.Components{ { - Url: "https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz", // renovate:cni-plugins-release - Hash: "sha256:c2485ddb3ffc176578ae30ae58137f0b88e50f7c7f2af7d53a569276b2949a33", + Url: "https://github.com/containernetworking/plugins/releases/download/v1.6.0/cni-plugins-linux-amd64-v1.6.0.tgz", // renovate:cni-plugins-release + Hash: "sha256:682b49ff8933a997a52107161f1745f8312364b4c7f605ccdf7a77499130d89d", InstallPath: constants.CniPluginsDir, Extract: true, }, { - Url: "https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.29.0/crictl-v1.29.0-linux-amd64.tar.gz", // renovate:crictl-release - Hash: "sha256:d16a1ffb3938f5a19d5c8f45d363bd091ef89c0bc4d44ad16b933eede32fdcbb", + Url: "https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.31.1/crictl-v1.31.1-linux-amd64.tar.gz", // renovate:crictl-release + Hash: "sha256:0a03ba6b1e4c253d63627f8d210b2ea07675a8712587e697657b236d06d7d231", InstallPath: constants.BinDir, Extract: true, }, { - Url: "https://storage.googleapis.com/kubernetes-release/release/v1.29.4/bin/linux/amd64/kubelet", // renovate:kubernetes-release - Hash: "sha256:58571f0ed62543a9bbac541e52c15d8385083113a463e23aec1341d0b5043939", + Url: "https://dl.k8s.io/v1.29.9/bin/linux/amd64/kubelet", // renovate:kubernetes-release + Hash: "sha256:1bf6e9e9a5612ea4f6e1a8f541a08be93fdf144b1430147de6916dae363c34a2", InstallPath: constants.KubeletPath, Extract: false, }, { - Url: "https://storage.googleapis.com/kubernetes-release/release/v1.29.4/bin/linux/amd64/kubeadm", // renovate:kubernetes-release - Hash: "sha256:ea20ab064f716ab7f69a36d72df340257b31c9721ea86e1cf9d70b35999ddeea", + Url: "https://dl.k8s.io/v1.29.9/bin/linux/amd64/kubeadm", // renovate:kubernetes-release + Hash: "sha256:e313046d79c3f78d487804fc32248c0575af129bc8a31bca74b191efa036e0b1", InstallPath: constants.KubeadmPath, Extract: false, }, { - Url: "https://storage.googleapis.com/kubernetes-release/release/v1.29.4/bin/linux/amd64/kubectl", // renovate:kubernetes-release - Hash: "sha256:10e343861c3cb0010161e703307ba907add2aeeeaffc6444779ad915f9889c88", + Url: "https://dl.k8s.io/v1.29.9/bin/linux/amd64/kubectl", // renovate:kubernetes-release + Hash: "sha256:7b0de2466458cc3c12cf8742dc800c77d4fa72e831aa522df65e510d33b329e2", InstallPath: constants.KubectlPath, Extract: false, }, { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtYXBpc2VydmVyOnYxLjI5LjRAc2hhMjU2OjgwYmVmODIwZTk1NzdmMTQ5ZTUyMTkxOTZmNGRlZjQ5MTJhZWQ1ZmFiYmYwN2Q3YzQxNWQyNDEwNWY5ZWMwNTkifV0=", + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtYXBpc2VydmVyOnYxLjI5LjlAc2hhMjU2OmI4ODUzOGU3ZmRmNzM1ODNjODY3MDU0MGVlYzViMzYyMGFmNzVjOWVjMjAwNDM0YTU4MTVlZTdmYmE1MDIxZjMifV0=", InstallPath: patchFilePath("kube-apiserver"), }, { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtY29udHJvbGxlci1tYW5hZ2VyOnYxLjI5LjRAc2hhMjU2OjM4YTgzMjZkZjk3ZDI4NDY4MjQ5MTcwYWE2MzI1MGI4Y2U3Yjg3OTMxNTVmZjczZTI0ZDcwOTQyNGQ1YzlmMDkifV0=", + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtY29udHJvbGxlci1tYW5hZ2VyOnYxLjI5LjlAc2hhMjU2OmYyZjE4OTczY2NiNjk5NjY4N2QxMGJhNWJkMWI4ZjMwM2UzZGQyZmVkODBmODMxYTQ0ZDJhYzgxOTFlNWJiOWIifV0=", InstallPath: patchFilePath("kube-controller-manager"), }, { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtc2NoZWR1bGVyOnYxLjI5LjRAc2hhMjU2OjhkYzZhODY1MzE2NDA0YWM3ODVmYmU4OWQ3MTY3ZmVkOThlNjljYTk4MDgyMDZiNTU2YWRmYTZkZDZkNDk3ZDAifV0=", + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtc2NoZWR1bGVyOnYxLjI5LjlAc2hhMjU2OjljMTY0MDc2ZWViYWVmZGFlYmFkNDZhNWNjZDU1MGU5ZjM4YzYzNTg4YzAyZDM1MTYzYzZhMDllMTY0YWI4YTgifV0=", InstallPath: patchFilePath("kube-scheduler"), }, { - Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2V0Y2Q6My41LjEyLTBAc2hhMjU2OjQ0YThlMjRkY2JiYTM0NzBlZTFmZWUyMWQ1ZTg4ZDEyOGM5MzZlOWI1NWQ0YmM1MWZiZWY4MDg2ZjhlZDEyM2IifV0=", + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2V0Y2Q6My41LjE1LTBAc2hhMjU2OmE2ZGM2M2U2ZThjZmEwMzA3ZDc4NTE3NjJmYTZiNjI5YWZiMThmMjhkOGFhM2ZhYjVhNmU5MWI0YWY2MDAyNmEifV0=", InstallPath: patchFilePath("etcd"), }, }, // CloudControllerManagerImageAWS is the CCM image used on AWS. - CloudControllerManagerImageAWS: "registry.k8s.io/provider-aws/cloud-controller-manager:v1.29.2@sha256:db37f9ad7cb64d2248fee5354e5d2d9311bea5f188bdf24ffc3380a4c00066c9", // renovate:container + // Check for newer versions at https://github.com/kubernetes/cloud-provider-aws/releases. + CloudControllerManagerImageAWS: "registry.k8s.io/provider-aws/cloud-controller-manager:v1.29.6@sha256:8074b8828a33fb273833e8fd374dda6a0ab10335ae8e19684fbd61eeff7d3594", // renovate:container // CloudControllerManagerImageAzure is the CCM image used on Azure. // Check for newer versions at https://github.com/kubernetes-sigs/cloud-provider-azure/blob/master/README.md. - CloudControllerManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-controller-manager:v1.28.9@sha256:7abf813ad41b8f1ed91f50bfefb6f285b367664c57758af0b5a623b65f55b34b", // renovate:container + CloudControllerManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-controller-manager:v1.29.11@sha256:2ecdca660c03b17110a4ee732230424ce0377c5b1756a4408666e40938ee976a", // renovate:container // CloudNodeManagerImageAzure is the cloud-node-manager image used on Azure. // Check for newer versions at https://github.com/kubernetes-sigs/cloud-provider-azure/blob/master/README.md. - CloudNodeManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-node-manager:v1.28.9@sha256:65285c13cc3eced1005a1c6c5f727570d781ac25f421a9e5cf169de8d7e1d6a9", // renovate:container + CloudNodeManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-node-manager:v1.29.11@sha256:17888b0ebaec6735214b85d20bdcc8062f051bc27e835454e9ef89734d34aa4b", // renovate:container // CloudControllerManagerImageGCP is the CCM image used on GCP. - // TODO(3u13r): use newer "cloud-provider-gcp" from https://github.com/kubernetes/cloud-provider-gcp when newer releases are available. - CloudControllerManagerImageGCP: "ghcr.io/edgelesssys/cloud-provider-gcp:v29.0.1@sha256:66651afaf19f7da2f60f80fd733ee8cc7d161767f34f0da4f111ff35387c5217", // renovate:container + CloudControllerManagerImageGCP: "ghcr.io/edgelesssys/cloud-provider-gcp:v29.5.1@sha256:ebbc6f5755725b6c2c81ca1d1580e2feba83572c41608b739c50f85b2e5de936", // renovate:container // CloudControllerManagerImageOpenStack is the CCM image used on OpenStack. CloudControllerManagerImageOpenStack: "docker.io/k8scloudprovider/openstack-cloud-controller-manager:v1.26.4@sha256:05e846fb13481b6dbe4a1e50491feb219e8f5101af6cf662a086115735624db0", // renovate:container // External service image. Depends on k8s version. // Check for new versions at https://github.com/kubernetes/autoscaler/releases. - ClusterAutoscalerImage: "registry.k8s.io/autoscaling/cluster-autoscaler:v1.29.0@sha256:808185c1090107f06ea69b0a5e507e387ad2ee3a3b12b7cd08ea0dac730cf58b", // renovate:container + ClusterAutoscalerImage: "registry.k8s.io/autoscaling/cluster-autoscaler:v1.29.4@sha256:786728c85787a58c6376b47d2e22cc04db3ecfdd73a52b5b9be20fd869abce2f", // renovate:container + }, + V1_30: { + ClusterVersion: "v1.30.5", // renovate:kubernetes-release + KubernetesComponents: components.Components{ + { + Url: "https://github.com/containernetworking/plugins/releases/download/v1.6.0/cni-plugins-linux-amd64-v1.6.0.tgz", // renovate:cni-plugins-release + Hash: "sha256:682b49ff8933a997a52107161f1745f8312364b4c7f605ccdf7a77499130d89d", + InstallPath: constants.CniPluginsDir, + Extract: true, + }, + { + Url: "https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.31.1/crictl-v1.31.1-linux-amd64.tar.gz", // renovate:crictl-release + Hash: "sha256:0a03ba6b1e4c253d63627f8d210b2ea07675a8712587e697657b236d06d7d231", + InstallPath: constants.BinDir, + Extract: true, + }, + { + Url: "https://dl.k8s.io/v1.30.5/bin/linux/amd64/kubelet", // renovate:kubernetes-release + Hash: "sha256:9b4b8f8b33c988372cc9c67791418028ca2cef4a4b4b8d98ab67d6f21275a11a", + InstallPath: constants.KubeletPath, + Extract: false, + }, + { + Url: "https://dl.k8s.io/v1.30.5/bin/linux/amd64/kubeadm", // renovate:kubernetes-release + Hash: "sha256:b91e32e527d3941369cee016fccb6cb12cd214a120a81d8c5f84c7cbc9e120b2", + InstallPath: constants.KubeadmPath, + Extract: false, + }, + { + Url: "https://dl.k8s.io/v1.30.5/bin/linux/amd64/kubectl", // renovate:kubernetes-release + Hash: "sha256:b8aa921a580c3d8ba473236815de5ce5173d6fbfa2ccff453fa5eef46cc5ee7a", + InstallPath: constants.KubectlPath, + Extract: false, + }, + { + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtYXBpc2VydmVyOnYxLjMwLjVAc2hhMjU2Ojc3NDZlYTU1YWQ3NGUyNGI4ZWRlYmI1M2ZiOTc5ZmZlODAyZTJiYzQ3ZTNiN2ExMmM4ZTFiMDk2MWQyNzNlZDIifV0=", + InstallPath: patchFilePath("kube-apiserver"), + }, + { + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtY29udHJvbGxlci1tYW5hZ2VyOnYxLjMwLjVAc2hhMjU2OmJiZDE1ZDI2NzI5NGEyMmEyMGJmOTJhNzdiM2ZmMGUxZGI3Y2ZiMmNlNzY5OTFkYTJhYWEwM2QwOWRiM2I2NDUifV0=", + InstallPath: patchFilePath("kube-controller-manager"), + }, + { + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2t1YmUtc2NoZWR1bGVyOnYxLjMwLjVAc2hhMjU2OjYyYzkxNzU2YTNjOWI1MzVlZjk3NjU1YTViY2NhMDVlNjdlNzViNTc4Zjc3ZmM5MDdkODU5OWExOTU5NDZlZTkifV0=", + InstallPath: patchFilePath("kube-scheduler"), + }, + { + Url: "data:application/json;base64,W3sib3AiOiJyZXBsYWNlIiwicGF0aCI6Ii9zcGVjL2NvbnRhaW5lcnMvMC9pbWFnZSIsInZhbHVlIjoicmVnaXN0cnkuazhzLmlvL2V0Y2Q6My41LjE1LTBAc2hhMjU2OmE2ZGM2M2U2ZThjZmEwMzA3ZDc4NTE3NjJmYTZiNjI5YWZiMThmMjhkOGFhM2ZhYjVhNmU5MWI0YWY2MDAyNmEifV0=", + InstallPath: patchFilePath("etcd"), + }, + }, + // CloudControllerManagerImageAWS is the CCM image used on AWS. + // Check for newer versions at https://github.com/kubernetes/cloud-provider-aws/releases. + CloudControllerManagerImageAWS: "registry.k8s.io/provider-aws/cloud-controller-manager:v1.30.3@sha256:30a1758dec30814178c787e2d50f46bb141e9f0bb2e16190ddd19df15f957874", // renovate:container + // CloudControllerManagerImageAzure is the CCM image used on Azure. + // Check for newer versions at https://github.com/kubernetes-sigs/cloud-provider-azure/blob/master/README.md. + CloudControllerManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-controller-manager:v1.30.7@sha256:03b2876f481507781a27b56a6e66c1928b7b93774e787e52a5239aefa41191e4", // renovate:container + // CloudNodeManagerImageAzure is the cloud-node-manager image used on Azure. + // Check for newer versions at https://github.com/kubernetes-sigs/cloud-provider-azure/blob/master/README.md. + CloudNodeManagerImageAzure: "mcr.microsoft.com/oss/kubernetes/azure-cloud-node-manager:v1.30.7@sha256:f18feb78e36eef88f0e23d98d798476d2bf6837de11892fe118ab043afdcd497", // renovate:container + // CloudControllerManagerImageGCP is the CCM image used on GCP. + CloudControllerManagerImageGCP: "ghcr.io/edgelesssys/cloud-provider-gcp:v30.1.0@sha256:64d2d5d4d2b5fb426c307c64ada9a61b64e797b56d9768363f145f2bd957998f", // renovate:container + // CloudControllerManagerImageOpenStack is the CCM image used on OpenStack. + CloudControllerManagerImageOpenStack: "docker.io/k8scloudprovider/openstack-cloud-controller-manager:v1.26.4@sha256:05e846fb13481b6dbe4a1e50491feb219e8f5101af6cf662a086115735624db0", // renovate:container + // External service image. Depends on k8s version. + // Check for new versions at https://github.com/kubernetes/autoscaler/releases. + ClusterAutoscalerImage: "registry.k8s.io/autoscaling/cluster-autoscaler:v1.30.2@sha256:ef370d1d06a1603c4b1e47e64bb27c3ff51cb20680712dc3d41c34f3fbf7be9f", // renovate:container }, } @@ -406,9 +406,9 @@ type KubernetesVersion struct { KubernetesComponents components.Components CloudControllerManagerImageAWS string // k8s version dependency. CloudControllerManagerImageAzure string // k8s version dependency. - CloudControllerManagerImageGCP string // Using self-built image until resolved: https://github.com/kubernetes/cloud-provider-gcp/issues/289 + CloudControllerManagerImageGCP string // Published by .github/workflows/build-ccm-gcp.yml because of https://github.com/kubernetes/cloud-provider-gcp/issues/289. CloudControllerManagerImageOpenStack string // k8s version dependency. - CloudNodeManagerImageAzure string // k8s version dependency. Same version as above. + CloudNodeManagerImageAzure string // k8s version dependency. Same version as Azure's CCM image above. ClusterAutoscalerImage string // Matches k8s versioning scheme. } diff --git a/joinservice/internal/kms/BUILD.bazel b/joinservice/internal/kms/BUILD.bazel index 35f6a6bbb..b3c7a3dc9 100644 --- a/joinservice/internal/kms/BUILD.bazel +++ b/joinservice/internal/kms/BUILD.bazel @@ -8,7 +8,7 @@ go_library( visibility = ["//joinservice:__subpackages__"], deps = [ "//keyservice/keyserviceproto", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//credentials/insecure", ], ) @@ -21,7 +21,7 @@ go_test( "//internal/logger", "//keyservice/keyserviceproto", "@com_github_stretchr_testify//assert", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//test/bufconn", "@org_uber_go_goleak//:goleak", ], diff --git a/joinservice/internal/kms/kms.go b/joinservice/internal/kms/kms.go index a3a28147d..b6115f803 100644 --- a/joinservice/internal/kms/kms.go +++ b/joinservice/internal/kms/kms.go @@ -39,7 +39,7 @@ func (c Client) GetDataKey(ctx context.Context, keyID string, length int) ([]byt // the KMS does not use aTLS since traffic is only routed through the Constellation cluster // cluster internal connections are considered trustworthy log.Info(fmt.Sprintf("Connecting to KMS at %s", c.endpoint)) - conn, err := grpc.DialContext(ctx, c.endpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.NewClient(c.endpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, err } diff --git a/joinservice/internal/server/BUILD.bazel b/joinservice/internal/server/BUILD.bazel index 409c50c0e..7e29a733c 100644 --- a/joinservice/internal/server/BUILD.bazel +++ b/joinservice/internal/server/BUILD.bazel @@ -15,7 +15,7 @@ go_library( "//internal/versions/components", "//joinservice/joinproto", "@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm/v1beta3", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//credentials", "@org_golang_google_grpc//status", diff --git a/joinservice/internal/server/server.go b/joinservice/internal/server/server.go index 0b8a98f10..21bb24d67 100644 --- a/joinservice/internal/server/server.go +++ b/joinservice/internal/server/server.go @@ -58,10 +58,11 @@ func New( // Run starts the gRPC server on the given port, using the provided tlsConfig. func (s *Server) Run(creds credentials.TransportCredentials, port string) error { - logger.ReplaceGRPCLogger(slog.New(logger.NewLevelHandler(slog.LevelWarn, s.log.Handler())).WithGroup("gRPC")) + grpcLog := logger.GRPCLogger(s.log) + logger.ReplaceGRPCLogger(grpcLog) grpcServer := grpc.NewServer( grpc.Creds(creds), - logger.GetServerUnaryInterceptor(s.log.WithGroup("gRPC")), + logger.GetServerUnaryInterceptor(grpcLog), ) joinproto.RegisterAPIServer(grpcServer, s) diff --git a/joinservice/joinproto/join.pb.go b/joinservice/joinproto/join.pb.go index 6e0a6efad..c83a02e1a 100644 --- a/joinservice/joinproto/join.pb.go +++ b/joinservice/joinproto/join.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.1 -// protoc v4.22.1 +// protoc-gen-go v1.35.1 +// protoc v5.29.0--rc2 // source: joinservice/joinproto/join.proto package joinproto @@ -37,11 +37,9 @@ type IssueJoinTicketRequest struct { func (x *IssueJoinTicketRequest) Reset() { *x = IssueJoinTicketRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_joinservice_joinproto_join_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_joinservice_joinproto_join_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *IssueJoinTicketRequest) String() string { @@ -52,7 +50,7 @@ func (*IssueJoinTicketRequest) ProtoMessage() {} func (x *IssueJoinTicketRequest) ProtoReflect() protoreflect.Message { mi := &file_joinservice_joinproto_join_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -107,11 +105,9 @@ type IssueJoinTicketResponse struct { func (x *IssueJoinTicketResponse) Reset() { *x = IssueJoinTicketResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_joinservice_joinproto_join_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_joinservice_joinproto_join_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *IssueJoinTicketResponse) String() string { @@ -122,7 +118,7 @@ func (*IssueJoinTicketResponse) ProtoMessage() {} func (x *IssueJoinTicketResponse) ProtoReflect() protoreflect.Message { mi := &file_joinservice_joinproto_join_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -218,11 +214,9 @@ type ControlPlaneCertOrKey struct { func (x *ControlPlaneCertOrKey) Reset() { *x = ControlPlaneCertOrKey{} - if protoimpl.UnsafeEnabled { - mi := &file_joinservice_joinproto_join_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_joinservice_joinproto_join_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ControlPlaneCertOrKey) String() string { @@ -233,7 +227,7 @@ func (*ControlPlaneCertOrKey) ProtoMessage() {} func (x *ControlPlaneCertOrKey) ProtoReflect() protoreflect.Message { mi := &file_joinservice_joinproto_join_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -272,11 +266,9 @@ type IssueRejoinTicketRequest struct { func (x *IssueRejoinTicketRequest) Reset() { *x = IssueRejoinTicketRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_joinservice_joinproto_join_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_joinservice_joinproto_join_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *IssueRejoinTicketRequest) String() string { @@ -287,7 +279,7 @@ func (*IssueRejoinTicketRequest) ProtoMessage() {} func (x *IssueRejoinTicketRequest) ProtoReflect() protoreflect.Message { mi := &file_joinservice_joinproto_join_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -320,11 +312,9 @@ type IssueRejoinTicketResponse struct { func (x *IssueRejoinTicketResponse) Reset() { *x = IssueRejoinTicketResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_joinservice_joinproto_join_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_joinservice_joinproto_join_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *IssueRejoinTicketResponse) String() string { @@ -335,7 +325,7 @@ func (*IssueRejoinTicketResponse) ProtoMessage() {} func (x *IssueRejoinTicketResponse) ProtoReflect() protoreflect.Message { mi := &file_joinservice_joinproto_join_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -461,7 +451,7 @@ func file_joinservice_joinproto_join_proto_rawDescGZIP() []byte { } var file_joinservice_joinproto_join_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_joinservice_joinproto_join_proto_goTypes = []interface{}{ +var file_joinservice_joinproto_join_proto_goTypes = []any{ (*IssueJoinTicketRequest)(nil), // 0: join.IssueJoinTicketRequest (*IssueJoinTicketResponse)(nil), // 1: join.IssueJoinTicketResponse (*ControlPlaneCertOrKey)(nil), // 2: join.control_plane_cert_or_key @@ -488,68 +478,6 @@ func file_joinservice_joinproto_join_proto_init() { if File_joinservice_joinproto_join_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_joinservice_joinproto_join_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IssueJoinTicketRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_joinservice_joinproto_join_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IssueJoinTicketResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_joinservice_joinproto_join_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ControlPlaneCertOrKey); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_joinservice_joinproto_join_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IssueRejoinTicketRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_joinservice_joinproto_join_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IssueRejoinTicketResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/keyservice/internal/server/BUILD.bazel b/keyservice/internal/server/BUILD.bazel index 756c76f6d..22110e200 100644 --- a/keyservice/internal/server/BUILD.bazel +++ b/keyservice/internal/server/BUILD.bazel @@ -12,7 +12,7 @@ go_library( "//internal/kms/kms", "//internal/logger", "//keyservice/keyserviceproto", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//status", ], diff --git a/keyservice/internal/server/server.go b/keyservice/internal/server/server.go index b7517bceb..8ff9bed8a 100644 --- a/keyservice/internal/server/server.go +++ b/keyservice/internal/server/server.go @@ -48,9 +48,11 @@ func (s *Server) Run(port string) error { return fmt.Errorf("failed to listen on port %s: %v", port, err) } - server := grpc.NewServer(logger.GetServerUnaryInterceptor(s.log.WithGroup("gRPC"))) + grpcLog := logger.GRPCLogger(s.log) + logger.ReplaceGRPCLogger(grpcLog) + + server := grpc.NewServer(logger.GetServerUnaryInterceptor(grpcLog)) keyserviceproto.RegisterAPIServer(server, s) - logger.ReplaceGRPCLogger(slog.New(logger.NewLevelHandler(slog.LevelWarn, s.log.Handler())).WithGroup("gRPC")) // start the server s.log.Info(fmt.Sprintf("Starting Constellation key management service on %s", listener.Addr().String())) diff --git a/keyservice/keyserviceproto/keyservice.pb.go b/keyservice/keyserviceproto/keyservice.pb.go index 37f15ecae..11e1bf4d8 100644 --- a/keyservice/keyserviceproto/keyservice.pb.go +++ b/keyservice/keyserviceproto/keyservice.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.1 -// protoc v4.22.1 +// protoc-gen-go v1.35.1 +// protoc v5.29.0--rc2 // source: keyservice/keyserviceproto/keyservice.proto package keyserviceproto @@ -35,11 +35,9 @@ type GetDataKeyRequest struct { func (x *GetDataKeyRequest) Reset() { *x = GetDataKeyRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_keyservice_keyserviceproto_keyservice_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_keyservice_keyserviceproto_keyservice_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GetDataKeyRequest) String() string { @@ -50,7 +48,7 @@ func (*GetDataKeyRequest) ProtoMessage() {} func (x *GetDataKeyRequest) ProtoReflect() protoreflect.Message { mi := &file_keyservice_keyserviceproto_keyservice_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -89,11 +87,9 @@ type GetDataKeyResponse struct { func (x *GetDataKeyResponse) Reset() { *x = GetDataKeyResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_keyservice_keyserviceproto_keyservice_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_keyservice_keyserviceproto_keyservice_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GetDataKeyResponse) String() string { @@ -104,7 +100,7 @@ func (*GetDataKeyResponse) ProtoMessage() {} func (x *GetDataKeyResponse) ProtoReflect() protoreflect.Message { mi := &file_keyservice_keyserviceproto_keyservice_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -165,7 +161,7 @@ func file_keyservice_keyserviceproto_keyservice_proto_rawDescGZIP() []byte { } var file_keyservice_keyserviceproto_keyservice_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_keyservice_keyserviceproto_keyservice_proto_goTypes = []interface{}{ +var file_keyservice_keyserviceproto_keyservice_proto_goTypes = []any{ (*GetDataKeyRequest)(nil), // 0: kms.GetDataKeyRequest (*GetDataKeyResponse)(nil), // 1: kms.GetDataKeyResponse } @@ -184,32 +180,6 @@ func file_keyservice_keyserviceproto_keyservice_proto_init() { if File_keyservice_keyserviceproto_keyservice_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_keyservice_keyserviceproto_keyservice_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetDataKeyRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_keyservice_keyserviceproto_keyservice_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetDataKeyResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/nix/cc/cryptsetup.nix b/nix/cc/cryptsetup.nix index 9687e1019..1aa8c8c37 100644 --- a/nix/cc/cryptsetup.nix +++ b/nix/cc/cryptsetup.nix @@ -11,7 +11,7 @@ pkgs.symlinkJoin { paths = packages; buildInputs = packages; postBuild = '' - tar -cf $out/closure.tar --mtime="@$SOURCE_DATE_EPOCH" --sort=name ${closure} + tar -cf $out/closure.tar --mtime="@$SOURCE_DATE_EPOCH" --sort=name --hard-dereference ${closure} echo "${rpath}" > $out/rpath cp ${cc}/nix-support/dynamic-linker $out/dynamic-linker ''; diff --git a/nix/cc/libvirt.nix b/nix/cc/libvirt.nix index 47660a97f..afb739aaf 100644 --- a/nix/cc/libvirt.nix +++ b/nix/cc/libvirt.nix @@ -11,7 +11,7 @@ pkgs.symlinkJoin { paths = packages; buildInputs = packages; postBuild = '' - tar -cf $out/closure.tar --mtime="@$SOURCE_DATE_EPOCH" --sort=name ${closure} + tar -cf $out/closure.tar --mtime="@$SOURCE_DATE_EPOCH" --sort=name --hard-dereference ${closure} tar --transform 's+^./+bin/+' -cf $out/bin-linktree.tar --mtime="@$SOURCE_DATE_EPOCH" --sort=name -C $out/bin . echo "${rpath}" > $out/rpath cp ${cc}/nix-support/dynamic-linker $out/dynamic-linker diff --git a/nix/container/vpn/sidecar.sh b/nix/container/vpn/sidecar.sh index c6720f41b..a77c8bc7a 100755 --- a/nix/container/vpn/sidecar.sh +++ b/nix/container/vpn/sidecar.sh @@ -30,10 +30,17 @@ reconcile_sip_verification() { fi } +optional_mtu() { + if [ -n "${VPN_MTU}" ]; then + printf "mtu %s" "${VPN_MTU}" + fi +} + # Set up the route from the node network namespace to the VPN pod. reconcile_route() { for cidr in ${VPN_PEER_CIDRS}; do - nsenter -t 1 -n ip route replace "${cidr}" via "$(myip)" + # shellcheck disable=SC2046 # Word splitting is intentional here. + nsenter -t 1 -n ip route replace "${cidr}" via "$(myip)" $(optional_mtu) done } diff --git a/operators/constellation-node-operator/internal/cloud/aws/client/nodeimage.go b/operators/constellation-node-operator/internal/cloud/aws/client/nodeimage.go index 61d6026ee..78c37601e 100644 --- a/operators/constellation-node-operator/internal/cloud/aws/client/nodeimage.go +++ b/operators/constellation-node-operator/internal/cloud/aws/client/nodeimage.go @@ -9,6 +9,7 @@ package client import ( "context" "fmt" + "strings" "time" "github.com/aws/aws-sdk-go-v2/service/autoscaling" @@ -207,7 +208,7 @@ func (c *Client) DeleteNode(ctx context.Context, providerID string) error { ShouldDecrementDesiredCapacity: toPtr(true), }, ) - if err != nil { + if err != nil && !isInstanceNotFoundError(err) { return fmt.Errorf("failed to terminate instance: %w", err) } @@ -217,3 +218,10 @@ func (c *Client) DeleteNode(ctx context.Context, providerID string) error { func toPtr[T any](v T) *T { return &v } + +func isInstanceNotFoundError(err error) bool { + if err == nil { + return false + } + return strings.Contains(err.Error(), "Instance Id not found") +} diff --git a/operators/constellation-node-operator/internal/cloud/aws/client/nodeimage_test.go b/operators/constellation-node-operator/internal/cloud/aws/client/nodeimage_test.go index 1bae66ec0..d939f2029 100644 --- a/operators/constellation-node-operator/internal/cloud/aws/client/nodeimage_test.go +++ b/operators/constellation-node-operator/internal/cloud/aws/client/nodeimage_test.go @@ -8,6 +8,7 @@ package client import ( "context" + "fmt" "testing" "github.com/aws/aws-sdk-go-v2/service/autoscaling" @@ -382,6 +383,10 @@ func TestDeleteNode(t *testing.T) { terminateInstanceErr: assert.AnError, wantErr: true, }, + "deleting node succeeds when the instance does not exist": { + providerID: "aws:///us-east-2a/i-00000000000000000", + terminateInstanceErr: fmt.Errorf("Instance Id not found - No managed instance found for instance ID: i-00000000000000000"), + }, } for name, tc := range testCases { t.Run(name, func(t *testing.T) { diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/BUILD.bazel b/operators/constellation-node-operator/internal/cloud/azure/client/BUILD.bazel index 2c763b1e2..ee7e27d79 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/BUILD.bazel +++ b/operators/constellation-node-operator/internal/cloud/azure/client/BUILD.bazel @@ -27,7 +27,7 @@ go_library( "@com_github_azure_azure_sdk_for_go_sdk_azcore//runtime", "@com_github_azure_azure_sdk_for_go_sdk_azcore//to", "@com_github_azure_azure_sdk_for_go_sdk_azidentity//:azidentity", - "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v5//:armcompute", + "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v6//:armcompute", "@com_github_spf13_afero//:afero", ], ) @@ -53,7 +53,7 @@ go_test( "@com_github_azure_azure_sdk_for_go_sdk_azcore//:azcore", "@com_github_azure_azure_sdk_for_go_sdk_azcore//runtime", "@com_github_azure_azure_sdk_for_go_sdk_azcore//to", - "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v5//:armcompute", + "@com_github_azure_azure_sdk_for_go_sdk_resourcemanager_compute_armcompute_v6//:armcompute", "@com_github_spf13_afero//:afero", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/api.go b/operators/constellation-node-operator/internal/cloud/azure/client/api.go index 6f77a9929..33a4369a7 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/api.go +++ b/operators/constellation-node-operator/internal/cloud/azure/client/api.go @@ -10,7 +10,7 @@ import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/internal/poller" ) diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/client.go b/operators/constellation-node-operator/internal/cloud/azure/client/client.go index af78fee88..2e767a9f7 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/client.go +++ b/operators/constellation-node-operator/internal/cloud/azure/client/client.go @@ -8,7 +8,7 @@ package client import ( "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/internal/poller" "github.com/spf13/afero" ) diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/client_test.go b/operators/constellation-node-operator/internal/cloud/azure/client/client_test.go index f798d2be8..e63904b2c 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/client_test.go +++ b/operators/constellation-node-operator/internal/cloud/azure/client/client_test.go @@ -11,7 +11,7 @@ import ( "net/http" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" ) type stubScaleSetsAPI struct { diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/instanceview.go b/operators/constellation-node-operator/internal/cloud/azure/client/instanceview.go index e55ab21c6..da38b1aef 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/instanceview.go +++ b/operators/constellation-node-operator/internal/cloud/azure/client/instanceview.go @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only package client import ( - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/api/v1alpha1" ) diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/instanceview_test.go b/operators/constellation-node-operator/internal/cloud/azure/client/instanceview_test.go index 26737e6cc..16ece38f7 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/instanceview_test.go +++ b/operators/constellation-node-operator/internal/cloud/azure/client/instanceview_test.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" "github.com/stretchr/testify/assert" updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/api/v1alpha1" diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/nodeimage.go b/operators/constellation-node-operator/internal/cloud/azure/client/nodeimage.go index 0af5c5885..8b4d438a1 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/nodeimage.go +++ b/operators/constellation-node-operator/internal/cloud/azure/client/nodeimage.go @@ -11,7 +11,7 @@ import ( "fmt" "strings" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" "github.com/edgelesssys/constellation/v2/internal/mpimage" ) diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/nodeimage_test.go b/operators/constellation-node-operator/internal/cloud/azure/client/nodeimage_test.go index 135859602..866cf535f 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/nodeimage_test.go +++ b/operators/constellation-node-operator/internal/cloud/azure/client/nodeimage_test.go @@ -13,7 +13,7 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/internal/poller" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/pendingnode_test.go b/operators/constellation-node-operator/internal/cloud/azure/client/pendingnode_test.go index aeda7edad..7c12ed749 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/pendingnode_test.go +++ b/operators/constellation-node-operator/internal/cloud/azure/client/pendingnode_test.go @@ -14,7 +14,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/api/v1alpha1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/scalinggroup.go b/operators/constellation-node-operator/internal/cloud/azure/client/scalinggroup.go index 26c682c64..470bb2d90 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/scalinggroup.go +++ b/operators/constellation-node-operator/internal/cloud/azure/client/scalinggroup.go @@ -12,7 +12,7 @@ import ( "strings" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/mpimage" updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/api/v1alpha1" diff --git a/operators/constellation-node-operator/internal/cloud/azure/client/scalinggroup_test.go b/operators/constellation-node-operator/internal/cloud/azure/client/scalinggroup_test.go index 11b65da0f..1f9e1516d 100644 --- a/operators/constellation-node-operator/internal/cloud/azure/client/scalinggroup_test.go +++ b/operators/constellation-node-operator/internal/cloud/azure/client/scalinggroup_test.go @@ -12,7 +12,7 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6" "github.com/edgelesssys/constellation/v2/internal/constants" cspapi "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/internal/cloud/api" "github.com/stretchr/testify/assert" diff --git a/operators/constellation-node-operator/internal/cloud/gcp/client/BUILD.bazel b/operators/constellation-node-operator/internal/cloud/gcp/client/BUILD.bazel index 72548055d..54100de98 100644 --- a/operators/constellation-node-operator/internal/cloud/gcp/client/BUILD.bazel +++ b/operators/constellation-node-operator/internal/cloud/gcp/client/BUILD.bazel @@ -29,6 +29,7 @@ go_library( "@com_github_spf13_afero//:afero", "@com_google_cloud_go_compute//apiv1", "@com_google_cloud_go_compute//apiv1/computepb", + "@org_golang_google_api//compute/v1:compute", "@org_golang_google_api//googleapi", "@org_golang_google_api//iterator", "@org_golang_google_protobuf//proto", @@ -61,6 +62,7 @@ go_test( "@com_github_stretchr_testify//require", "@com_google_cloud_go_compute//apiv1", "@com_google_cloud_go_compute//apiv1/computepb", + "@org_golang_google_api//compute/v1:compute", "@org_golang_google_api//googleapi", "@org_golang_google_api//iterator", "@org_golang_google_protobuf//proto", diff --git a/operators/constellation-node-operator/internal/cloud/gcp/client/api.go b/operators/constellation-node-operator/internal/cloud/gcp/client/api.go index 12966da9e..15c56ece5 100644 --- a/operators/constellation-node-operator/internal/cloud/gcp/client/api.go +++ b/operators/constellation-node-operator/internal/cloud/gcp/client/api.go @@ -12,6 +12,7 @@ import ( compute "cloud.google.com/go/compute/apiv1" "cloud.google.com/go/compute/apiv1/computepb" "github.com/googleapis/gax-go/v2" + computeREST "google.golang.org/api/compute/v1" ) type projectAPI interface { @@ -27,13 +28,9 @@ type instanceAPI interface { } type instanceTemplateAPI interface { - Close() error - Get(ctx context.Context, req *computepb.GetInstanceTemplateRequest, - opts ...gax.CallOption) (*computepb.InstanceTemplate, error) - Delete(ctx context.Context, req *computepb.DeleteInstanceTemplateRequest, - opts ...gax.CallOption) (Operation, error) - Insert(ctx context.Context, req *computepb.InsertInstanceTemplateRequest, - opts ...gax.CallOption) (Operation, error) + Get(projectID, template string) (*computeREST.InstanceTemplate, error) + Delete(projectID, template string) (*computeREST.Operation, error) + Insert(projectID string, template *computeREST.InstanceTemplate) (*computeREST.Operation, error) } type instanceGroupManagersAPI interface { diff --git a/operators/constellation-node-operator/internal/cloud/gcp/client/client.go b/operators/constellation-node-operator/internal/cloud/gcp/client/client.go index aa0a46ae7..e9dbc3a4e 100644 --- a/operators/constellation-node-operator/internal/cloud/gcp/client/client.go +++ b/operators/constellation-node-operator/internal/cloud/gcp/client/client.go @@ -14,6 +14,7 @@ import ( compute "cloud.google.com/go/compute/apiv1" "github.com/spf13/afero" + computeREST "google.golang.org/api/compute/v1" ) // Client is a client for the Google Compute Engine. @@ -48,12 +49,17 @@ func New(ctx context.Context, configPath string) (*Client, error) { return nil, err } closers = append(closers, insAPI) - templAPI, err := compute.NewInstanceTemplatesRESTClient(ctx) + + // TODO(msanft): Go back to protobuf-based API when it supports setting + // a confidential instance type. + // See https://github.com/googleapis/google-cloud-go/issues/10873 for the current status. + restClient, err := computeREST.NewService(ctx) if err != nil { _ = closeAll(closers) return nil, err } - closers = append(closers, templAPI) + templAPI := computeREST.NewInstanceTemplatesService(restClient) + groupAPI, err := compute.NewInstanceGroupManagersRESTClient(ctx) if err != nil { _ = closeAll(closers) @@ -81,7 +87,6 @@ func (c *Client) Close() error { closers := []closer{ c.projectAPI, c.instanceAPI, - c.instanceTemplateAPI, c.instanceGroupManagersAPI, c.diskAPI, } diff --git a/operators/constellation-node-operator/internal/cloud/gcp/client/client_test.go b/operators/constellation-node-operator/internal/cloud/gcp/client/client_test.go index e7779453b..58816c561 100644 --- a/operators/constellation-node-operator/internal/cloud/gcp/client/client_test.go +++ b/operators/constellation-node-operator/internal/cloud/gcp/client/client_test.go @@ -12,6 +12,7 @@ import ( compute "cloud.google.com/go/compute/apiv1" "cloud.google.com/go/compute/apiv1/computepb" "github.com/googleapis/gax-go/v2" + computeREST "google.golang.org/api/compute/v1" "google.golang.org/api/iterator" "google.golang.org/protobuf/proto" ) @@ -47,7 +48,7 @@ func (a stubInstanceAPI) Get(_ context.Context, _ *computepb.GetInstanceRequest, } type stubInstanceTemplateAPI struct { - template *computepb.InstanceTemplate + template *computeREST.InstanceTemplate getErr error deleteErr error insertErr error @@ -57,30 +58,16 @@ func (a stubInstanceTemplateAPI) Close() error { return nil } -func (a stubInstanceTemplateAPI) Get(_ context.Context, _ *computepb.GetInstanceTemplateRequest, - _ ...gax.CallOption, -) (*computepb.InstanceTemplate, error) { +func (a stubInstanceTemplateAPI) Get(_, _ string) (*computeREST.InstanceTemplate, error) { return a.template, a.getErr } -func (a stubInstanceTemplateAPI) Delete(_ context.Context, _ *computepb.DeleteInstanceTemplateRequest, - _ ...gax.CallOption, -) (Operation, error) { - return &stubOperation{ - &computepb.Operation{ - Name: proto.String("name"), - }, - }, a.deleteErr +func (a stubInstanceTemplateAPI) Delete(_, _ string) (*computeREST.Operation, error) { + return &computeREST.Operation{}, a.deleteErr } -func (a stubInstanceTemplateAPI) Insert(_ context.Context, _ *computepb.InsertInstanceTemplateRequest, - _ ...gax.CallOption, -) (Operation, error) { - return &stubOperation{ - &computepb.Operation{ - Name: proto.String("name"), - }, - }, a.insertErr +func (a stubInstanceTemplateAPI) Insert(_ string, _ *computeREST.InstanceTemplate) (*computeREST.Operation, error) { + return &computeREST.Operation{}, a.insertErr } type stubInstanceGroupManagersAPI struct { diff --git a/operators/constellation-node-operator/internal/cloud/gcp/client/gcpwrappers.go b/operators/constellation-node-operator/internal/cloud/gcp/client/gcpwrappers.go index 3d34efba7..da87f596c 100644 --- a/operators/constellation-node-operator/internal/cloud/gcp/client/gcpwrappers.go +++ b/operators/constellation-node-operator/internal/cloud/gcp/client/gcpwrappers.go @@ -12,26 +12,27 @@ import ( compute "cloud.google.com/go/compute/apiv1" "cloud.google.com/go/compute/apiv1/computepb" "github.com/googleapis/gax-go/v2" + computeREST "google.golang.org/api/compute/v1" ) type instanceTemplateClient struct { - *compute.InstanceTemplatesClient + *computeREST.InstanceTemplatesService } func (c *instanceTemplateClient) Close() error { - return c.InstanceTemplatesClient.Close() + return nil // no-op } -func (c *instanceTemplateClient) Delete(ctx context.Context, req *computepb.DeleteInstanceTemplateRequest, - opts ...gax.CallOption, -) (Operation, error) { - return c.InstanceTemplatesClient.Delete(ctx, req, opts...) +func (c *instanceTemplateClient) Get(project, template string) (*computeREST.InstanceTemplate, error) { + return c.InstanceTemplatesService.Get(project, template).Do() } -func (c *instanceTemplateClient) Insert(ctx context.Context, req *computepb.InsertInstanceTemplateRequest, - opts ...gax.CallOption, -) (Operation, error) { - return c.InstanceTemplatesClient.Insert(ctx, req, opts...) +func (c *instanceTemplateClient) Delete(project, template string) (*computeREST.Operation, error) { + return c.InstanceTemplatesService.Delete(project, template).Do() +} + +func (c *instanceTemplateClient) Insert(projectID string, template *computeREST.InstanceTemplate) (*computeREST.Operation, error) { + return c.InstanceTemplatesService.Insert(projectID, template).Do() } type instanceGroupManagersClient struct { diff --git a/operators/constellation-node-operator/internal/cloud/gcp/client/nodeimage.go b/operators/constellation-node-operator/internal/cloud/gcp/client/nodeimage.go index ddd102d39..e69750321 100644 --- a/operators/constellation-node-operator/internal/cloud/gcp/client/nodeimage.go +++ b/operators/constellation-node-operator/internal/cloud/gcp/client/nodeimage.go @@ -139,7 +139,8 @@ func (c *Client) DeleteNode(ctx context.Context, providerID string) error { Project: instanceGroupProject, Zone: instanceGroupZone, InstanceGroupManagersDeleteInstancesRequestResource: &computepb.InstanceGroupManagersDeleteInstancesRequest{ - Instances: []string{instanceID}, + Instances: []string{instanceID}, + SkipInstancesOnValidationError: toPtr(true), }, }) if err != nil { @@ -147,3 +148,7 @@ func (c *Client) DeleteNode(ctx context.Context, providerID string) error { } return op.Wait(ctx) } + +func toPtr[T any](v T) *T { + return &v +} diff --git a/operators/constellation-node-operator/internal/cloud/gcp/client/scalinggroup.go b/operators/constellation-node-operator/internal/cloud/gcp/client/scalinggroup.go index 683ad89ce..658aaea96 100644 --- a/operators/constellation-node-operator/internal/cloud/gcp/client/scalinggroup.go +++ b/operators/constellation-node-operator/internal/cloud/gcp/client/scalinggroup.go @@ -16,6 +16,7 @@ import ( "github.com/edgelesssys/constellation/v2/internal/constants" updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/api/v1alpha1" cspapi "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/internal/cloud/api" + computeREST "google.golang.org/api/compute/v1" "google.golang.org/api/iterator" ) @@ -49,29 +50,22 @@ func (c *Client) SetScalingGroupImage(ctx context.Context, scalingGroupID, image } // clone template with desired image - if instanceTemplate.Name == nil { + if instanceTemplate.Name == "" { return fmt.Errorf("instance template of scaling group %q has no name", scalingGroupID) } - instanceTemplate.Properties.Disks[0].InitializeParams.SourceImage = &imageURI - newTemplateName, err := generateInstanceTemplateName(*instanceTemplate.Name) + instanceTemplate.Properties.Disks[0].InitializeParams.SourceImage = imageURI + newTemplateName, err := generateInstanceTemplateName(instanceTemplate.Name) if err != nil { return err } - instanceTemplate.Name = &newTemplateName - op, err := c.instanceTemplateAPI.Insert(ctx, &computepb.InsertInstanceTemplateRequest{ - Project: project, - InstanceTemplateResource: instanceTemplate, - }) - if err != nil { + instanceTemplate.Name = newTemplateName + if _, err := c.instanceTemplateAPI.Insert(project, instanceTemplate); err != nil { return fmt.Errorf("cloning instance template: %w", err) } - if err := op.Wait(ctx); err != nil { - return fmt.Errorf("waiting for cloned instance template: %w", err) - } newTemplateURI := joinInstanceTemplateURI(project, newTemplateName) // update instance group manager to use new template - op, err = c.instanceGroupManagersAPI.SetInstanceTemplate(ctx, &computepb.SetInstanceTemplateInstanceGroupManagerRequest{ + op, err := c.instanceGroupManagersAPI.SetInstanceTemplate(ctx, &computepb.SetInstanceTemplateInstanceGroupManagerRequest{ InstanceGroupManager: instanceGroupName, Project: project, Zone: zone, @@ -133,10 +127,7 @@ func (c *Client) ListScalingGroups(ctx context.Context, uid string) ([]cspapi.Sc if len(templateURI) < 1 { continue // invalid template URI } - template, err := c.instanceTemplateAPI.Get(ctx, &computepb.GetInstanceTemplateRequest{ - Project: c.projectID, - InstanceTemplate: templateURI[len(templateURI)-1], - }) + template, err := c.instanceTemplateAPI.Get(c.projectID, templateURI[len(templateURI)-1]) if err != nil { return nil, fmt.Errorf("getting instance template: %w", err) } @@ -188,7 +179,7 @@ func (c *Client) ListScalingGroups(ctx context.Context, uid string) ([]cspapi.Sc return results, nil } -func (c *Client) getScalingGroupTemplate(ctx context.Context, scalingGroupID string) (*computepb.InstanceTemplate, error) { +func (c *Client) getScalingGroupTemplate(ctx context.Context, scalingGroupID string) (*computeREST.InstanceTemplate, error) { project, zone, instanceGroupName, err := splitInstanceGroupID(scalingGroupID) if err != nil { return nil, err @@ -208,22 +199,19 @@ func (c *Client) getScalingGroupTemplate(ctx context.Context, scalingGroupID str if err != nil { return nil, fmt.Errorf("splitting instance template name: %w", err) } - instanceTemplate, err := c.instanceTemplateAPI.Get(ctx, &computepb.GetInstanceTemplateRequest{ - InstanceTemplate: instanceTemplateName, - Project: instanceTemplateProject, - }) + instanceTemplate, err := c.instanceTemplateAPI.Get(instanceTemplateProject, instanceTemplateName) if err != nil { return nil, fmt.Errorf("getting instance template %q: %w", instanceTemplateName, err) } return instanceTemplate, nil } -func instanceTemplateSourceImage(instanceTemplate *computepb.InstanceTemplate) (string, error) { +func instanceTemplateSourceImage(instanceTemplate *computeREST.InstanceTemplate) (string, error) { if instanceTemplate.Properties == nil || len(instanceTemplate.Properties.Disks) == 0 || instanceTemplate.Properties.Disks[0].InitializeParams == nil || - instanceTemplate.Properties.Disks[0].InitializeParams.SourceImage == nil { + instanceTemplate.Properties.Disks[0].InitializeParams.SourceImage == "" { return "", errors.New("instance template has no source image") } - return uriNormalize(*instanceTemplate.Properties.Disks[0].InitializeParams.SourceImage), nil + return uriNormalize(instanceTemplate.Properties.Disks[0].InitializeParams.SourceImage), nil } diff --git a/operators/constellation-node-operator/internal/cloud/gcp/client/scalinggroup_test.go b/operators/constellation-node-operator/internal/cloud/gcp/client/scalinggroup_test.go index a91f49d1d..26983cb97 100644 --- a/operators/constellation-node-operator/internal/cloud/gcp/client/scalinggroup_test.go +++ b/operators/constellation-node-operator/internal/cloud/gcp/client/scalinggroup_test.go @@ -16,6 +16,7 @@ import ( cspapi "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/internal/cloud/api" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + computeREST "google.golang.org/api/compute/v1" "google.golang.org/protobuf/proto" ) @@ -23,7 +24,7 @@ func TestGetScalingGroupImage(t *testing.T) { testCases := map[string]struct { scalingGroupID string instanceGroupManagerTemplateID *string - instanceTemplate *computepb.InstanceTemplate + instanceTemplate *computeREST.InstanceTemplate getInstanceGroupManagerErr error getInstanceTemplateErr error wantImage string @@ -32,12 +33,12 @@ func TestGetScalingGroupImage(t *testing.T) { "getting image works": { scalingGroupID: "projects/project/zones/zone/instanceGroupManagers/instance-group", instanceGroupManagerTemplateID: proto.String("projects/project/global/instanceTemplates/instance-template"), - instanceTemplate: &computepb.InstanceTemplate{ - Properties: &computepb.InstanceProperties{ - Disks: []*computepb.AttachedDisk{ + instanceTemplate: &computeREST.InstanceTemplate{ + Properties: &computeREST.InstanceProperties{ + Disks: []*computeREST.AttachedDisk{ { - InitializeParams: &computepb.AttachedDiskInitializeParams{ - SourceImage: proto.String("https://www.googleapis.com/compute/v1/projects/project/global/images/image"), + InitializeParams: &computeREST.AttachedDiskInitializeParams{ + SourceImage: "https://www.googleapis.com/compute/v1/projects/project/global/images/image", }, }, }, @@ -72,8 +73,8 @@ func TestGetScalingGroupImage(t *testing.T) { "instance template has no disks": { scalingGroupID: "projects/project/zones/zone/instanceGroupManagers/instance-group", instanceGroupManagerTemplateID: proto.String("projects/project/global/instanceTemplates/instance-template"), - instanceTemplate: &computepb.InstanceTemplate{ - Properties: &computepb.InstanceProperties{}, + instanceTemplate: &computeREST.InstanceTemplate{ + Properties: &computeREST.InstanceProperties{}, }, wantErr: true, }, @@ -112,7 +113,7 @@ func TestSetScalingGroupImage(t *testing.T) { scalingGroupID string imageURI string instanceGroupManagerTemplateID *string - instanceTemplate *computepb.InstanceTemplate + instanceTemplate *computeREST.InstanceTemplate getInstanceGroupManagerErr error getInstanceTemplateErr error setInstanceTemplateErr error @@ -123,13 +124,13 @@ func TestSetScalingGroupImage(t *testing.T) { scalingGroupID: "projects/project/zones/zone/instanceGroupManagers/instance-group", imageURI: "projects/project/global/images/image-2", instanceGroupManagerTemplateID: proto.String("projects/project/global/instanceTemplates/instance-template"), - instanceTemplate: &computepb.InstanceTemplate{ - Name: proto.String("instance-template"), - Properties: &computepb.InstanceProperties{ - Disks: []*computepb.AttachedDisk{ + instanceTemplate: &computeREST.InstanceTemplate{ + Name: "instance-template", + Properties: &computeREST.InstanceProperties{ + Disks: []*computeREST.AttachedDisk{ { - InitializeParams: &computepb.AttachedDiskInitializeParams{ - SourceImage: proto.String("https://www.googleapis.com/compute/v1/projects/project/global/images/image-1"), + InitializeParams: &computeREST.AttachedDiskInitializeParams{ + SourceImage: "https://www.googleapis.com/compute/v1/projects/project/global/images/image-1", }, }, }, @@ -140,13 +141,13 @@ func TestSetScalingGroupImage(t *testing.T) { scalingGroupID: "projects/project/zones/zone/instanceGroupManagers/instance-group", imageURI: "projects/project/global/images/image", instanceGroupManagerTemplateID: proto.String("projects/project/global/instanceTemplates/instance-template"), - instanceTemplate: &computepb.InstanceTemplate{ - Name: proto.String("instance-template"), - Properties: &computepb.InstanceProperties{ - Disks: []*computepb.AttachedDisk{ + instanceTemplate: &computeREST.InstanceTemplate{ + Name: "instance-template", + Properties: &computeREST.InstanceProperties{ + Disks: []*computeREST.AttachedDisk{ { - InitializeParams: &computepb.AttachedDiskInitializeParams{ - SourceImage: proto.String("https://www.googleapis.com/compute/v1/projects/project/global/images/image"), + InitializeParams: &computeREST.AttachedDiskInitializeParams{ + SourceImage: "https://www.googleapis.com/compute/v1/projects/project/global/images/image", }, }, }, @@ -182,8 +183,8 @@ func TestSetScalingGroupImage(t *testing.T) { "instance template has no disks": { scalingGroupID: "projects/project/zones/zone/instanceGroupManagers/instance-group", instanceGroupManagerTemplateID: proto.String("projects/project/global/instanceTemplates/instance-template"), - instanceTemplate: &computepb.InstanceTemplate{ - Properties: &computepb.InstanceProperties{}, + instanceTemplate: &computeREST.InstanceTemplate{ + Properties: &computeREST.InstanceProperties{}, }, wantErr: true, }, @@ -191,12 +192,12 @@ func TestSetScalingGroupImage(t *testing.T) { scalingGroupID: "projects/project/zones/zone/instanceGroupManagers/instance-group", imageURI: "projects/project/global/images/image-2", instanceGroupManagerTemplateID: proto.String("projects/project/global/instanceTemplates/instance-template"), - instanceTemplate: &computepb.InstanceTemplate{ - Properties: &computepb.InstanceProperties{ - Disks: []*computepb.AttachedDisk{ + instanceTemplate: &computeREST.InstanceTemplate{ + Properties: &computeREST.InstanceProperties{ + Disks: []*computeREST.AttachedDisk{ { - InitializeParams: &computepb.AttachedDiskInitializeParams{ - SourceImage: proto.String("https://www.googleapis.com/compute/v1/projects/project/global/images/image-1"), + InitializeParams: &computeREST.AttachedDiskInitializeParams{ + SourceImage: "https://www.googleapis.com/compute/v1/projects/project/global/images/image-1", }, }, }, @@ -208,13 +209,13 @@ func TestSetScalingGroupImage(t *testing.T) { scalingGroupID: "projects/project/zones/zone/instanceGroupManagers/instance-group", imageURI: "projects/project/global/images/image-2", instanceGroupManagerTemplateID: proto.String("projects/project/global/instanceTemplates/instance-template"), - instanceTemplate: &computepb.InstanceTemplate{ - Name: proto.String("instance-template-999999999999999999999"), - Properties: &computepb.InstanceProperties{ - Disks: []*computepb.AttachedDisk{ + instanceTemplate: &computeREST.InstanceTemplate{ + Name: "instance-template-999999999999999999999", + Properties: &computeREST.InstanceProperties{ + Disks: []*computeREST.AttachedDisk{ { - InitializeParams: &computepb.AttachedDiskInitializeParams{ - SourceImage: proto.String("https://www.googleapis.com/compute/v1/projects/project/global/images/image-1"), + InitializeParams: &computeREST.AttachedDiskInitializeParams{ + SourceImage: "https://www.googleapis.com/compute/v1/projects/project/global/images/image-1", }, }, }, @@ -226,13 +227,13 @@ func TestSetScalingGroupImage(t *testing.T) { scalingGroupID: "projects/project/zones/zone/instanceGroupManagers/instance-group", imageURI: "projects/project/global/images/image-2", instanceGroupManagerTemplateID: proto.String("projects/project/global/instanceTemplates/instance-template"), - instanceTemplate: &computepb.InstanceTemplate{ - Name: proto.String("instance-template"), - Properties: &computepb.InstanceProperties{ - Disks: []*computepb.AttachedDisk{ + instanceTemplate: &computeREST.InstanceTemplate{ + Name: "instance-template", + Properties: &computeREST.InstanceProperties{ + Disks: []*computeREST.AttachedDisk{ { - InitializeParams: &computepb.AttachedDiskInitializeParams{ - SourceImage: proto.String("https://www.googleapis.com/compute/v1/projects/project/global/images/image-1"), + InitializeParams: &computeREST.AttachedDiskInitializeParams{ + SourceImage: "https://www.googleapis.com/compute/v1/projects/project/global/images/image-1", }, }, }, @@ -245,13 +246,13 @@ func TestSetScalingGroupImage(t *testing.T) { scalingGroupID: "projects/project/zones/zone/instanceGroupManagers/instance-group", imageURI: "projects/project/global/images/image-2", instanceGroupManagerTemplateID: proto.String("projects/project/global/instanceTemplates/instance-template"), - instanceTemplate: &computepb.InstanceTemplate{ - Name: proto.String("instance-template"), - Properties: &computepb.InstanceProperties{ - Disks: []*computepb.AttachedDisk{ + instanceTemplate: &computeREST.InstanceTemplate{ + Name: "instance-template", + Properties: &computeREST.InstanceProperties{ + Disks: []*computeREST.AttachedDisk{ { - InitializeParams: &computepb.AttachedDiskInitializeParams{ - SourceImage: proto.String("https://www.googleapis.com/compute/v1/projects/project/global/images/image-1"), + InitializeParams: &computeREST.AttachedDiskInitializeParams{ + SourceImage: "https://www.googleapis.com/compute/v1/projects/project/global/images/image-1", }, }, }, @@ -445,8 +446,8 @@ func TestListScalingGroups(t *testing.T) { }, }, instanceTemplateAPI: &stubInstanceTemplateAPI{ - template: &computepb.InstanceTemplate{ - Properties: &computepb.InstanceProperties{ + template: &computeREST.InstanceTemplate{ + Properties: &computeREST.InstanceProperties{ Labels: tc.templateLabels, }, }, diff --git a/operators/constellation-node-operator/internal/executor/executor.go b/operators/constellation-node-operator/internal/executor/executor.go index 152dc3a40..10492f88c 100644 --- a/operators/constellation-node-operator/internal/executor/executor.go +++ b/operators/constellation-node-operator/internal/executor/executor.go @@ -205,7 +205,7 @@ func (c *Config) applyDefaults() { c.PollingFrequency = defaultPollingFrequency } if c.RateLimiter == nil { - c.RateLimiter = workqueue.DefaultControllerRateLimiter() + c.RateLimiter = workqueue.DefaultTypedControllerRateLimiter[any]() } } diff --git a/operators/constellation-node-operator/internal/upgrade/BUILD.bazel b/operators/constellation-node-operator/internal/upgrade/BUILD.bazel index 546ffaf7d..cf1588a80 100644 --- a/operators/constellation-node-operator/internal/upgrade/BUILD.bazel +++ b/operators/constellation-node-operator/internal/upgrade/BUILD.bazel @@ -1,4 +1,5 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("//bazel/go:go_test.bzl", "go_test") go_library( name = "upgrade", @@ -9,7 +10,19 @@ go_library( "//internal/constants", "//internal/versions/components", "//upgrade-agent/upgradeproto", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//credentials/insecure", ], ) + +go_test( + name = "upgrade_test", + srcs = ["upgrade_test.go"], + embed = [":upgrade"], + deps = [ + "//internal/versions/components", + "//upgrade-agent/upgradeproto", + "@com_github_stretchr_testify//require", + "@org_golang_google_grpc//:grpc", + ], +) diff --git a/operators/constellation-node-operator/internal/upgrade/upgrade.go b/operators/constellation-node-operator/internal/upgrade/upgrade.go index 18813557c..7204f473d 100644 --- a/operators/constellation-node-operator/internal/upgrade/upgrade.go +++ b/operators/constellation-node-operator/internal/upgrade/upgrade.go @@ -21,24 +21,25 @@ import ( // Client is a client for the upgrade agent. type Client struct { + addr string dialer Dialer } -// NewClient creates a new upgrade agent client. +// NewClient creates a new upgrade agent client connecting to the default upgrade-agent Unix socket. func NewClient() *Client { + return newClientWithAddress(mainconstants.UpgradeAgentMountPath) +} + +func newClientWithAddress(addr string) *Client { return &Client{ + addr: "unix:" + addr, dialer: &net.Dialer{}, } } // Upgrade upgrades the Constellation node to the given Kubernetes version. func (c *Client) Upgrade(ctx context.Context, kubernetesComponents components.Components, WantedKubernetesVersion string) error { - conn, err := grpc.DialContext(ctx, mainconstants.UpgradeAgentMountPath, grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithContextDialer( - func(ctx context.Context, addr string) (net.Conn, error) { - return c.dialer.DialContext(ctx, "unix", addr) - }, - )) + conn, err := grpc.NewClient(c.addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return fmt.Errorf("failed to dial: %w", err) } diff --git a/operators/constellation-node-operator/internal/upgrade/upgrade_test.go b/operators/constellation-node-operator/internal/upgrade/upgrade_test.go new file mode 100644 index 000000000..394ffc54d --- /dev/null +++ b/operators/constellation-node-operator/internal/upgrade/upgrade_test.go @@ -0,0 +1,52 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package upgrade + +import ( + "context" + "net" + "os" + "path/filepath" + "testing" + + "github.com/edgelesssys/constellation/v2/internal/versions/components" + "github.com/edgelesssys/constellation/v2/upgrade-agent/upgradeproto" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" +) + +// TestGRPCDialer is a regression test to ensure the upgrade client can connect to a UDS. +func TestGRPCDialer(t *testing.T) { + require := require.New(t) + + dir := t.TempDir() + sockAddr := filepath.Join(dir, "test.socket") + + upgradeAgent := &fakeUpgradeAgent{} + grpcServer := grpc.NewServer() + upgradeproto.RegisterUpdateServer(grpcServer, upgradeAgent) + + listener, err := net.Listen("unix", sockAddr) + require.NoError(err) + go grpcServer.Serve(listener) + t.Cleanup(grpcServer.Stop) + + fileInfo, err := os.Stat(sockAddr) + require.NoError(err) + require.Equal(os.ModeSocket, fileInfo.Mode()&os.ModeType) + + upgradeClient := newClientWithAddress(sockAddr) + require.NoError(upgradeClient.Upgrade(context.Background(), []*components.Component{}, "v1.29.6")) +} + +type fakeUpgradeAgent struct { + upgradeproto.UnimplementedUpdateServer +} + +func (s *fakeUpgradeAgent) ExecuteUpdate(_ context.Context, _ *upgradeproto.ExecuteUpdateRequest) (*upgradeproto.ExecuteUpdateResponse, error) { + return &upgradeproto.ExecuteUpdateResponse{}, nil +} diff --git a/renovate.json5 b/renovate.json5 index d6fc3454e..8424d5473 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -56,6 +56,7 @@ "pinDigest", "rollback", ], + "schedule": ["before 8am on monday"], }, { // Group update of Terraform dependencies. @@ -71,15 +72,38 @@ "pinDigest", "rollback", ], + "schedule": ["before 8am on wednesday"], }, { "matchManagers": ["bazelisk", "bazel", "bazel-module"], - "matchDepNames": ["bazel", "io_bazel_rules_go", "bazel_gazelle"], + "matchDepNames": ["bazel", "io_bazel_rules_go", "bazel_gazelle", "rules_go", "gazelle"], "groupName": "bazel (core)", }, + { + "matchManagers": ["bazel"], + "matchDepNames": [ + "!bazel", + "!io_bazel_rules_go", + "!bazel_gazelle", + "!rules_go", + "!gazelle", + ], + "groupName": "bazel (plugins)", + }, + { + "matchManagers": ["bazel-module"], + "matchDepNames": [ + "!bazel", + "!io_bazel_rules_go", + "!bazel_gazelle", + "!rules_go", + "!gazelle", + ], + "groupName": "bazel (modules)", + }, { "matchDatasources": ["golang-version"], - "allowedVersions": "1.22", + "allowedVersions": "1.23", }, { "matchManagers": ["pip_requirements"], @@ -89,6 +113,7 @@ "matchManagers": ["github-actions"], "groupName": "GitHub action dependencies", "matchUpdateTypes": [ + "major", "minor", "patch", "pin", @@ -98,6 +123,7 @@ "rollback", "bump", ], + "schedule": ["before 8am on tuesday"], }, { "matchDepNames": ["kubernetes/kubernetes"], @@ -159,6 +185,7 @@ "ignoreUnstable": false, "groupName": "Constellation containers", "prPriority": 20, + "schedule": ["before 8am on thursday"], }, { "matchDepNames": [ @@ -219,12 +246,12 @@ "datasourceTemplate": "github-releases", }, { - "fileMatch": ["(^|\\/)versions.go$"], + "fileMatch": ["(^|\\/)versions.go$", "[.]github\\/(actions|workflows)\\/.*[.]ya?ml"], "matchStrings": [ // Match github releases. // example match:' "https://github.com/foo/bar/releases/download/v1.2.3/foo.bin" // renovate:github-release' // (foo/bar -> depName, v1.2.3 -> currentValue) - " \"https:\\/\\/github\\.com\\/(?[^\\/\\s\"]+\\/[^\\/\\s\"]+)\\/releases\\/download\\/(?[^\\/\\s\"]+)\\/[^\"]+\"[^\\n]+\\/\\/ renovate:github-release", + "https:\\/\\/github\\.com\\/(?[^\\/\\s\"]+\\/[^\\/\\s\"]+)\\/releases\\/download\\/(?[^\\/\\s\"]+).*renovate:github-release", ], "datasourceTemplate": "github-releases", }, diff --git a/rfc/016-node-access.md b/rfc/016-node-access.md new file mode 100644 index 000000000..0c6875c48 --- /dev/null +++ b/rfc/016-node-access.md @@ -0,0 +1,188 @@ +--- +status: approved, not implemented +--- + +# RFC 016: Node Access + +## Background + +A production Constellation cluster is currently configured not to allow any kind of remote administrative access. +This choice is deliberate: any mechanism for remote accesss can potentially be exploited, or may leak sensitive data. + +However, some operations on a Kubernetes cluster require some form of access to the nodes. +A good class of examples are etcd cluster maintenance tasks, like backup and recovery, or emergency operations like removing a permanently failed member. +Some kubeadm operations, like certificate rotation, also require some form of cluster access. + +While some tasks can be accomplished by DaemonSets, CronJobs and the like, relying on Kubernetes objects is insufficient. +Executing commands in a Kubernetes pod may fail because Kubernetes is not healthy, etcd is bricked or the network is down. +Administrative access to the nodes through a side channel would greatly help remediate, or at least debug, those situations. + +## Requirements + +Constellation admins can log into Constellation nodes for maintenance, subject to the following restrictions: + +* Access must be encrypted end-to-end to protect from CSP snooping. +* Access must be possible even if the Kubernetes API server is down. + +Nice-to-have: + +* The method of access should not require long-term storage of a second secret. +* The method of access should be time-limited. + +## Proposed Design + +Core to the proposal is [certificate-based authentication for OpenSSH](https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Certificate-based_Authentication). +We can derive a valid SSH key from the Constellation master secret. +An OpenSSH server on the node accepts certificates issued by this CA key. +Admins can derive the CA key from the master secret on demand, and issue certificates for arbitrary public keys. +An example program is in the [Appendix](#appendix). + +### Key Details + +We use an HKDF to derive an ed25519 private key from the master secret. +This private key acts as an SSH certificate authority, whose signed certs allow access to cluster nodes. +Since the master secret is available to both the cluster owner and the nodes, no communication with the cluster is needed to mint valid certificates. +The choice of curve allows to directly use the derived secret bytes as key. +This makes the implementation deterministic, and thus the CA key recoverable. + +### Server-side Details + +An OpenSSH server is added to the node image software stack. +It's configured with a `TrustedUserCAKeys` file and a `RevokedKeys` file, both being empty on startup. +All other means of authentication are disabled. + +After initialization, the bootstrapper fills the `TrustedUserCAKeys` file with the derived CA's public key. +Joining nodes send their public host key as part of the `IssueJoinTokenRequest` and receive the CA certificate and an indefinitely valid certificate as response. + +The `RevokedKeys` KRL is an option for the cluster administrator to revoke keys, but it's not managed by Constellation. + +### Client-side Details + +A new `ssh` subcommand is added to the CLI. +The exact name is TBD, but it should fit in with other key-related activity, like generating volume keys. +It takes the master secret file and an SSH pub key file as arguments, and writes a certificate to stdout. +Optional arguments may include principals or vailidity period. +The implementation could roughly follow the PoC in the [Appendix](#appendix). + +As an extension, the subcommand could allow generating a key pair and a matching certificate in a temp dir, and `exec` the ssh program directly. +This would encourage use of very short-lived certificates. + +## Security Considerations + +Exposing an additional service to the outside world increases the attack surface. +We propose the following mitigations: + +1. The SSH port is only exposed to the VPC. + This restricts the attackers to malicious co-tenants and the CSP. + In an emergency, admins need to add a load balancer to be able to reach the nodes. +2. A hardened OpenSSH config only allows the options strictly necessary for the scheme proposed here. + Authorized keys and passwords must be disabled. + Cipher suites should be restricted. etc. + +## Alternatives Considered + +### Enable Serial Console + +Serial consoles for cloud VMs are tunnelled through the CSP in the clear. +To make this solution secure, an encrypted channel would need to be established on top of the serial connection. +The author is not aware of any software providing such a channel. + +### SSH with Authorized Keys + +We could ask users to add a public key to their `constellation-conf.yaml` and add that to `/root/.ssh/authorized_keys` after joining. +This would require the cluster owner to permanently manage a second secret, and there would be no built-in way to revoke access. + +### Debug Pod + +Some node administration tasks can be performed with a [debug pod]. +If privileged access is required, it's usually necessary to schedule a custom pod. +This only works if the Kubernetes API server is still processing requests, pods can be scheduled on the target node and the network allows connecting to it. + +[debug pod]: https://kubernetes.io/docs/tasks/debug/debug-cluster/kubectl-node-debug/ + +### Host an Admin API Server + +There are alternatives to SSH that allow fine-grained authorization of node operations. +An example would be [SansShell], which verifies node access requests with a policy. +Setting up such a tool requires a detailed understanding of the use cases, of which some might be hard to foresee. +This may be better suited as an extension of the low-level emergency access mechanisms. + +[SansShell]: https://github.com/Snowflake-Labs/sansshell + +## Appendix + +A proof-of-concept implementation of the certificate generation. +Constellation nodes would stop after deriving the CA public key. + +```golang +package main + +import ( + "crypto/ed25519" + "crypto/rand" + "crypto/sha256" + "encoding/json" + "flag" + "fmt" + "log" + "os" + "time" + + "golang.org/x/crypto/hkdf" + "golang.org/x/crypto/ssh" +) + +type secret struct { + Key []byte `json:"key,omitempty"` + Salt []byte `json:"salt,omitempty"` +} + +var permissions = ssh.Permissions{ + Extensions: map[string]string{ + "permit-port-forwarding": "yes", + "permit-pty": "yes", + }, +} + +func main() { + masterSecret := flag.String("secret", "", "") + flag.Parse() + + secretJSON, err := os.ReadFile(*masterSecret) + must(err) + var secret secret + must(json.Unmarshal(secretJSON, &secret)) + + hkdf := hkdf.New(sha256.New, secret.Key, secret.Salt, []byte("ssh-ca")) + + _, priv, err := ed25519.GenerateKey(hkdf) + must(err) + + ca, err := ssh.NewSignerFromSigner(priv) + must(err) + + log.Printf("CA KEY: %s", string(ssh.MarshalAuthorizedKey(ca.PublicKey()))) + + buf, err := os.ReadFile(flag.Arg(0)) + must(err) + pub, _, _, _, err := ssh.ParseAuthorizedKey(buf) + must(err) + certificate := ssh.Certificate{ + Key: pub, + CertType: ssh.UserCert, + ValidAfter: uint64(time.Now().Unix()), + ValidBefore: uint64(time.Now().Add(24 * time.Hour).Unix()), + ValidPrincipals: []string{"root"}, + Permissions: permissions, + } + must(certificate.SignCert(rand.Reader, ca)) + + fmt.Printf("%s\n", string(ssh.MarshalAuthorizedKey(&certificate))) +} + +func must(err error) { + if err != nil { + log.Fatal(err) + } +} +``` diff --git a/s3proxy/deploy/s3proxy/values.yaml b/s3proxy/deploy/s3proxy/values.yaml index dd84620c5..cc41d5887 100644 --- a/s3proxy/deploy/s3proxy/values.yaml +++ b/s3proxy/deploy/s3proxy/values.yaml @@ -3,7 +3,7 @@ awsAccessKeyID: "replaceme" awsSecretAccessKey: "replaceme" # Pod image to deploy. -image: "ghcr.io/edgelesssys/constellation/s3proxy:v2.17.0" +image: "ghcr.io/edgelesssys/constellation/s3proxy:v2.18.0-pre.0.20240807132706-ffde0ef7b7d3" # Control if multipart uploads are blocked. allowMultipart: false diff --git a/s3proxy/internal/kms/BUILD.bazel b/s3proxy/internal/kms/BUILD.bazel index bb7bc1cd4..630b13818 100644 --- a/s3proxy/internal/kms/BUILD.bazel +++ b/s3proxy/internal/kms/BUILD.bazel @@ -8,7 +8,7 @@ go_library( visibility = ["//s3proxy:__subpackages__"], deps = [ "//keyservice/keyserviceproto", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//credentials/insecure", ], ) @@ -21,7 +21,7 @@ go_test( "//internal/logger", "//keyservice/keyserviceproto", "@com_github_stretchr_testify//assert", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//test/bufconn", "@org_uber_go_goleak//:goleak", ], diff --git a/s3proxy/internal/kms/kms.go b/s3proxy/internal/kms/kms.go index d6c100b20..f0d71b875 100644 --- a/s3proxy/internal/kms/kms.go +++ b/s3proxy/internal/kms/kms.go @@ -42,7 +42,7 @@ func (c Client) GetDataKey(ctx context.Context, keyID string, length int) ([]byt // the KMS does not use aTLS since traffic is only routed through the Constellation cluster // cluster internal connections are considered trustworthy log.Info("Connecting to KMS") - conn, err := grpc.DialContext(ctx, c.endpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.NewClient(c.endpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, err } diff --git a/terraform-provider-constellation/docs/data-sources/attestation.md b/terraform-provider-constellation/docs/data-sources/attestation.md index b1b8891c0..0dbf32a3d 100644 --- a/terraform-provider-constellation/docs/data-sources/attestation.md +++ b/terraform-provider-constellation/docs/data-sources/attestation.md @@ -32,8 +32,8 @@ data "constellation_attestation" "test" { * `aws-nitro-tpm` * `azure-sev-snp` * `azure-tdx` - * `gcp-sev-es` * `gcp-sev-snp` + * `gcp-sev-es` * `qemu-vtpm` - `csp` (String) CSP (Cloud Service Provider) to use. (e.g. `azure`) See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports. @@ -42,7 +42,8 @@ See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview ### Optional - `insecure` (Boolean) DON'T USE IN PRODUCTION Skip the signature verification when fetching measurements for the image. -- `maa_url` (String) For Azure only, the URL of the Microsoft Azure Attestation service +- `maa_url` (String) For Azure only, the URL of the Microsoft Azure Attestation service. The MAA's policy needs to be patched manually to work with Constellation OS images. +See the [Constellation documentation](https://docs.edgeless.systems/constellation/workflows/terraform-provider#quick-setup) for more information. ### Read-Only @@ -83,8 +84,8 @@ Read-Only: * `aws-nitro-tpm` * `azure-sev-snp` * `azure-tdx` - * `gcp-sev-es` * `gcp-sev-snp` + * `gcp-sev-es` * `qemu-vtpm` diff --git a/terraform-provider-constellation/docs/data-sources/image.md b/terraform-provider-constellation/docs/data-sources/image.md index f0b37455a..7933e93fc 100644 --- a/terraform-provider-constellation/docs/data-sources/image.md +++ b/terraform-provider-constellation/docs/data-sources/image.md @@ -31,8 +31,8 @@ data "constellation_image" "example" { * `aws-nitro-tpm` * `azure-sev-snp` * `azure-tdx` - * `gcp-sev-es` * `gcp-sev-snp` + * `gcp-sev-es` * `qemu-vtpm` - `csp` (String) CSP (Cloud Service Provider) to use. (e.g. `azure`) See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports. diff --git a/terraform-provider-constellation/docs/resources/cluster.md b/terraform-provider-constellation/docs/resources/cluster.md index 0941d3c53..556622f4b 100644 --- a/terraform-provider-constellation/docs/resources/cluster.md +++ b/terraform-provider-constellation/docs/resources/cluster.md @@ -69,7 +69,7 @@ resource "constellation_cluster" "azure_example" { See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports. - `image` (Attributes) Constellation OS Image to use on the nodes. (see [below for nested schema](#nestedatt--image)) - `init_secret` (String) Secret used for initialization of the cluster. -- `kubernetes_version` (String) The Kubernetes version to use for the cluster. The supported versions are [v1.27.13 v1.28.9 v1.29.4]. +- `kubernetes_version` (String) The Kubernetes version to use for the cluster. The supported versions are [v1.28.14 v1.29.9 v1.30.5]. - `master_secret` (String) Hex-encoded 32-byte master secret for the cluster. - `master_secret_salt` (String) Hex-encoded 32-byte master secret salt for the cluster. - `measurement_salt` (String) Hex-encoded 32-byte measurement salt for the cluster. @@ -90,8 +90,12 @@ See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview ### Read-Only +- `client_certificate` (String) The client certificate of the cluster. +- `client_key` (String, Sensitive) The client key of the cluster. +- `cluster_ca_certificate` (String) The cluster CA certificate of the cluster. - `cluster_id` (String) The cluster ID of the cluster. -- `kubeconfig` (String, Sensitive) The kubeconfig of the cluster. +- `host` (String) The host of the cluster. +- `kubeconfig` (String, Sensitive) The kubeconfig (file) of the cluster. - `owner_id` (String) The owner ID of the cluster. @@ -110,8 +114,8 @@ Required: * `aws-nitro-tpm` * `azure-sev-snp` * `azure-tdx` - * `gcp-sev-es` * `gcp-sev-snp` + * `gcp-sev-es` * `qemu-vtpm` Optional: diff --git a/terraform-provider-constellation/examples/full/aws/main.tf b/terraform-provider-constellation/examples/full/aws/main.tf index 4a467d5e4..0df608981 100644 --- a/terraform-provider-constellation/examples/full/aws/main.tf +++ b/terraform-provider-constellation/examples/full/aws/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { constellation = { source = "edgelesssys/constellation" - version = "0.0.0" // replace with the version you want to use + version = "2.17.0" // replace with the version you want to use } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } } } diff --git a/terraform-provider-constellation/examples/full/azure/main.tf b/terraform-provider-constellation/examples/full/azure/main.tf index 46a5f8f9b..d473b72a4 100644 --- a/terraform-provider-constellation/examples/full/azure/main.tf +++ b/terraform-provider-constellation/examples/full/azure/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { constellation = { source = "edgelesssys/constellation" - version = "0.0.0" // replace with the version you want to use + version = "2.17.0" // replace with the version you want to use } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } } } @@ -21,7 +21,8 @@ locals { location = "northeurope" control_plane_count = 3 worker_count = 2 - instance_type = "Standard_DC4as_v5" + instance_type = "Standard_DC4as_v5" // Adjust if using TDX + subscription_id = "00000000-0000-0000-0000-000000000000" master_secret = random_bytes.master_secret.hex master_secret_salt = random_bytes.master_secret_salt.hex @@ -43,6 +44,7 @@ resource "random_bytes" "measurement_salt" { module "azure_iam" { // replace $VERSION with the Constellation version you want to use, e.g., v2.14.0 source = "https://github.com/edgelesssys/constellation/releases/download/$VERSION/terraform-module.zip//terraform-module/iam/azure" + subscription_id = local.subscription_id location = local.location service_principal_name = "${local.name}-sp" resource_group_name = "${local.name}-rg" @@ -51,6 +53,7 @@ module "azure_iam" { module "azure_infrastructure" { // replace $VERSION with the Constellation version you want to use, e.g., v2.14.0 source = "https://github.com/edgelesssys/constellation/releases/download/$VERSION/terraform-module.zip//terraform-module/azure" + subscription_id = local.subscription_id name = local.name user_assigned_identity = module.azure_iam.uami_id node_groups = { @@ -80,7 +83,9 @@ data "constellation_attestation" "foo" { csp = local.csp attestation_variant = local.attestation_variant image = data.constellation_image.bar.image - maa_url = module.azure_infrastructure.attestation_url + # Needs to be patched manually, see: + # https://docs.edgeless.systems/constellation/workflows/terraform-provider#quick-setup + maa_url = module.azure_infrastructure.attestation_url } data "constellation_image" "bar" { diff --git a/terraform-provider-constellation/examples/full/gcp/main.tf b/terraform-provider-constellation/examples/full/gcp/main.tf index 1cbbd525c..04ede4b59 100644 --- a/terraform-provider-constellation/examples/full/gcp/main.tf +++ b/terraform-provider-constellation/examples/full/gcp/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { constellation = { source = "edgelesssys/constellation" - version = "0.0.0" // replace with the version you want to use + version = "2.17.0" // replace with the version you want to use } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } } } @@ -17,14 +17,14 @@ locals { kubernetes_version = "vX.Y.Z" microservice_version = "vX.Y.Z" csp = "gcp" - attestation_variant = "gcp-sev-es" + attestation_variant = "gcp-sev-snp" region = "europe-west3" zone = "europe-west3-b" project_id = "constellation-331613" control_plane_count = 3 worker_count = 2 instance_type = "n2d-standard-4" - cc_technology = "SEV" + cc_technology = "SEV_SNP" master_secret = random_bytes.master_secret.hex master_secret_salt = random_bytes.master_secret_salt.hex diff --git a/terraform-provider-constellation/examples/full/stackit/main.tf b/terraform-provider-constellation/examples/full/stackit/main.tf index 22ef92451..a380daec7 100644 --- a/terraform-provider-constellation/examples/full/stackit/main.tf +++ b/terraform-provider-constellation/examples/full/stackit/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { constellation = { source = "edgelesssys/constellation" - version = "0.0.0" // replace with the version you want to use + version = "2.17.0" // replace with the version you want to use } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } } } diff --git a/terraform-provider-constellation/internal/provider/BUILD.bazel b/terraform-provider-constellation/internal/provider/BUILD.bazel index 1fac7618a..8f6f573d1 100644 --- a/terraform-provider-constellation/internal/provider/BUILD.bazel +++ b/terraform-provider-constellation/internal/provider/BUILD.bazel @@ -32,6 +32,7 @@ go_library( "//internal/constellation/helm", "//internal/constellation/kubecmd", "//internal/constellation/state", + "//internal/encoding", "//internal/file", "//internal/grpc/dialer", "//internal/imagefetcher", @@ -57,6 +58,7 @@ go_library( "@com_github_hashicorp_terraform_plugin_framework_validators//stringvalidator", "@com_github_hashicorp_terraform_plugin_log//tflog", "@com_github_spf13_afero//:afero", + "@io_k8s_client_go//tools/clientcmd", ], ) diff --git a/terraform-provider-constellation/internal/provider/attestation_data_source.go b/terraform-provider-constellation/internal/provider/attestation_data_source.go index abf2921b6..f48c24a13 100644 --- a/terraform-provider-constellation/internal/provider/attestation_data_source.go +++ b/terraform-provider-constellation/internal/provider/attestation_data_source.go @@ -98,8 +98,9 @@ func (d *AttestationDataSource) Schema(_ context.Context, _ datasource.SchemaReq "attestation_variant": newAttestationVariantAttributeSchema(attributeInput), "image": newImageAttributeSchema(attributeInput), "maa_url": schema.StringAttribute{ - MarkdownDescription: "For Azure only, the URL of the Microsoft Azure Attestation service", - Optional: true, + MarkdownDescription: `For Azure only, the URL of the Microsoft Azure Attestation service. The MAA's policy needs to be patched manually to work with Constellation OS images. +See the [Constellation documentation](https://docs.edgeless.systems/constellation/workflows/terraform-provider#quick-setup) for more information.`, + Optional: true, }, "insecure": schema.BoolAttribute{ MarkdownDescription: "DON'T USE IN PRODUCTION Skip the signature verification when fetching measurements for the image.", @@ -125,6 +126,15 @@ func (d *AttestationDataSource) ValidateConfig(ctx context.Context, req datasour ) return } + + if !data.MaaURL.IsNull() { + resp.Diagnostics.AddAttributeWarning( + path.Root("maa_url"), + "Ensure that the MAA's policy is patched", "When MAA is used, please ensure the MAA's policy is patche properly for use within Constellation. See https://docs.edgeless.systems/constellation/workflows/terraform-provider#quick-setup for more information.", + ) + return + } + if data.AttestationVariant.Equal(types.StringValue("azure-sev-snp")) && data.MaaURL.IsNull() { tflog.Info(ctx, "MAA URL not set, MAA fallback will be unavailable") } @@ -162,17 +172,18 @@ func (d *AttestationDataSource) Read(ctx context.Context, req datasource.ReadReq insecureFetch := data.Insecure.ValueBool() - snpVersions := attestationconfigapi.SEVSNPVersionAPI{} - if attestationVariant.Equal(variant.AzureSEVSNP{}) || - attestationVariant.Equal(variant.AWSSEVSNP{}) || + latestVersions := attestationconfigapi.Entry{} + if attestationVariant.Equal(variant.AWSSEVSNP{}) || + attestationVariant.Equal(variant.AzureSEVSNP{}) || + attestationVariant.Equal(variant.AzureTDX{}) || attestationVariant.Equal(variant.GCPSEVSNP{}) { - snpVersions, err = d.fetcher.FetchSEVSNPVersionLatest(ctx, attestationVariant) + latestVersions, err = d.fetcher.FetchLatestVersion(ctx, attestationVariant) if err != nil { resp.Diagnostics.AddError("Fetching SNP Version numbers", err.Error()) return } } - tfAttestation, err := convertToTfAttestation(attestationVariant, snpVersions) + tfAttestation, err := convertToTfAttestation(attestationVariant, latestVersions) if err != nil { resp.Diagnostics.AddError("Converting attestation", err.Error()) } diff --git a/terraform-provider-constellation/internal/provider/attestation_data_source_test.go b/terraform-provider-constellation/internal/provider/attestation_data_source_test.go index 3740e6b11..ff97968e7 100644 --- a/terraform-provider-constellation/internal/provider/attestation_data_source_test.go +++ b/terraform-provider-constellation/internal/provider/attestation_data_source_test.go @@ -7,6 +7,8 @@ SPDX-License-Identifier: AGPL-3.0-only package provider import ( + "errors" + "strconv" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -16,6 +18,30 @@ func TestAccAttestationSource(t *testing.T) { // Set the path to the Terraform binary for acceptance testing when running under Bazel. bazelPreCheck := func() { bazelSetTerraformBinaryPath(t) } + assertNonZeroValue := func(attr string) resource.TestCheckFunc { + return resource.TestCheckResourceAttrWith( + "data.constellation_attestation.test", + attr, + func(value string) error { + parsedValue, err := strconv.ParseUint(value, 10, 8) + if err == nil && parsedValue == 0 { + return errors.New("expected non-zero value") + } + return err + }, + ) + } + assertUint8Value := func(attr string) resource.TestCheckFunc { + return resource.TestCheckResourceAttrWith( + "data.constellation_attestation.test", + attr, + func(value string) error { + _, err := strconv.ParseUint(value, 10, 8) + return err + }, + ) + } + testCases := map[string]resource.TestCase{ "azure sev-snp success": { ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, @@ -36,12 +62,10 @@ func TestAccAttestationSource(t *testing.T) { `, Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.variant", "azure-sev-snp"), - - resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.bootloader_version", "3"), - resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.microcode_version", "115"), - resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.snp_version", "8"), - resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.tee_version", "0"), - + assertNonZeroValue("attestation.bootloader_version"), + assertNonZeroValue("attestation.microcode_version"), + assertNonZeroValue("attestation.snp_version"), + assertUint8Value("attestation.tee_version"), // the valid value is 0 at the moment resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.azure_firmware_signer_config.accepted_key_digests.0", "0356215882a825279a85b300b0b742931d113bf7e32dde2e50ffde7ec743ca491ecdd7f336dc28a6e0b2bb57af7a44a3"), resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.azure_firmware_signer_config.enforcement_policy", "MAAFallback"), @@ -110,33 +134,34 @@ func TestAccAttestationSource(t *testing.T) { }, }, }, - // TODO(msanft): Enable once v2.17.0 is available - // "gcp sev-snp succcess": { - // ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, - // PreCheck: bazelPreCheck, - // Steps: []resource.TestStep{ - // { - // Config: testingConfig + ` - // data "constellation_attestation" "test" { - // csp = "gcp" - // attestation_variant = "gcp-sev-snp" - // image = { - // version = "v2.17.0" - // reference = "v2.17.0" - // short_path = "v2.17.0" - // } - // } - // `, - // Check: resource.ComposeAggregateTestCheckFunc( - // resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.variant", "gcp-sev-snp"), - // resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.bootloader_version", "0"), // since this is not supported on GCP, we expect 0 - - // resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.1.expected", "745f2fb4235e4647aa0ad5ace781cd929eb68c28870e7dd5d1a1535854325e56"), - // resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.1.warn_only", "true"), - // ), - // }, - // }, - // }, + "gcp sev-snp succcess": { + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + PreCheck: bazelPreCheck, + Steps: []resource.TestStep{ + { + Config: testingConfig + ` + data "constellation_attestation" "test" { + csp = "gcp" + attestation_variant = "gcp-sev-snp" + image = { + version = "v2.17.0" + reference = "v2.17.0" + short_path = "v2.17.0" + } + } + `, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.variant", "gcp-sev-snp"), + assertNonZeroValue("attestation.bootloader_version"), + assertNonZeroValue("attestation.microcode_version"), + assertNonZeroValue("attestation.snp_version"), + assertUint8Value("attestation.tee_version"), // the valid value is 0 at the moment + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.1.expected", "3695dcc55e3aa34027c27793c85c723c697d708c42d1f73bd6fa4f26608a5b24"), + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.1.warn_only", "true"), + ), + }, + }, + }, "STACKIT qemu-vtpm success": { ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, PreCheck: bazelPreCheck, diff --git a/terraform-provider-constellation/internal/provider/cluster_resource.go b/terraform-provider-constellation/internal/provider/cluster_resource.go index a12fe38da..978771e83 100644 --- a/terraform-provider-constellation/internal/provider/cluster_resource.go +++ b/terraform-provider-constellation/internal/provider/cluster_resource.go @@ -54,6 +54,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types/basetypes" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/spf13/afero" + "k8s.io/client-go/tools/clientcmd" ) var ( @@ -102,9 +103,13 @@ type ClusterResourceModel struct { Azure types.Object `tfsdk:"azure"` OpenStack types.Object `tfsdk:"openstack"` - OwnerID types.String `tfsdk:"owner_id"` - ClusterID types.String `tfsdk:"cluster_id"` - KubeConfig types.String `tfsdk:"kubeconfig"` + OwnerID types.String `tfsdk:"owner_id"` + ClusterID types.String `tfsdk:"cluster_id"` + KubeConfig types.String `tfsdk:"kubeconfig"` + Host types.String `tfsdk:"host"` + ClientCertificate types.String `tfsdk:"client_certificate"` + ClientKey types.String `tfsdk:"client_key"` + ClusterCACertificate types.String `tfsdk:"cluster_ca_certificate"` } // networkConfigAttribute is the network config attribute's data model. @@ -417,8 +422,8 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re }, }, "kubeconfig": schema.StringAttribute{ - MarkdownDescription: "The kubeconfig of the cluster.", - Description: "The kubeconfig of the cluster.", + MarkdownDescription: "The kubeconfig (file) of the cluster.", + Description: "The kubeconfig (file) of the cluster.", Computed: true, Sensitive: true, PlanModifiers: []planmodifier.String{ @@ -426,6 +431,43 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re stringplanmodifier.UseStateForUnknown(), }, }, + "host": schema.StringAttribute{ + MarkdownDescription: "The host of the cluster.", + Description: "The host of the cluster.", + Computed: true, + PlanModifiers: []planmodifier.String{ + // We know that this value will never change after creation, so we can use the state value for upgrades. + stringplanmodifier.UseStateForUnknown(), + }, + }, + "client_certificate": schema.StringAttribute{ + MarkdownDescription: "The client certificate of the cluster.", + Description: "The client certificate of the cluster.", + Computed: true, + PlanModifiers: []planmodifier.String{ + // We know that this value will never change after creation, so we can use the state value for upgrades. + stringplanmodifier.UseStateForUnknown(), + }, + }, + "client_key": schema.StringAttribute{ + MarkdownDescription: "The client key of the cluster.", + Description: "The client key of the cluster.", + Computed: true, + Sensitive: true, + PlanModifiers: []planmodifier.String{ + // We know that this value will never change after creation, so we can use the state value for upgrades. + stringplanmodifier.UseStateForUnknown(), + }, + }, + "cluster_ca_certificate": schema.StringAttribute{ + MarkdownDescription: "The cluster CA certificate of the cluster.", + Description: "The cluster CA certificate of the cluster.", + Computed: true, + PlanModifiers: []planmodifier.String{ + // We know that this value will never change after creation, so we can use the state value for upgrades. + stringplanmodifier.UseStateForUnknown(), + }, + }, }, } } @@ -1171,7 +1213,45 @@ func (r *ClusterResource) runInitRPC(ctx context.Context, applier *constellation } // Save data from init response into the Terraform state + + // Save the raw kubeconfig file. data.KubeConfig = types.StringValue(string(initOutput.Kubeconfig)) + + // Unmarshal the kubeconfig to get the fine-grained values. + kubeconfig, err := clientcmd.Load(initOutput.Kubeconfig) + if err != nil { + diags.AddError("Unmarshalling kubeconfig", err.Error()) + return diags + } + + clusterContext, ok := kubeconfig.Contexts[kubeconfig.CurrentContext] + if !ok { + diags.AddError("Getting cluster context", + fmt.Sprintf("Context %s not found in kubeconfig", kubeconfig.CurrentContext)) + return diags + } + + cluster, ok := kubeconfig.Clusters[clusterContext.Cluster] + if !ok { + diags.AddError("Getting cluster", + fmt.Sprintf("Cluster %s not found in kubeconfig", clusterContext.Cluster)) + return diags + } + + data.Host = types.StringValue(cluster.Server) + data.ClusterCACertificate = types.StringValue(string(cluster.CertificateAuthorityData)) + + authInfo, ok := kubeconfig.AuthInfos[clusterContext.AuthInfo] + if !ok { + diags.AddError("Getting auth info", + fmt.Sprintf("Auth info %s not found in kubeconfig", clusterContext.AuthInfo)) + return diags + } + + data.ClientCertificate = types.StringValue(string(authInfo.ClientCertificateData)) + data.ClientKey = types.StringValue(string(authInfo.ClientKeyData)) + + // Save other values from the init response. data.ClusterID = types.StringValue(initOutput.ClusterID) data.OwnerID = types.StringValue(initOutput.OwnerID) @@ -1211,6 +1291,11 @@ func (r *ClusterResource) applyHelmCharts(ctx context.Context, applier *constell OpenStackValues: payload.openStackHelmValues, } + if err := applier.AnnotateCoreDNSResources(ctx); err != nil { + diags.AddError("Annotating CoreDNS resources", err.Error()) + return diags + } + executor, _, err := applier.PrepareHelmCharts(options, state, payload.serviceAccURI, payload.masterSecret) var upgradeErr *compatibility.InvalidUpgradeError @@ -1226,6 +1311,11 @@ func (r *ClusterResource) applyHelmCharts(ctx context.Context, applier *constell diags.AddError("Applying Helm charts", err.Error()) return diags } + + if err := applier.CleanupCoreDNSResources(ctx); err != nil { + diags.AddError("Cleaning up CoreDNS resources", err.Error()) + return diags + } return diags } diff --git a/terraform-provider-constellation/internal/provider/convert.go b/terraform-provider-constellation/internal/provider/convert.go index cfe9ec7fa..84e4c8832 100644 --- a/terraform-provider-constellation/internal/provider/convert.go +++ b/terraform-provider-constellation/internal/provider/convert.go @@ -17,6 +17,7 @@ import ( "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/config" + "github.com/edgelesssys/constellation/v2/internal/encoding" ) // naming schema: @@ -110,12 +111,12 @@ func convertFromTfAttestationCfg(tfAttestation attestationAttribute, attestation attestationConfig = &config.AzureTDX{ Measurements: c11nMeasurements, - QESVN: tfAttestation.TDX.QESVN, - PCESVN: tfAttestation.TDX.PCESVN, - TEETCBSVN: teeTCBSVN, - QEVendorID: qeVendorID, + QESVN: newVersion(tfAttestation.TDX.QESVN), + PCESVN: newVersion(tfAttestation.TDX.PCESVN), + TEETCBSVN: newVersion(encoding.HexBytes(teeTCBSVN)), + QEVendorID: newVersion(encoding.HexBytes(qeVendorID)), MRSeam: mrSeam, - XFAM: xfam, + XFAM: newVersion(encoding.HexBytes(xfam)), IntelRootKey: rootKey, } case variant.GCPSEVES{}: @@ -137,13 +138,9 @@ func convertFromTfAttestationCfg(tfAttestation attestationAttribute, attestation } // convertToTfAttestationCfg converts the constellation attestation config to the related terraform structs. -func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfigapi.SEVSNPVersionAPI) (tfAttestation attestationAttribute, err error) { +func convertToTfAttestation(attVar variant.Variant, latestVersions attestationconfigapi.Entry) (tfAttestation attestationAttribute, err error) { tfAttestation = attestationAttribute{ - Variant: attVar.String(), - BootloaderVersion: snpVersions.Bootloader, - TEEVersion: snpVersions.TEE, - SNPVersion: snpVersions.SNP, - MicrocodeVersion: snpVersions.Microcode, + Variant: attVar.String(), } switch attVar { @@ -153,6 +150,10 @@ func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfi return tfAttestation, err } tfAttestation.AMDRootKey = certStr + tfAttestation.BootloaderVersion = latestVersions.Bootloader + tfAttestation.TEEVersion = latestVersions.TEE + tfAttestation.SNPVersion = latestVersions.SNP + tfAttestation.MicrocodeVersion = latestVersions.Microcode case variant.GCPSEVSNP{}: certStr, err := certAsString(config.DefaultForGCPSEVSNP().AMDRootKey) @@ -160,6 +161,10 @@ func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfi return tfAttestation, err } tfAttestation.AMDRootKey = certStr + tfAttestation.BootloaderVersion = latestVersions.Bootloader + tfAttestation.TEEVersion = latestVersions.TEE + tfAttestation.SNPVersion = latestVersions.SNP + tfAttestation.MicrocodeVersion = latestVersions.Microcode case variant.AzureSEVSNP{}: certStr, err := certAsString(config.DefaultForAzureSEVSNP().AMDRootKey) @@ -167,6 +172,10 @@ func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfi return tfAttestation, err } tfAttestation.AMDRootKey = certStr + tfAttestation.BootloaderVersion = latestVersions.Bootloader + tfAttestation.TEEVersion = latestVersions.TEE + tfAttestation.SNPVersion = latestVersions.SNP + tfAttestation.MicrocodeVersion = latestVersions.Microcode firmwareCfg := config.DefaultForAzureSEVSNP().FirmwareSignerConfig tfFirmwareCfg, err := convertToTfFirmwareCfg(firmwareCfg) @@ -174,24 +183,19 @@ func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfi return tfAttestation, err } tfAttestation.AzureSNPFirmwareSignerConfig = tfFirmwareCfg + case variant.AzureTDX{}: - tdxCfg := config.DefaultForAzureTDX() - certStr, err := certAsString(tdxCfg.IntelRootKey) + certStr, err := certAsString(config.DefaultForAzureTDX().IntelRootKey) if err != nil { return tfAttestation, err } + tfAttestation.TDX.IntelRootKey = certStr + tfAttestation.TDX.PCESVN = latestVersions.PCESVN + tfAttestation.TDX.QESVN = latestVersions.QESVN + tfAttestation.TDX.TEETCBSVN = hex.EncodeToString(latestVersions.TEETCBSVN[:]) + tfAttestation.TDX.QEVendorID = hex.EncodeToString(latestVersions.QEVendorID[:]) + tfAttestation.TDX.XFAM = hex.EncodeToString(latestVersions.XFAM[:]) - tfTdxCfg := tdxConfigAttribute{ - IntelRootKey: certStr, - // TODO(AB#3798): Load these values dynamically from our attestation API - QESVN: tdxCfg.QESVN, - PCESVN: tdxCfg.PCESVN, - TEETCBSVN: hex.EncodeToString(tdxCfg.TEETCBSVN), - QEVendorID: hex.EncodeToString(tdxCfg.QEVendorID), - MRSeam: hex.EncodeToString(tdxCfg.MRSeam), - XFAM: hex.EncodeToString(tdxCfg.XFAM), - } - tfAttestation.TDX = tfTdxCfg case variant.GCPSEVES{}, variant.QEMUVTPM{}: // no additional fields default: @@ -251,8 +255,8 @@ func convertToTfMeasurements(m measurements.M) map[string]measurementAttribute { return tfMeasurements } -func newVersion(v uint8) config.AttestationVersion { - return config.AttestationVersion{ +func newVersion[T uint8 | uint16 | encoding.HexBytes](v T) config.AttestationVersion[T] { + return config.AttestationVersion[T]{ Value: v, } } diff --git a/terraform-provider-constellation/internal/provider/shared_attributes.go b/terraform-provider-constellation/internal/provider/shared_attributes.go index 0a8c6a72d..e1cc4e1dd 100644 --- a/terraform-provider-constellation/internal/provider/shared_attributes.go +++ b/terraform-provider-constellation/internal/provider/shared_attributes.go @@ -31,8 +31,8 @@ func newAttestationVariantAttributeSchema(t attributeType) schema.Attribute { " * `aws-nitro-tpm`\n" + " * `azure-sev-snp`\n" + " * `azure-tdx`\n" + - " * `gcp-sev-es`\n" + " * `gcp-sev-snp`\n" + + " * `gcp-sev-es`\n" + " * `qemu-vtpm`\n", Required: isInput, Computed: !isInput, diff --git a/terraform/infrastructure/aws/.terraform.lock.hcl b/terraform/infrastructure/aws/.terraform.lock.hcl index 32ca13156..22f27bd4b 100644 --- a/terraform/infrastructure/aws/.terraform.lock.hcl +++ b/terraform/infrastructure/aws/.terraform.lock.hcl @@ -2,52 +2,67 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "5.37.0" - constraints = "5.37.0" + version = "5.57.0" + constraints = "5.57.0" hashes = [ - "h1:6qJfvyWObjLPoUrEC8kNVAJ1ZFFrIgzC1xprMkkoSjo=", - "h1:CQeYyWigNz838zjXKYH9VDkpjqlGB0phcM742YXiNh4=", - "h1:WcdVLFBrCN1lP44ZzCSTR8e8p/4C9BQLAqdszE+jh4M=", - "h1:jy1tY8vUGirfcC9GwSS2Uf01GXcxnNnotvIK/WjI2WI=", - "h1:o6f/hNLxrONTw/QlRbBVctdXNI2aSfrght4wtng6rOU=", - "zh:00f40a3d9593476693a7a72d993fd289f7be374fe3f2799776c6296eb6ff890a", - "zh:1010a9fbf55852a8da3473de4ec0f1fcf29efa85d66f61cbe2b086dbbd7747ae", - "zh:103a5674d1eb1cff05fe35e9baa9875afd18d740868b63f9c0c25eadb5eb4eb7", - "zh:270ac1b7a1327c1456a43df44c0b5cc3e26ed6d8861a709adeea1da684a563f5", - "zh:424362c02c8917c0586f3dd49aca27b7e0c21f5a23374b7045e9be3b5646c028", - "zh:549fa2ea187964ab9a0c354310947ead30e09b3199db1ff377c21d7547d78299", - "zh:6492d2ccc7f7d60e83cd8b7244adc53f30efc17d84b1ffc1b8fd6c385f8255fd", - "zh:66fb7b3b8a357071d26c5996c16d426edf07502a05ac86f4a6f73646ee7d1bbb", - "zh:6ecc05fb466d06ea8945564d2cdb8c2a8827d8cfca1550e9fb7eac0e95920196", - "zh:7932360b627b211dad937d278a8692a6c52bd6c0a71e4ec9e94ccbe825053822", - "zh:97ed1b4a18842c4d56a735329e87b4ef91a47e820e5a5c3c2dd64e293408bfc8", + "h1:0vkeOAKaYJn/Qo1LT5BMMYcfxxorbdg6Wjm5cRUaSsk=", + "h1:47axyGCVgEBHaQThoNSabiGsrpFXGdIK+uLXqADLNeI=", + "h1:78RIKu5Kn+y7jwbk3Av+z64OQ+ubOqzkr+WkG2BLeXs=", + "h1:9yi3yb3XOMjj/xsSbOfscfmQzPUQ7sZqSYSBfGSfkBA=", + "h1:B8Rpgfr1+wt2ByOZYWZL0cIoOcfSUUYkajsF+ocZ97o=", + "h1:FPU7aOZNSo+wwydZpmA7sB4nt1d0Wgkh0cb5Zl+WNj4=", + "h1:KMPhyxoRthbmc11+RbClq5bricmGDICh1NgE3nPjN7U=", + "h1:PXidujIDQyFAIS9qHoEdsonNbfV7TWXiFYag/KLnq7c=", + "h1:RaNKerWC8c10tAXCRUNqO9FVLw3qIYwQN4Zp4+O/rWE=", + "h1:bSps73eq0YgIZf73/JvKKve40TNGfTB6+86bmT4ABGI=", + "h1:txjX+di/ltKLPAcNKskNjoVB4g/KjKfOYwCq9Tne+JI=", + "h1:u7FszdKvOSKA53nsWnNOuh0/GtKwzBe6uIlAoTEWeyU=", + "h1:y4fdaiu5VqzHOTjsuB0mTI33hoKYc4MnloHWjLCuA3c=", + "h1:yz3Y5KM6UgOzpOrlR/ExM4mlD2wAGvzlhkfODzuVHE8=", + "zh:03761bedb72290599aef0040d3cefb77842f0ef4338673a7e5b53557b0ca4960", + "zh:1c70c050116370688abd239979b06f33c5c8cb7f6e59e89f60cf08ee01666064", + "zh:1cc3b259028a65b2f68ffc25df876bbb0f46d108f262b8ec7c56fc597ac697af", + "zh:3bcdf1415b37f39b71e07d4d92977cf8697f07602382d63687d5f683fee0231a", + "zh:40b1774a2cacc84002ac88ef30fb017c273009456d7a1f9f7c5a4a057041ec75", + "zh:46d51fa066c6441594a1e242c9491cc31dbb2dc85f1acf8bc54ad6faa4de524b", + "zh:550e5635b0cd5d98fa66c2afd5dbb1563a8e019be9f760bd1543fbcca763f0c1", + "zh:7acc8357b5e02ed3eb478125614d049511d6faeb9850c084d6e6519db875f0d1", + "zh:7f7367299811ddf5560a0586e525d57dd52f1a0ca37e42e2c5284308069bf2b6", + "zh:8766cc10c83b1fc2e971c4e645bc4d3c871d4758eb54b0a3216600c66e3db681", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:d5e022052011e1984b9c2f8bc5a6b05c909e3b5bf40c3baddf191bf90e3169c2", - "zh:d7e9488b2ce5904efb91c8577b3fe9b0cd599c4cd508f1f163f292930f54fdf0", - "zh:e57cd93d5cd81dd0f446076af6e47a53ce83df2947ec64ed39a1090d4bdf8f0b", + "zh:a1e85b1fb9004d8ffab7600304e02bce4aa14cea9f0ad77fbd7b84aae6390760", + "zh:bcf2fc83bd9e20e5a930d9d596eb813c319f2b007c620b1818e574c1702eb9a9", + "zh:d2538fcb20dc2afc04b716f67969944eef7f4fc4296410116d5b7af1811100f2", + "zh:e0e47c5d8710bbfcfe4db1cfa81c67e320056006d08063e69640cd2d492c6f64", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.6.0" - constraints = "3.6.0" + version = "3.6.2" + constraints = "3.6.2" hashes = [ - "h1:5KeoKSVKVHJW308uiTgslxFbjQAdWzBGUFK68vgMRWY=", - "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", - "h1:R5Ucn26riKIEijcsiOMBR3uOAjuOMfI1x7XvH4P6B1w=", - "h1:p6WG1IPHnqx1fnJVKNjv733FBaArIugqy58HRZnpPCk=", - "h1:t0mRdJzegohRKhfdoQEJnv3JRISSezJRblN0HIe67vo=", - "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", - "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", - "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", - "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", - "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", + "h1:5lstwe/L8AZS/CP0lil2nPvmbbjAu8kCaU/ogSGNbxk=", + "h1:Gd3WitYIzSYo/Suo+PMxpZpIGpRPrwl0JU0+DhxycFM=", + "h1:J9EOvuE7qCS/S0lqMX6DNqsh/wq2uhwxE2bOpSn0/hc=", + "h1:R5qdQjKzOU16TziCN1vR3Exr/B+8WGK80glLTT4ZCPk=", + "h1:UQlmHGddu39vVzG8kruMsde4GHlG+1S7OLqFApbJvtc=", + "h1:VYBb5/CQ1tPhV92eUsfxSZ4Ta2OCfNggYwE+Qo+yCD0=", + "h1:VavG5unYCa3SYISMKF9pzc3718M0bhPlcbUZZGl7wuo=", + "h1:jke+2u84Hrc7szJKevP1BKFn1o3pfxYhYtity2RPCS8=", + "h1:m/7/S7a6RzGgeRAJJCsDza2kbaNmFpQDDd849RxD2FE=", + "h1:uOP0uuF8PKF98YlLqgtjdHBELJLI4BMOOHYXQMYhdlI=", + "h1:wmG0QFjQ2OfyPy6BB7mQ57WtoZZGGV07uAPQeDmIrAE=", + "zh:0ef01a4f81147b32c1bea3429974d4d104bbc4be2ba3cfa667031a8183ef88ec", + "zh:1bcd2d8161e89e39886119965ef0f37fcce2da9c1aca34263dd3002ba05fcb53", + "zh:37c75d15e9514556a5f4ed02e1548aaa95c0ecd6ff9af1119ac905144c70c114", + "zh:4210550a767226976bc7e57d988b9ce48f4411fa8a60cd74a6b246baf7589dad", + "zh:562007382520cd4baa7320f35e1370ffe84e46ed4e2071fdc7e4b1a9b1f8ae9b", + "zh:5efb9da90f665e43f22c2e13e0ce48e86cae2d960aaf1abf721b497f32025916", + "zh:6f71257a6b1218d02a573fc9bff0657410404fb2ef23bc66ae8cd968f98d5ff6", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", - "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", - "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", - "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", - "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", - "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", + "zh:9647e18f221380a85f2f0ab387c68fdafd58af6193a932417299cdcae4710150", + "zh:bb6297ce412c3c2fa9fec726114e5e0508dd2638cad6a0cb433194930c97a544", + "zh:f83e925ed73ff8a5ef6e3608ad9225baa5376446349572c2449c0c0b3cf184b7", + "zh:fbef0781cb64de76b1df1ca11078aecba7800d82fd4a956302734999cfd9a4af", ] } diff --git a/terraform/infrastructure/aws/main.tf b/terraform/infrastructure/aws/main.tf index 53a83ff74..28bcd09a1 100644 --- a/terraform/infrastructure/aws/main.tf +++ b/terraform/infrastructure/aws/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "5.37.0" + version = "5.57.0" } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } } } @@ -55,6 +55,13 @@ locals { in_cluster_endpoint = aws_lb.front_end.dns_name out_of_cluster_endpoint = var.internal_load_balancer && var.debug ? module.jump_host[0].ip : local.in_cluster_endpoint + revision = 1 +} + +# A way to force replacement of resources if the provider does not want to replace them +# see: https://developer.hashicorp.com/terraform/language/resources/terraform-data#example-usage-data-for-replace_triggered_by +resource "terraform_data" "replacement" { + input = local.revision } resource "random_id" "uid" { diff --git a/terraform/infrastructure/aws/modules/instance_group/main.tf b/terraform/infrastructure/aws/modules/instance_group/main.tf index 3a2e92fff..bc067e225 100644 --- a/terraform/infrastructure/aws/modules/instance_group/main.tf +++ b/terraform/infrastructure/aws/modules/instance_group/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "5.37.0" + version = "5.57.0" } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } } } diff --git a/terraform/infrastructure/aws/modules/jump_host/main.tf b/terraform/infrastructure/aws/modules/jump_host/main.tf index fa388b653..31e6b69d9 100644 --- a/terraform/infrastructure/aws/modules/jump_host/main.tf +++ b/terraform/infrastructure/aws/modules/jump_host/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "5.37.0" + version = "5.57.0" } } } diff --git a/terraform/infrastructure/aws/modules/load_balancer_target/main.tf b/terraform/infrastructure/aws/modules/load_balancer_target/main.tf index 56f27beeb..2dc9d0d39 100644 --- a/terraform/infrastructure/aws/modules/load_balancer_target/main.tf +++ b/terraform/infrastructure/aws/modules/load_balancer_target/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "5.37.0" + version = "5.57.0" } } } diff --git a/terraform/infrastructure/aws/modules/public_private_subnet/main.tf b/terraform/infrastructure/aws/modules/public_private_subnet/main.tf index 222476d76..a6679e13a 100644 --- a/terraform/infrastructure/aws/modules/public_private_subnet/main.tf +++ b/terraform/infrastructure/aws/modules/public_private_subnet/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "5.37.0" + version = "5.57.0" } } } diff --git a/terraform/infrastructure/azure/.terraform.lock.hcl b/terraform/infrastructure/azure/.terraform.lock.hcl index a11464c43..78936e6a3 100644 --- a/terraform/infrastructure/azure/.terraform.lock.hcl +++ b/terraform/infrastructure/azure/.terraform.lock.hcl @@ -2,50 +2,56 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "3.92.0" - constraints = "3.92.0" + version = "4.1.0" + constraints = "4.1.0" hashes = [ - "h1:+bZPRgjpUA6LivvMIS1UdwRWUgzoYBp/nhEpbL4aXHM=", - "h1:D5lngW1uKlPM2EUCdNG1f2FvPGHYRklDFN8b2jPCIpM=", - "h1:nTP2ZYfuEpMP+PkkgRdhQphNmWWJuKdE9Z4TzeC7ydo=", - "h1:sqVZftg9rJGDiiPiY9l1V/a+5CWkxNcj22sBu8HsJBY=", - "h1:swoRk2drVrD8v7GrW/2OJSk06v2I2zGk3XPAgBDbw9A=", - "zh:04292e149676ba956d738e85faeb6d6ebd3759e8310f1c4155e67402eb5ae0f7", - "zh:0963b4528f25d01d5c733e17de31e2c0b94790fd02931b2a47cd051b20dd0d96", - "zh:133563e16e8a4a7139ac11d94e68de8d1d5e3a62a532e64ac936735d7b1e04db", - "zh:2b219f1b40881d3bdd89257c916f255a7e36904ddc65dbbafee80763661b4636", - "zh:4b4e11a4e3716b290b3b173dfd15b06814b2f6f148f663e3c67a677c95526339", - "zh:5607c7bff3019c3b31488be1a8a9d77a96d27b199a1d8b789e4c2d4c90805674", - "zh:6469aef7728947dacb47785e6082d2d95ebd336a8798f3be6cece5a13145108c", - "zh:69e563f4e6397e1ebaef6f554d296238ec1d9dadc4b865c36743bd8366a888da", - "zh:887a223b7a9ec4e66634dbb65d9dcc53f0be06d058d9a209927ad49702ae790c", - "zh:b03c273367885c5489a24c31859af81ea58cb169431c0da97a175945ec968f53", - "zh:dd7b704ceaf98ce591e111a9c5085465c946f4f8f357089c0e27e990a669ba39", + "h1:K2OLOYxwF/onOegr+Y6Sfu/DjEjDLobQBBrLBF3i9TI=", + "h1:cwtEEnEESVOgcxtXGz0A2wXCiNZIzm3dC2xHmYuxg9M=", + "h1:dKXFrVrjv579ax6iX4wc6lmEAVFsr3iTDjErnPHIjH4=", + "h1:iqN6KxIOGYv0N1p5xfNTgsjvDHpE3bZM8s5vIAEgfnQ=", + "h1:qDmSr5+vMVdWmfBEaIwqSLo5ZLyYk7KYoJo5flny6lk=", + "zh:3f332bca3a8b7dc982e428e09c73862d1afda34c2ad7803e70d8ba7b9e2445fd", + "zh:66b7e4a7a4fd06e0a5a3a22b4f76bda48e50ed3dd26c388738d9cc882b801bce", + "zh:6a271175d6e079241f24129f5026e0b16f04e7a548807f115600003d615e0ec3", + "zh:7a6abc7e2ae8d1041d0446bbe87156e0436639676ee1fad40321e8ee6759a454", + "zh:903f6e7f03e5952347ce6ee589d58c829179f2f22220f25cf52ae4efecd7053c", + "zh:a572b9834cf3b51799c82c5009705c59309d947a6ecdb7e17729868c55e7d0e0", + "zh:a7fca14338f0cfb82b17ce085400c210cbc986a87086702e3a11efcb4e53d6e4", + "zh:af36c7004702b0a273794914a17a77af1eb972caaad64e0068739e55c1488845", + "zh:b36f308db1cdc02dee659e3e518186d7dec970d88b6149be3f6b3f8d544e4282", + "zh:bedf6d13cf4bccc128d8cbb0703a3a8b547629674439ffda5e73563ab775d0f7", + "zh:d1df286a2e5d4a5f6a7f4d29700a25588167ccffa31c686550ef617503df3254", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.6.0" - constraints = "3.6.0" + version = "3.6.2" + constraints = "3.6.2" hashes = [ - "h1:5KeoKSVKVHJW308uiTgslxFbjQAdWzBGUFK68vgMRWY=", - "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", - "h1:R5Ucn26riKIEijcsiOMBR3uOAjuOMfI1x7XvH4P6B1w=", - "h1:p6WG1IPHnqx1fnJVKNjv733FBaArIugqy58HRZnpPCk=", - "h1:t0mRdJzegohRKhfdoQEJnv3JRISSezJRblN0HIe67vo=", - "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", - "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", - "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", - "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", - "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", + "h1:5lstwe/L8AZS/CP0lil2nPvmbbjAu8kCaU/ogSGNbxk=", + "h1:Gd3WitYIzSYo/Suo+PMxpZpIGpRPrwl0JU0+DhxycFM=", + "h1:J9EOvuE7qCS/S0lqMX6DNqsh/wq2uhwxE2bOpSn0/hc=", + "h1:R5qdQjKzOU16TziCN1vR3Exr/B+8WGK80glLTT4ZCPk=", + "h1:UQlmHGddu39vVzG8kruMsde4GHlG+1S7OLqFApbJvtc=", + "h1:VYBb5/CQ1tPhV92eUsfxSZ4Ta2OCfNggYwE+Qo+yCD0=", + "h1:VavG5unYCa3SYISMKF9pzc3718M0bhPlcbUZZGl7wuo=", + "h1:jke+2u84Hrc7szJKevP1BKFn1o3pfxYhYtity2RPCS8=", + "h1:m/7/S7a6RzGgeRAJJCsDza2kbaNmFpQDDd849RxD2FE=", + "h1:uOP0uuF8PKF98YlLqgtjdHBELJLI4BMOOHYXQMYhdlI=", + "h1:wmG0QFjQ2OfyPy6BB7mQ57WtoZZGGV07uAPQeDmIrAE=", + "zh:0ef01a4f81147b32c1bea3429974d4d104bbc4be2ba3cfa667031a8183ef88ec", + "zh:1bcd2d8161e89e39886119965ef0f37fcce2da9c1aca34263dd3002ba05fcb53", + "zh:37c75d15e9514556a5f4ed02e1548aaa95c0ecd6ff9af1119ac905144c70c114", + "zh:4210550a767226976bc7e57d988b9ce48f4411fa8a60cd74a6b246baf7589dad", + "zh:562007382520cd4baa7320f35e1370ffe84e46ed4e2071fdc7e4b1a9b1f8ae9b", + "zh:5efb9da90f665e43f22c2e13e0ce48e86cae2d960aaf1abf721b497f32025916", + "zh:6f71257a6b1218d02a573fc9bff0657410404fb2ef23bc66ae8cd968f98d5ff6", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", - "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", - "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", - "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", - "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", - "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", + "zh:9647e18f221380a85f2f0ab387c68fdafd58af6193a932417299cdcae4710150", + "zh:bb6297ce412c3c2fa9fec726114e5e0508dd2638cad6a0cb433194930c97a544", + "zh:f83e925ed73ff8a5ef6e3608ad9225baa5376446349572c2449c0c0b3cf184b7", + "zh:fbef0781cb64de76b1df1ca11078aecba7800d82fd4a956302734999cfd9a4af", ] } diff --git a/terraform/infrastructure/azure/main.tf b/terraform/infrastructure/azure/main.tf index 259bd2b3d..b670b2989 100644 --- a/terraform/infrastructure/azure/main.tf +++ b/terraform/infrastructure/azure/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.92.0" + version = "4.1.0" } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } } } @@ -17,6 +17,10 @@ provider "azurerm" { prevent_deletion_if_contains_resources = false } } + subscription_id = var.subscription_id + # This enables all resource providers. + # In the future, we might want to use `resource_providers_to_register` to registers just the ones we need. + resource_provider_registrations = "all" } locals { @@ -33,7 +37,6 @@ locals { { name = "kubernetes", port = "6443", health_check_protocol = "Https", path = "/readyz", priority = 100 }, { name = "bootstrapper", port = "9000", health_check_protocol = "Tcp", path = null, priority = 101 }, { name = "verify", port = "30081", health_check_protocol = "Tcp", path = null, priority = 102 }, - { name = "konnectivity", port = "8132", health_check_protocol = "Tcp", path = null, priority = 103 }, { name = "recovery", port = "9999", health_check_protocol = "Tcp", path = null, priority = 104 }, { name = "join", port = "30090", health_check_protocol = "Tcp", path = null, priority = 105 }, var.debug ? [{ name = "debugd", port = "4000", health_check_protocol = "Tcp", path = null, priority = 106 }] : [], @@ -49,6 +52,13 @@ locals { in_cluster_endpoint = var.internal_load_balancer ? azurerm_lb.loadbalancer.frontend_ip_configuration[0].private_ip_address : azurerm_public_ip.loadbalancer_ip[0].ip_address out_of_cluster_endpoint = var.debug && var.internal_load_balancer ? module.jump_host[0].ip : local.in_cluster_endpoint + revision = 1 +} + +# A way to force replacement of resources if the provider does not want to replace them +# see: https://developer.hashicorp.com/terraform/language/resources/terraform-data#example-usage-data-for-replace_triggered_by +resource "terraform_data" "replacement" { + input = local.revision } resource "random_id" "uid" { @@ -170,6 +180,8 @@ module "loadbalancer_backend_control_plane" { ports = local.ports } +# We cannot delete them right away since we first need to to delete the dependency from the VMSS to this backend pool. +# TODO(@3u13r): Remove this resource after v2.18.0 has been released. module "loadbalancer_backend_worker" { source = "./modules/load_balancer_backend" @@ -179,11 +191,14 @@ module "loadbalancer_backend_worker" { ports = [] } +# We cannot delete them right away since we first need to to delete the dependency from the VMSS to this backend pool. +# TODO(@3u13r): Remove this resource after v2.18.0 has been released. resource "azurerm_lb_backend_address_pool" "all" { loadbalancer_id = azurerm_lb.loadbalancer.id name = "${var.name}-all" } + resource "azurerm_virtual_network" "network" { name = local.name resource_group_name = var.resource_group @@ -212,24 +227,24 @@ resource "azurerm_network_security_group" "security_group" { location = var.location resource_group_name = var.resource_group tags = local.tags +} - dynamic "security_rule" { - for_each = concat( - local.ports, - [{ name = "nodeports", port = local.ports_node_range, priority = 200 }] - ) - content { - name = security_rule.value.name - priority = security_rule.value.priority - direction = "Inbound" - access = "Allow" - protocol = "Tcp" - source_port_range = "*" - destination_port_range = security_rule.value.port - source_address_prefix = "*" - destination_address_prefix = "*" - } +resource "azurerm_network_security_rule" "nsg_rule" { + for_each = { + for o in local.ports : o.name => o } + # TODO(elchead): v2.20.0: remove name suffix and priority offset. Might need to add create_before_destroy to the NSG rule. + name = "${each.value.name}-new" + priority = each.value.priority + 10 # offset to not overlap with old rules + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = each.value.port + source_address_prefix = "*" + destination_address_prefix = "*" + resource_group_name = var.resource_group + network_security_group_name = azurerm_network_security_group.security_group.name } module "scale_set_group" { @@ -257,14 +272,8 @@ module "scale_set_group" { image_id = var.image_id network_security_group_id = azurerm_network_security_group.security_group.id subnet_id = azurerm_subnet.node_subnet.id - backend_address_pool_ids = each.value.role == "control-plane" ? [ - azurerm_lb_backend_address_pool.all.id, - module.loadbalancer_backend_control_plane.backendpool_id - ] : [ - azurerm_lb_backend_address_pool.all.id, - module.loadbalancer_backend_worker.backendpool_id - ] - marketplace_image = var.marketplace_image + backend_address_pool_ids = each.value.role == "control-plane" ? [module.loadbalancer_backend_control_plane.backendpool_id] : [] + marketplace_image = var.marketplace_image } module "jump_host" { diff --git a/terraform/infrastructure/azure/modules/jump_host/main.tf b/terraform/infrastructure/azure/modules/jump_host/main.tf index c35136ff7..ba7d5f726 100644 --- a/terraform/infrastructure/azure/modules/jump_host/main.tf +++ b/terraform/infrastructure/azure/modules/jump_host/main.tf @@ -29,7 +29,7 @@ resource "azurerm_linux_virtual_machine" "jump_host" { } boot_diagnostics { - + storage_account_uri = null } user_data = base64encode(< 0 ? var.openstack_clouds_yaml_path : "~/.config/openstack/clouds.yaml" cloudsyaml = yamldecode(file(pathexpand(local.cloudsyaml_path))) cloudyaml = local.cloudsyaml.clouds[var.cloud] + revision = 1 +} + +# A way to force replacement of resources if the provider does not want to replace them +# see: https://developer.hashicorp.com/terraform/language/resources/terraform-data#example-usage-data-for-replace_triggered_by +resource "terraform_data" "replacement" { + input = local.revision } resource "random_id" "uid" { @@ -242,6 +249,7 @@ module "instance_group" { openstack_username = local.cloudyaml["auth"]["username"] openstack_password = local.cloudyaml["auth"]["password"] openstack_user_domain_name = local.cloudyaml["auth"]["user_domain_name"] + openstack_region_name = local.cloudyaml["region_name"] openstack_load_balancer_endpoint = openstack_networking_floatingip_v2.public_ip.address } diff --git a/terraform/infrastructure/openstack/modules/instance_group/main.tf b/terraform/infrastructure/openstack/modules/instance_group/main.tf index b104506d5..b2feecb5f 100644 --- a/terraform/infrastructure/openstack/modules/instance_group/main.tf +++ b/terraform/infrastructure/openstack/modules/instance_group/main.tf @@ -80,6 +80,7 @@ resource "openstack_compute_instance_v2" "instance_group_member" { openstack-username = var.openstack_username openstack-password = var.openstack_password openstack-user-domain-name = var.openstack_user_domain_name + openstack-region-name = var.openstack_region_name openstack-load-balancer-endpoint = var.openstack_load_balancer_endpoint }) availability_zone_hints = length(var.availability_zone) > 0 ? var.availability_zone : null diff --git a/terraform/infrastructure/openstack/modules/instance_group/variables.tf b/terraform/infrastructure/openstack/modules/instance_group/variables.tf index 74f0f9e28..991985c97 100644 --- a/terraform/infrastructure/openstack/modules/instance_group/variables.tf +++ b/terraform/infrastructure/openstack/modules/instance_group/variables.tf @@ -97,6 +97,11 @@ variable "openstack_password" { description = "OpenStack password." } +variable "openstack_region_name" { + type = string + description = "OpenStack region name." +} + variable "openstack_load_balancer_endpoint" { type = string description = "OpenStack load balancer endpoint." diff --git a/terraform/infrastructure/openstack/modules/stackit_loadbalancer/main.tf b/terraform/infrastructure/openstack/modules/stackit_loadbalancer/main.tf index 889964ee9..d4ada1605 100644 --- a/terraform/infrastructure/openstack/modules/stackit_loadbalancer/main.tf +++ b/terraform/infrastructure/openstack/modules/stackit_loadbalancer/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.17.0" + version = "0.33.2" } } } diff --git a/terraform/infrastructure/qemu/.terraform.lock.hcl b/terraform/infrastructure/qemu/.terraform.lock.hcl index fe10c6d34..5ac4182a5 100644 --- a/terraform/infrastructure/qemu/.terraform.lock.hcl +++ b/terraform/infrastructure/qemu/.terraform.lock.hcl @@ -2,52 +2,61 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/dmacvicar/libvirt" { - version = "0.7.1" - constraints = "0.7.1" + version = "0.7.6" + constraints = "0.7.6" hashes = [ - "h1:1yEJVPVFkRkbRY63+sFRAWau/eJ0xlecHWLCV8spkWU=", - "h1:AJn6IML1iiq9oIUdDQTDApMvsfSKfMncF4RoKnhpNaY=", - "h1:G114r+ESpxpMCnBxFXZZ3+HktoNK4WXAJ5M3GRwvgBQ=", - "h1:ZG+KVAKVm++wfWnGdc8QIFn1LHRycUnmYibMg4REQyk=", - "h1:rDm9KgxNWuhdTCJpfepeTzCB/b24bKrOMN57637RZtU=", - "zh:1c59f2ab68da6326637ee8b03433e84af76b3e3562f251a7f2aa239a7b262a8d", - "zh:236e24ecf036e99d9d1e2081a39dc9cb4b8993850a37141a1449f20750f883d6", - "zh:4519c22b1f00c1d37d60ac6c2cb7ad5ab9dbcd44a80b4f61e68aacb54eae017d", - "zh:54de4e3c979c32af1dc71ec2846912f669a28bdb0990e8a3c1fb8fea4ede7b61", - "zh:6270a757bcf4e1f9efe47726cf0caefba30a25e59d151103cf03d1656325783c", - "zh:68b8586d5b29c0a1cb7c608a309b38db911449c072d60eee9e40e01881f1c23a", - "zh:724ba2290fea704714378e9363541420c36091e790c7f39150cde8987d4e0754", - "zh:7b6860c92376cdad98273aab4bea62546622e08f50733e4b2e58a7a859d3b49d", - "zh:986a0a4f8d9511c64bcac8010337deb43110b4c2f91969b2491fd9edc290b60e", - "zh:aff0f6f24d69cd97a44cd6059edaf355769fbb8a7643a6db4d52c9a94f98e194", - "zh:c46ca3f8384d06c13a7ed3d4b83c65b4f8dccbf9d5f624843b68d176add5c5c2", - "zh:ef310534e7d38153aca4ce31655b52a6e6c4d76f32e49732c96b62e9de1ee843", - "zh:f1566b094f4267ef2674889d874962dd41e0cba55251645e16d003c77ca8a19c", - "zh:f2e019df7b537069828c5537c481e5b7f41d2404eef6fe5c86702c20900b303d", + "h1:CcdSVsSt7fDoisqnTqWKkekjaGLUlYBuEkzA6NFFqeA=", + "h1:DEJO3ab+JUUGG5rjNRI1+ORSst66oJ4YYS12s2yX7cs=", + "h1:H63KAqcO593KB4M92zMqLLNv5cnvtGJtpCY0YMV13lE=", + "h1:ID44pCKG1/P+6AznezHDE66EG2ZZqnV9FiNdMwQkLBw=", + "h1:UiPwB2qXh43jYHm6Nvx8hkvx2XdOpmtz8sFuqrTyKC8=", + "h1:dwJ5HUkCaeARF1uQS6XyV5LWD3vomBXzq759LO29bU4=", + "h1:e28YOgPYS+zeAHc3fDvopaSO+Hwp5epGquh/k1rWHio=", + "h1:g53oDOhYVkBTf8oGRQdapTkiIVA/0HmgfRfRrjkLgDE=", + "h1:gt306d/Blv/6C5X1XmCgoIDPFyEdYJTcUblaoXvEFlI=", + "h1:h5AOtaYpdnjPPtjKw2PsNmjZ9VmjnAgqXTndl3Mwwug=", + "h1:iSXq5AwwWFurJwtRq4EtRxzAq+vctJsZcSLgGxOczNI=", + "h1:mmbm4vTyC/DCGO4Ed/vbp5AKvy1gmVn/94fzB9VmR08=", + "h1:pnJ5M2g8UDabX2GZLzi5piapRKvrZAWoBIIx3ipulWQ=", + "h1:z/E1KtF70UEfa2/sm5fhVAcmfDyPxDZa38jbYkU2Jso=", + "zh:0bde54f6f658b20b620b875daf106b5b25b1bae4d15408d6c5f06d58360e254d", + "zh:0c97c6930015918b8a34b6d7a2b0c3d17a649c226fcd1874fcba5bbbc0f35972", + "zh:1bdd7aa0011c5f024a09a124836ee9bc8e71b05a6ece810c61824275fd3f695f", + "zh:2b0cc7c794e4caf395d84ffff0b380d17e4b3219a4696264271bfe5059450efe", + "zh:2f8633f7fe07f76c188836ed6f93321ec5fbf5c004bc7699e1741d9b21ed5f37", + "zh:5bf47eed286ce55ed10a5cf657de49a34ab21cc8677c56fef3aab69cdde41a27", + "zh:7dca790fc5fd1d42bc4bc7170be003a7093602026d0f95c8aab84ad551fdf2a4", + "zh:80476b68bc84e3d661d1390025f83879b88f9cdc836de9751af09bd5716089cb", + "zh:82f3e2f3f50176cd6041c8ba36e295cbda1b289ef52ab75b5eceb0f921f64f7b", + "zh:a179b165f3b9bb9a67ebbbf9d73157ded33f02d476b2f58906389dca03b653c9", + "zh:acae54a5d0616f22b3180ddd8e8aad39af664e604394fdacf1f7b337bca2d5b4", + "zh:da4406a2428a9a7e98272c032cb93431c3919253af2fe9934b532d26c0deab09", + "zh:f63dbd8e579ab5268d01ffab4503b8a8e736b70d1a04e4f271559ba8dd133dcd", + "zh:f85c1d9e51a94ecde137435c9d6b0fb7be590437ea8a725334d1577eebbc550c", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.6.0" - constraints = "3.6.0" + version = "3.6.2" + constraints = "3.6.2" hashes = [ - "h1:5KeoKSVKVHJW308uiTgslxFbjQAdWzBGUFK68vgMRWY=", - "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", - "h1:R5Ucn26riKIEijcsiOMBR3uOAjuOMfI1x7XvH4P6B1w=", - "h1:p6WG1IPHnqx1fnJVKNjv733FBaArIugqy58HRZnpPCk=", - "h1:t0mRdJzegohRKhfdoQEJnv3JRISSezJRblN0HIe67vo=", - "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", - "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", - "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", - "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", - "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", + "h1:5lstwe/L8AZS/CP0lil2nPvmbbjAu8kCaU/ogSGNbxk=", + "h1:R5qdQjKzOU16TziCN1vR3Exr/B+8WGK80glLTT4ZCPk=", + "h1:UQlmHGddu39vVzG8kruMsde4GHlG+1S7OLqFApbJvtc=", + "h1:VavG5unYCa3SYISMKF9pzc3718M0bhPlcbUZZGl7wuo=", + "h1:wmG0QFjQ2OfyPy6BB7mQ57WtoZZGGV07uAPQeDmIrAE=", + "zh:0ef01a4f81147b32c1bea3429974d4d104bbc4be2ba3cfa667031a8183ef88ec", + "zh:1bcd2d8161e89e39886119965ef0f37fcce2da9c1aca34263dd3002ba05fcb53", + "zh:37c75d15e9514556a5f4ed02e1548aaa95c0ecd6ff9af1119ac905144c70c114", + "zh:4210550a767226976bc7e57d988b9ce48f4411fa8a60cd74a6b246baf7589dad", + "zh:562007382520cd4baa7320f35e1370ffe84e46ed4e2071fdc7e4b1a9b1f8ae9b", + "zh:5efb9da90f665e43f22c2e13e0ce48e86cae2d960aaf1abf721b497f32025916", + "zh:6f71257a6b1218d02a573fc9bff0657410404fb2ef23bc66ae8cd968f98d5ff6", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", - "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", - "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", - "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", - "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", - "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", + "zh:9647e18f221380a85f2f0ab387c68fdafd58af6193a932417299cdcae4710150", + "zh:bb6297ce412c3c2fa9fec726114e5e0508dd2638cad6a0cb433194930c97a544", + "zh:f83e925ed73ff8a5ef6e3608ad9225baa5376446349572c2449c0c0b3cf184b7", + "zh:fbef0781cb64de76b1df1ca11078aecba7800d82fd4a956302734999cfd9a4af", ] } diff --git a/terraform/infrastructure/qemu/main.tf b/terraform/infrastructure/qemu/main.tf index 047e9dbdc..52b3138dc 100644 --- a/terraform/infrastructure/qemu/main.tf +++ b/terraform/infrastructure/qemu/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { libvirt = { source = "dmacvicar/libvirt" - version = "0.7.1" + version = "0.7.6" } docker = { source = "kreuzwerker/docker" @@ -23,6 +23,13 @@ locals { cidr_vpc_subnet_nodes = "10.42.0.0/22" cidr_vpc_subnet_control_planes = "10.42.1.0/24" cidr_vpc_subnet_worker = "10.42.2.0/24" + revision = 1 +} + +# A way to force replacement of resources if the provider does not want to replace them +# see: https://developer.hashicorp.com/terraform/language/resources/terraform-data#example-usage-data-for-replace_triggered_by +resource "terraform_data" "replacement" { + input = local.revision } resource "random_password" "init_secret" { diff --git a/terraform/infrastructure/qemu/modules/instance_group/main.tf b/terraform/infrastructure/qemu/modules/instance_group/main.tf index 75ecbf2b8..f81420d57 100644 --- a/terraform/infrastructure/qemu/modules/instance_group/main.tf +++ b/terraform/infrastructure/qemu/modules/instance_group/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { libvirt = { source = "dmacvicar/libvirt" - version = "0.7.1" + version = "0.7.6" } random = { source = "hashicorp/random" - version = "3.6.0" + version = "3.6.2" } } } diff --git a/upgrade-agent/cmd/main.go b/upgrade-agent/cmd/main.go index 2eaabb91d..ba2906bc7 100644 --- a/upgrade-agent/cmd/main.go +++ b/upgrade-agent/cmd/main.go @@ -23,17 +23,10 @@ const ( ) func main() { - gRPCDebug := flag.Bool("debug", false, "Enable gRPC debug logging") verbosity := flag.Int("v", 0, logger.CmdLineVerbosityDescription) flag.Parse() - - log := logger.NewJSONLogger(logger.VerbosityFromInt(*verbosity)).WithGroup("bootstrapper") - - if *gRPCDebug { - logger.ReplaceGRPCLogger(log.WithGroup("gRPC")) - } else { - logger.ReplaceGRPCLogger(slog.New(logger.NewLevelHandler(slog.LevelWarn, log.Handler())).WithGroup("gRPC")) - } + log := logger.NewJSONLogger(logger.VerbosityFromInt(*verbosity)).WithGroup("upgrade-agent") + logger.ReplaceGRPCLogger(logger.GRPCLogger(log)) handler := file.NewHandler(afero.NewOsFs()) server, err := server.New(log, handler) diff --git a/upgrade-agent/internal/server/BUILD.bazel b/upgrade-agent/internal/server/BUILD.bazel index 0d6275d78..e7424a639 100644 --- a/upgrade-agent/internal/server/BUILD.bazel +++ b/upgrade-agent/internal/server/BUILD.bazel @@ -13,7 +13,7 @@ go_library( "//internal/logger", "//internal/versions/components", "//upgrade-agent/upgradeproto", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//status", "@org_golang_x_mod//semver", diff --git a/upgrade-agent/internal/server/server.go b/upgrade-agent/internal/server/server.go index ea18e3d57..3221baed5 100644 --- a/upgrade-agent/internal/server/server.go +++ b/upgrade-agent/internal/server/server.go @@ -54,7 +54,7 @@ func New(log *slog.Logger, fileHandler file.Handler) (*Server, error) { } grpcServer := grpc.NewServer( - logger.GetServerUnaryInterceptor(log.WithGroup("gRPC")), + logger.GetServerUnaryInterceptor(logger.GRPCLogger(log)), ) upgradeproto.RegisterUpdateServer(grpcServer, server) @@ -111,12 +111,18 @@ func (s *Server) ExecuteUpdate(ctx context.Context, updateRequest *upgradeproto. return nil, status.Errorf(codes.Internal, "unable to install the kubeadm binary: %s", err) } - upgradeCmd := exec.CommandContext(ctx, "kubeadm", "upgrade", "plan", updateRequest.WantedKubernetesVersion) + // CoreDNS addon status is checked even though we did not install it. + // TODO(burgerdev): Use kubeadm phases once supported: https://github.com/kubernetes/kubeadm/issues/1318. + commonArgs := []string{"--ignore-preflight-errors", "CoreDNSMigration,CoreDNSUnsupportedPlugins", updateRequest.WantedKubernetesVersion} + planArgs := append([]string{"upgrade", "plan"}, commonArgs...) + applyArgs := append([]string{"upgrade", "apply", "--yes", "--patches", constants.KubeadmPatchDir}, commonArgs...) + + upgradeCmd := exec.CommandContext(ctx, "kubeadm", planArgs...) if out, err := upgradeCmd.CombinedOutput(); err != nil { return nil, status.Errorf(codes.Internal, "unable to execute kubeadm upgrade plan %s: %s: %s", updateRequest.WantedKubernetesVersion, err, string(out)) } - applyCmd := exec.CommandContext(ctx, "kubeadm", "upgrade", "apply", "--yes", "--patches", constants.KubeadmPatchDir, updateRequest.WantedKubernetesVersion) + applyCmd := exec.CommandContext(ctx, "kubeadm", applyArgs...) if out, err := applyCmd.CombinedOutput(); err != nil { return nil, status.Errorf(codes.Internal, "unable to execute kubeadm upgrade apply: %s: %s", err, string(out)) } diff --git a/upgrade-agent/upgradeproto/upgrade.pb.go b/upgrade-agent/upgradeproto/upgrade.pb.go index 1fb32ecfb..3ad16c64d 100644 --- a/upgrade-agent/upgradeproto/upgrade.pb.go +++ b/upgrade-agent/upgradeproto/upgrade.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.1 -// protoc v4.22.1 +// protoc-gen-go v1.35.1 +// protoc v5.29.0--rc2 // source: upgrade-agent/upgradeproto/upgrade.proto package upgradeproto @@ -36,11 +36,9 @@ type ExecuteUpdateRequest struct { func (x *ExecuteUpdateRequest) Reset() { *x = ExecuteUpdateRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_upgrade_agent_upgradeproto_upgrade_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_upgrade_agent_upgradeproto_upgrade_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ExecuteUpdateRequest) String() string { @@ -51,7 +49,7 @@ func (*ExecuteUpdateRequest) ProtoMessage() {} func (x *ExecuteUpdateRequest) ProtoReflect() protoreflect.Message { mi := &file_upgrade_agent_upgradeproto_upgrade_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -88,11 +86,9 @@ type ExecuteUpdateResponse struct { func (x *ExecuteUpdateResponse) Reset() { *x = ExecuteUpdateResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_upgrade_agent_upgradeproto_upgrade_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_upgrade_agent_upgradeproto_upgrade_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ExecuteUpdateResponse) String() string { @@ -103,7 +99,7 @@ func (*ExecuteUpdateResponse) ProtoMessage() {} func (x *ExecuteUpdateResponse) ProtoReflect() protoreflect.Message { mi := &file_upgrade_agent_upgradeproto_upgrade_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -167,7 +163,7 @@ func file_upgrade_agent_upgradeproto_upgrade_proto_rawDescGZIP() []byte { } var file_upgrade_agent_upgradeproto_upgrade_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_upgrade_agent_upgradeproto_upgrade_proto_goTypes = []interface{}{ +var file_upgrade_agent_upgradeproto_upgrade_proto_goTypes = []any{ (*ExecuteUpdateRequest)(nil), // 0: upgrade.ExecuteUpdateRequest (*ExecuteUpdateResponse)(nil), // 1: upgrade.ExecuteUpdateResponse (*components.Component)(nil), // 2: components.Component @@ -188,32 +184,6 @@ func file_upgrade_agent_upgradeproto_upgrade_proto_init() { if File_upgrade_agent_upgradeproto_upgrade_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_upgrade_agent_upgradeproto_upgrade_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExecuteUpdateRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_upgrade_agent_upgradeproto_upgrade_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExecuteUpdateResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/verify/server/BUILD.bazel b/verify/server/BUILD.bazel index 3cd658b83..1561eb055 100644 --- a/verify/server/BUILD.bazel +++ b/verify/server/BUILD.bazel @@ -10,7 +10,7 @@ go_library( "//internal/constants", "//internal/logger", "//verify/verifyproto", - "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//:grpc", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//keepalive", "@org_golang_google_grpc//peer", diff --git a/verify/server/server.go b/verify/server/server.go index c8d7b2c82..16ab70b07 100644 --- a/verify/server/server.go +++ b/verify/server/server.go @@ -56,9 +56,10 @@ func (s *Server) Run(httpListener, grpcListener net.Listener) error { var wg sync.WaitGroup var once sync.Once - logger.ReplaceGRPCLogger(slog.New(logger.NewLevelHandler(slog.LevelWarn, s.log.Handler()).WithGroup("grpc"))) + grpcLog := logger.GRPCLogger(s.log) + logger.ReplaceGRPCLogger(grpcLog) grpcServer := grpc.NewServer( - logger.GetServerUnaryInterceptor(s.log.WithGroup("gRPC")), + logger.GetServerUnaryInterceptor(grpcLog), grpc.KeepaliveParams(keepalive.ServerParameters{Time: 15 * time.Second}), ) verifyproto.RegisterAPIServer(grpcServer, s) diff --git a/verify/verifyproto/verify.pb.go b/verify/verifyproto/verify.pb.go index 6c1b13f13..9a68d32c0 100644 --- a/verify/verifyproto/verify.pb.go +++ b/verify/verifyproto/verify.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.1 -// protoc v4.22.1 +// protoc-gen-go v1.35.1 +// protoc v5.29.0--rc2 // source: verify/verifyproto/verify.proto package verifyproto @@ -34,11 +34,9 @@ type GetAttestationRequest struct { func (x *GetAttestationRequest) Reset() { *x = GetAttestationRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_verify_verifyproto_verify_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_verify_verifyproto_verify_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GetAttestationRequest) String() string { @@ -49,7 +47,7 @@ func (*GetAttestationRequest) ProtoMessage() {} func (x *GetAttestationRequest) ProtoReflect() protoreflect.Message { mi := &file_verify_verifyproto_verify_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -81,11 +79,9 @@ type GetAttestationResponse struct { func (x *GetAttestationResponse) Reset() { *x = GetAttestationResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_verify_verifyproto_verify_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_verify_verifyproto_verify_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GetAttestationResponse) String() string { @@ -96,7 +92,7 @@ func (*GetAttestationResponse) ProtoMessage() {} func (x *GetAttestationResponse) ProtoReflect() protoreflect.Message { mi := &file_verify_verifyproto_verify_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -156,7 +152,7 @@ func file_verify_verifyproto_verify_proto_rawDescGZIP() []byte { } var file_verify_verifyproto_verify_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_verify_verifyproto_verify_proto_goTypes = []interface{}{ +var file_verify_verifyproto_verify_proto_goTypes = []any{ (*GetAttestationRequest)(nil), // 0: verify.GetAttestationRequest (*GetAttestationResponse)(nil), // 1: verify.GetAttestationResponse } @@ -175,32 +171,6 @@ func file_verify_verifyproto_verify_proto_init() { if File_verify_verifyproto_verify_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_verify_verifyproto_verify_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetAttestationRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_verify_verifyproto_verify_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetAttestationResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/version.txt b/version.txt index 8dbd61013..62717a0a7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v2.17.0-pre +v2.20.0-pre