mirror of https://github.com/spiffe/spire.git
Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
|
872f76d4e1 | |
|
8535a1a19f |
|
@ -1,8 +0,0 @@
|
|||
toplevel="$(git rev-parse --show-toplevel)"
|
||||
|
||||
# build and use the managed go sdk
|
||||
unset GOROOT
|
||||
make -C "$toplevel" go-check
|
||||
PATH="$(make --no-print-directory -C "$toplevel" go-bin-path)"
|
||||
|
||||
# add custom direnv initialization below here
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh
|
||||
# Copyright 2012 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
# git gofmt pre-commit hook
|
||||
#
|
||||
# To use, store as .git/hooks/pre-commit inside your repository and make sure
|
||||
# it has execute permissions.
|
||||
#
|
||||
# This script does not handle file names that contain spaces.
|
||||
|
||||
gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '\.go$')
|
||||
[ -z "$gofiles" ] && exit 0
|
||||
|
||||
unformatted=$(gofmt -l $gofiles)
|
||||
[ -z "$unformatted" ] && exit 0
|
||||
|
||||
# Some files are not gofmt'd. Print message and fail.
|
||||
|
||||
echo >&2 "Go files must be formatted with gofmt. Please run:"
|
||||
for fn in $unformatted; do
|
||||
echo >&2 " gofmt -w $PWD/$fn"
|
||||
done
|
||||
|
||||
exit 1
|
|
@ -7,24 +7,18 @@ updates:
|
|||
time: "09:00"
|
||||
timezone: "America/Los_Angeles"
|
||||
groups:
|
||||
actions:
|
||||
patterns:
|
||||
- "github.com/actions/*"
|
||||
aws-sdk:
|
||||
patterns:
|
||||
- "github.com/aws/aws-sdk-go-v2/*"
|
||||
azure-sdk:
|
||||
patterns:
|
||||
- "github.com/Azure/azure-sdk-for-go/*"
|
||||
google-cloud-sdk:
|
||||
patterns:
|
||||
- "cloud.google.com/go/*"
|
||||
k8s.io:
|
||||
patterns:
|
||||
- "k8s.io/*"
|
||||
sigs.k8s.io:
|
||||
patterns:
|
||||
- "sig.k8s.io/*"
|
||||
azure-sdk:
|
||||
patterns:
|
||||
- "github.com/Azure/azure-sdk-for-go/*"
|
||||
ignore:
|
||||
- dependency-name: "github.com/spiffe/spire-api-sdk"
|
||||
- dependency-name: "github.com/spiffe/spire-plugin-sdk"
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
name: DCO
|
||||
on:
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
merge_group:
|
||||
types:
|
||||
- checks_requested
|
||||
jobs:
|
||||
check-dco:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Check DCO
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
pip3 install -U dco-check
|
||||
dco-check --exclude-pattern 'dependabot\[bot\]@users\.noreply\.github\.com'
|
|
@ -10,6 +10,6 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0
|
||||
uses: actions/dependency-review-action@6c5ccdad469c9f8a2996bfecaec55a631a347034 # v3.1.0
|
||||
|
|
|
@ -10,26 +10,29 @@ env:
|
|||
|
||||
jobs:
|
||||
build-and-publish-images:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
|
||||
env:
|
||||
COSIGN_EXPERIMENTAL: 1
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0
|
||||
uses: sigstore/cosign-installer@11086d25041f77fe8fe7b9ea4e48e3b9192b8f19 # v3.1.2
|
||||
with:
|
||||
cosign-release: v2.2.3
|
||||
cosign-release: v1.13.1
|
||||
- name: Install regctl
|
||||
uses: regclient/actions/regctl-installer@ce5fd131e371ffcdd7508b478cb223b3511a9183 # main
|
||||
uses: regclient/actions/regctl-installer@b6614f5f56245066b533343a85f4109bdc38c8cc # main
|
||||
- name: Build images
|
||||
run: make images
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
@ -2,16 +2,15 @@ name: PR Build
|
|||
on:
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
merge_group:
|
||||
types:
|
||||
- checks_requested
|
||||
env:
|
||||
GO_VERSION: 1.21.1
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
cache-deps:
|
||||
name: cache-deps (linux)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 30
|
||||
|
||||
permissions:
|
||||
|
@ -19,13 +18,13 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup dep cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
|
@ -34,7 +33,7 @@ jobs:
|
|||
|
||||
lint:
|
||||
name: lint (linux)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: cache-deps
|
||||
timeout-minutes: 30
|
||||
|
||||
|
@ -43,18 +42,18 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Setup build tool cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
|
@ -70,7 +69,7 @@ jobs:
|
|||
unit-test:
|
||||
strategy:
|
||||
matrix:
|
||||
OS: [ubuntu-22.04, macos-latest]
|
||||
OS: [ubuntu-20.04, macos-latest]
|
||||
runs-on: ${{ matrix.OS }}
|
||||
needs: cache-deps
|
||||
timeout-minutes: 30
|
||||
|
@ -80,13 +79,13 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
|
@ -95,7 +94,7 @@ jobs:
|
|||
|
||||
unit-test-race-detector:
|
||||
name: unit-test (linux with race detection)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: cache-deps
|
||||
timeout-minutes: 30
|
||||
|
||||
|
@ -104,13 +103,13 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
|
@ -119,7 +118,7 @@ jobs:
|
|||
|
||||
artifacts:
|
||||
name: artifacts (linux)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [cache-deps, images]
|
||||
timeout-minutes: 30
|
||||
|
||||
|
@ -128,15 +127,15 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Install regctl
|
||||
uses: regclient/actions/regctl-installer@ce5fd131e371ffcdd7508b478cb223b3511a9183 # main
|
||||
uses: regclient/actions/regctl-installer@b6614f5f56245066b533343a85f4109bdc38c8cc # main
|
||||
- name: Download archived images
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: images
|
||||
path: .
|
||||
|
@ -146,14 +145,14 @@ jobs:
|
|||
- name: Build artifacts
|
||||
run: ./.github/workflows/scripts/build_artifacts.sh ${{ runner.os }}
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: binaries-linux
|
||||
name: binaries
|
||||
path: ./artifacts/
|
||||
|
||||
images:
|
||||
name: images (linux)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [cache-deps]
|
||||
timeout-minutes: 30
|
||||
|
||||
|
@ -162,31 +161,31 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Load cached build tools
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0
|
||||
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
- name: Build images
|
||||
run: make images-no-load
|
||||
- name: Export images
|
||||
run: tar -czvf images.tar.gz *-image.tar
|
||||
- name: Archive images
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: images
|
||||
path: images.tar.gz
|
||||
|
@ -194,7 +193,7 @@ jobs:
|
|||
images-windows:
|
||||
name: images (windows)
|
||||
runs-on: windows-2022
|
||||
needs: artifacts-windows
|
||||
needs: artifact-windows
|
||||
timeout-minutes: 45
|
||||
|
||||
permissions:
|
||||
|
@ -202,12 +201,12 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Load cached executables
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: bin-windows
|
||||
path: ./bin/
|
||||
key: ${{ runner.os }}-executables-${{ github.sha }}
|
||||
- name: Build images
|
||||
run: make images-windows
|
||||
- name: Export images
|
||||
|
@ -215,20 +214,20 @@ jobs:
|
|||
docker save spire-server-windows:latest-local spire-agent-windows:latest-local oidc-discovery-provider-windows:latest-local -o images-windows.tar
|
||||
gzip images-windows.tar
|
||||
- name: Archive images
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: images-windows
|
||||
path: images-windows.tar.gz
|
||||
|
||||
build-matrix:
|
||||
name: Build matrix
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [cache-deps]
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- id: set-matrix
|
||||
name: Collect versions
|
||||
run: |
|
||||
|
@ -239,9 +238,10 @@ jobs:
|
|||
outputs:
|
||||
test: ${{ steps.set-matrix.outputs.test }}
|
||||
|
||||
|
||||
integration:
|
||||
name: integration (${{ matrix.arch }}) (${{ strategy.job-index}}/${{ strategy.job-total }})
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
name: integration (linux)
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [cache-deps, images]
|
||||
timeout-minutes: 45
|
||||
|
||||
|
@ -251,17 +251,11 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [x64, arm64]
|
||||
num_runners: [10]
|
||||
runner_id: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
include:
|
||||
- arch: x64
|
||||
runs-on: ubuntu-22.04
|
||||
- arch: arm64
|
||||
runs-on: ubuntu-22.04-arm
|
||||
num_runners: [5]
|
||||
runner_id: [1, 2, 3, 4, 5]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
with:
|
||||
# The "upgrade" integration test needs the history to ensure
|
||||
# that the version number in the source code has been bumped as
|
||||
|
@ -269,23 +263,23 @@ jobs:
|
|||
# fetch depth of zero.
|
||||
fetch-depth: 0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Install regctl
|
||||
uses: regclient/actions/regctl-installer@ce5fd131e371ffcdd7508b478cb223b3511a9183 # main
|
||||
uses: regclient/actions/regctl-installer@b6614f5f56245066b533343a85f4109bdc38c8cc # main
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Load cached build tools
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Download archived images
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: images
|
||||
path: .
|
||||
|
@ -299,12 +293,13 @@ jobs:
|
|||
THIS_RUNNER: ${{ matrix.runner_id }}
|
||||
TERM: dumb
|
||||
CICD_TARGET_BRANCH: ${{ github.event.pull_request.base.ref }}
|
||||
IGNORE_SUITES: ${{ matrix.arch == 'arm64' && 'suites/upstream-authority-ejbca' || '' }} # Waiting for EJBCA to support arm64 (https://github.com/spiffe/spire/issues/6060)
|
||||
run: ./.github/workflows/scripts/split.sh | xargs ./test/integration/test.sh
|
||||
|
||||
|
||||
|
||||
integration-k8s:
|
||||
name: integration-k8s-${{ matrix.test[0] }}-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
name: integration-k8s
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [cache-deps, images, build-matrix]
|
||||
timeout-minutes: 45
|
||||
|
||||
|
@ -314,21 +309,13 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [x64, arm64]
|
||||
include:
|
||||
- arch: x64
|
||||
runs-on: ubuntu-22.04
|
||||
num_runners: 1
|
||||
runner_id: 1
|
||||
- arch: arm64
|
||||
runs-on: ubuntu-22.04-arm
|
||||
num_runners: 1
|
||||
runner_id: 1
|
||||
#Test elements should be added as [KubeCTLVersion, K8s-image, KindVersion]
|
||||
test: ${{ fromJson(needs.build-matrix.outputs.test) }}
|
||||
num_runners: [1]
|
||||
runner_id: [1]
|
||||
#Test elements should be added as [KubeCTLVersion, K8s-image, KindVersion]
|
||||
test: ${{ fromJson(needs.build-matrix.outputs.test) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
with:
|
||||
# The "upgrade" integration test needs the history to ensure
|
||||
# that the version number in the source code has been bumped as
|
||||
|
@ -336,23 +323,23 @@ jobs:
|
|||
# fetch depth of zero.
|
||||
fetch-depth: 0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Install regctl
|
||||
uses: regclient/actions/regctl-installer@ce5fd131e371ffcdd7508b478cb223b3511a9183 # main
|
||||
uses: regclient/actions/regctl-installer@b6614f5f56245066b533343a85f4109bdc38c8cc # main
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Load cached build tools
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Download archived images
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: images
|
||||
path: .
|
||||
|
@ -378,11 +365,6 @@ jobs:
|
|||
needs: images-windows
|
||||
timeout-minutes: 45
|
||||
|
||||
env:
|
||||
GOPATH: 'D:\golang\go'
|
||||
GOCACHE: 'D:\golang\cache'
|
||||
GOMODCACHE: 'D:\golang\modcache'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
|
@ -391,24 +373,23 @@ jobs:
|
|||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
cache: true
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Load cached build tools
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Install msys2
|
||||
uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2.26.0
|
||||
uses: msys2/setup-msys2@07aeda7763550b267746a772dcea5e5ac3340b36 # v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
update: true
|
||||
|
@ -416,7 +397,7 @@ jobs:
|
|||
install: >-
|
||||
git base-devel mingw-w64-x86_64-toolchain unzip
|
||||
- name: Download archived images
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: images-windows
|
||||
path: .
|
||||
|
@ -431,24 +412,18 @@ jobs:
|
|||
runs-on: windows-2022
|
||||
timeout-minutes: 45
|
||||
|
||||
env:
|
||||
GOPATH: 'D:\golang\go'
|
||||
GOCACHE: 'D:\golang\cache'
|
||||
GOMODCACHE: 'D:\golang\modcache'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
cache: true
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup dep cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
|
@ -461,11 +436,6 @@ jobs:
|
|||
needs: cache-deps-windows
|
||||
timeout-minutes: 45
|
||||
|
||||
env:
|
||||
GOPATH: 'D:\golang\go'
|
||||
GOCACHE: 'D:\golang\cache'
|
||||
GOMODCACHE: 'D:\golang\modcache'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
|
@ -474,24 +444,23 @@ jobs:
|
|||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
cache: true
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Setup build tool cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Install msys2
|
||||
uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2.26.0
|
||||
uses: msys2/setup-msys2@07aeda7763550b267746a772dcea5e5ac3340b36 # v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
update: true
|
||||
|
@ -510,11 +479,6 @@ jobs:
|
|||
needs: cache-deps-windows
|
||||
timeout-minutes: 45
|
||||
|
||||
env:
|
||||
GOPATH: 'D:\golang\go'
|
||||
GOCACHE: 'D:\golang\cache'
|
||||
GOMODCACHE: 'D:\golang\modcache'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
|
@ -523,19 +487,18 @@ jobs:
|
|||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
cache: true
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Install msys2
|
||||
uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2.26.0
|
||||
uses: msys2/setup-msys2@07aeda7763550b267746a772dcea5e5ac3340b36 # v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
update: true
|
||||
|
@ -544,17 +507,12 @@ jobs:
|
|||
- name: Run unit tests
|
||||
run: ./.github/workflows/scripts/run_unit_tests.sh
|
||||
|
||||
artifacts-windows:
|
||||
name: artifacts (windows)
|
||||
artifact-windows:
|
||||
name: artifact (windows)
|
||||
runs-on: windows-2022
|
||||
needs: cache-deps-windows
|
||||
timeout-minutes: 45
|
||||
|
||||
env:
|
||||
GOPATH: 'D:\golang\go'
|
||||
GOCACHE: 'D:\golang\cache'
|
||||
GOMODCACHE: 'D:\golang\modcache'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
|
@ -563,24 +521,23 @@ jobs:
|
|||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
cache: true
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Load cached build tools
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Install msys2
|
||||
uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2.26.0
|
||||
uses: msys2/setup-msys2@07aeda7763550b267746a772dcea5e5ac3340b36 # v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
update: true
|
||||
|
@ -588,22 +545,22 @@ jobs:
|
|||
git base-devel mingw-w64-x86_64-toolchain zip unzip
|
||||
- name: Build binaries
|
||||
run: make build
|
||||
- name: Setup executables cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
with:
|
||||
path: ./bin/
|
||||
key: ${{ runner.os }}-executables-${{ github.sha }}
|
||||
- name: Build artifacts
|
||||
run: ./.github/workflows/scripts/build_artifacts.sh ${{ runner.os }}
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
|
||||
- name: Archive binaries
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: binaries-windows
|
||||
name: bin-windows
|
||||
path: ./bin/
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: binaries
|
||||
path: ./artifacts/
|
||||
|
||||
success:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [lint, unit-test, unit-test-race-detector, artifacts, integration, integration-k8s, lint-windows, unit-test-windows, artifacts-windows, integration-windows]
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [lint, unit-test, unit-test-race-detector, artifacts, integration, lint-windows, unit-test-windows, artifact-windows, integration-windows]
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
|
@ -3,23 +3,25 @@ on:
|
|||
push:
|
||||
tags:
|
||||
- 'v[0-9].[0-9]+.[0-9]+'
|
||||
env:
|
||||
GO_VERSION: 1.21.1
|
||||
jobs:
|
||||
cache-deps:
|
||||
name: cache-deps (linux)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup dep cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
|
@ -28,7 +30,7 @@ jobs:
|
|||
|
||||
lint:
|
||||
name: lint (linux)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: cache-deps
|
||||
|
||||
permissions:
|
||||
|
@ -36,18 +38,18 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Setup build tool cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
|
@ -63,7 +65,7 @@ jobs:
|
|||
unit-test:
|
||||
strategy:
|
||||
matrix:
|
||||
OS: [ubuntu-22.04, macos-latest]
|
||||
OS: [ubuntu-20.04, macos-latest]
|
||||
runs-on: ${{ matrix.OS }}
|
||||
needs: cache-deps
|
||||
|
||||
|
@ -72,13 +74,13 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
|
@ -87,7 +89,7 @@ jobs:
|
|||
|
||||
unit-test-race-detector:
|
||||
name: unit-test (linux with race detection)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: cache-deps
|
||||
|
||||
permissions:
|
||||
|
@ -95,13 +97,13 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
|
@ -110,7 +112,7 @@ jobs:
|
|||
|
||||
artifacts:
|
||||
name: artifacts (linux)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [cache-deps, images]
|
||||
timeout-minutes: 30
|
||||
|
||||
|
@ -119,15 +121,15 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Install regctl
|
||||
uses: regclient/actions/regctl-installer@ce5fd131e371ffcdd7508b478cb223b3511a9183 # main
|
||||
uses: regclient/actions/regctl-installer@b6614f5f56245066b533343a85f4109bdc38c8cc # main
|
||||
- name: Download archived images
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: images
|
||||
path: .
|
||||
|
@ -137,14 +139,14 @@ jobs:
|
|||
- name: Build artifacts
|
||||
run: ./.github/workflows/scripts/build_artifacts.sh ${{ runner.os }}
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: binaries-linux
|
||||
name: binaries
|
||||
path: ./artifacts/
|
||||
|
||||
images:
|
||||
name: images (linux)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [cache-deps]
|
||||
|
||||
permissions:
|
||||
|
@ -152,27 +154,27 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Load cached build tools
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Build images
|
||||
run: TAG=${GITHUB_REF##refs/tags/v} make images-no-load
|
||||
run: make images-no-load
|
||||
- name: Export images
|
||||
run: tar -czvf images.tar.gz *-image.tar
|
||||
- name: Archive images
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: images
|
||||
path: images.tar.gz
|
||||
|
@ -180,19 +182,19 @@ jobs:
|
|||
images-windows:
|
||||
name: images (windows)
|
||||
runs-on: windows-2022
|
||||
needs: artifacts-windows
|
||||
needs: artifact-windows
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Load cached executables
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: bin-windows
|
||||
path: ./bin/
|
||||
key: ${{ runner.os }}-executables-${{ github.sha }}
|
||||
- name: Build images
|
||||
run: make images-windows
|
||||
- name: Export images
|
||||
|
@ -200,20 +202,20 @@ jobs:
|
|||
docker save spire-server-windows:latest-local spire-agent-windows:latest-local oidc-discovery-provider-windows:latest-local -o images-windows.tar
|
||||
gzip images-windows.tar
|
||||
- name: Archive images
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: images-windows
|
||||
path: images-windows.tar.gz
|
||||
|
||||
build-matrix:
|
||||
name: Build matrix
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [cache-deps]
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- id: set-matrix
|
||||
name: Collect versions
|
||||
run: |
|
||||
|
@ -225,10 +227,9 @@ jobs:
|
|||
test: ${{ steps.set-matrix.outputs.test }}
|
||||
|
||||
integration:
|
||||
name: integration (${{ matrix.arch }}) (${{ strategy.job-index}}/${{ strategy.job-total }})
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
name: integration (linux)
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [cache-deps, images]
|
||||
timeout-minutes: 45
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -236,17 +237,11 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [x64, arm64]
|
||||
num_runners: [10]
|
||||
runner_id: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
include:
|
||||
- arch: x64
|
||||
runs-on: ubuntu-22.04
|
||||
- arch: arm64
|
||||
runs-on: ubuntu-22.04-arm
|
||||
num_runners: [5]
|
||||
runner_id: [1, 2, 3, 4, 5]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
with:
|
||||
# The "upgrade" integration test needs the history to ensure
|
||||
# that the version number in the source code has been bumped as
|
||||
|
@ -263,23 +258,23 @@ jobs:
|
|||
- name: Fix tag annotations
|
||||
run: git fetch --tags --force
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Install regctl
|
||||
uses: regclient/actions/regctl-installer@ce5fd131e371ffcdd7508b478cb223b3511a9183 # main
|
||||
uses: regclient/actions/regctl-installer@b6614f5f56245066b533343a85f4109bdc38c8cc # main
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Load cached build tools
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Download archived images
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: images
|
||||
path: .
|
||||
|
@ -292,15 +287,14 @@ jobs:
|
|||
NUM_RUNNERS: ${{ matrix.num_runners }}
|
||||
THIS_RUNNER: ${{ matrix.runner_id }}
|
||||
TERM: dumb
|
||||
IGNORE_SUITES: ${{ matrix.arch == 'arm64' && 'suites/upstream-authority-ejbca' || '' }} # Waiting for EJBCA to support arm64 (https://github.com/spiffe/spire/issues/6060)
|
||||
# We don't need to specify CICD_TARGET_BRANCH since the upgrade
|
||||
# integration test will detect the annotated tag for version checking.
|
||||
# CICD_TARGET_BRANCH:
|
||||
run: ./.github/workflows/scripts/split.sh | xargs ./test/integration/test.sh
|
||||
|
||||
integration-k8s:
|
||||
name: integration-k8s-${{ matrix.test[0] }}-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
name: integration-k8s
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [cache-deps, images, build-matrix]
|
||||
timeout-minutes: 45
|
||||
|
||||
|
@ -310,21 +304,13 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [x64, arm64]
|
||||
include:
|
||||
- arch: x64
|
||||
runs-on: ubuntu-22.04
|
||||
num_runners: 1
|
||||
runner_id: 1
|
||||
- arch: arm64
|
||||
runs-on: ubuntu-22.04-arm
|
||||
num_runners: 1
|
||||
runner_id: 1
|
||||
#Test elements should be added as [KubeCTLVersion, K8s-image, KindVersion]
|
||||
test: ${{ fromJson(needs.build-matrix.outputs.test) }}
|
||||
num_runners: [1]
|
||||
runner_id: [1]
|
||||
#Test elements should be added as [KubeCTLVersion, K8s-image, KindVersion]
|
||||
test: ${{ fromJson(needs.build-matrix.outputs.test) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
with:
|
||||
# The "upgrade" integration test needs the history to ensure
|
||||
# that the version number in the source code has been bumped as
|
||||
|
@ -332,23 +318,23 @@ jobs:
|
|||
# fetch depth of zero.
|
||||
fetch-depth: 0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Install regctl
|
||||
uses: regclient/actions/regctl-installer@ce5fd131e371ffcdd7508b478cb223b3511a9183 # main
|
||||
uses: regclient/actions/regctl-installer@b6614f5f56245066b533343a85f4109bdc38c8cc # main
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Load cached build tools
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Download archived images
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: images
|
||||
path: .
|
||||
|
@ -380,23 +366,23 @@ jobs:
|
|||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Load cached build tools
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Install msys2
|
||||
uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2.26.0
|
||||
uses: msys2/setup-msys2@07aeda7763550b267746a772dcea5e5ac3340b36 # v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
update: true
|
||||
|
@ -404,7 +390,7 @@ jobs:
|
|||
install: >-
|
||||
git base-devel mingw-w64-x86_64-toolchain unzip
|
||||
- name: Download archived images
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: images-windows
|
||||
path: .
|
||||
|
@ -423,13 +409,13 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup dep cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
|
@ -449,23 +435,23 @@ jobs:
|
|||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Setup build tool cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Install msys2
|
||||
uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2.26.0
|
||||
uses: msys2/setup-msys2@07aeda7763550b267746a772dcea5e5ac3340b36 # v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
update: true
|
||||
|
@ -491,18 +477,18 @@ jobs:
|
|||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Install msys2
|
||||
uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2.26.0
|
||||
uses: msys2/setup-msys2@07aeda7763550b267746a772dcea5e5ac3340b36 # v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
update: true
|
||||
|
@ -511,8 +497,8 @@ jobs:
|
|||
- name: Run unit tests
|
||||
run: ./.github/workflows/scripts/run_unit_tests.sh
|
||||
|
||||
artifacts-windows:
|
||||
name: artifacts (windows)
|
||||
artifact-windows:
|
||||
name: artifact (windows)
|
||||
runs-on: windows-2022
|
||||
needs: cache-deps-windows
|
||||
|
||||
|
@ -524,23 +510,23 @@ jobs:
|
|||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Load cached deps
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Load cached build tools
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-tools-${{ hashFiles('.go-version','Makefile') }}
|
||||
- name: Install msys2
|
||||
uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2.26.0
|
||||
uses: msys2/setup-msys2@07aeda7763550b267746a772dcea5e5ac3340b36 # v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
update: true
|
||||
|
@ -550,41 +536,35 @@ jobs:
|
|||
run: make build
|
||||
- name: Build artifacts
|
||||
run: ./.github/workflows/scripts/build_artifacts.sh ${{ runner.os }}
|
||||
- name: Setup executables cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
- name: Archive binaries
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: bin-windows
|
||||
path: ./bin/
|
||||
key: ${{ runner.os }}-executables-${{ github.sha }}
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: binaries-windows
|
||||
name: binaries
|
||||
path: ./artifacts/
|
||||
|
||||
publish-artifacts:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [lint, unit-test, unit-test-race-detector, artifacts, integration, integration-k8s, lint-windows, unit-test-windows, artifacts-windows, integration-windows]
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [lint, unit-test, unit-test-race-detector, artifacts, integration, lint-windows, unit-test-windows, artifact-windows, integration-windows]
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Download archived Linux artifacts
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Download archived artifacts
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: binaries-linux
|
||||
name: binaries
|
||||
path: ./artifacts/
|
||||
- name: Download archived Windows artifacts
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: binaries-windows
|
||||
path: ./artifacts/
|
||||
|
||||
- name: Create Release
|
||||
env:
|
||||
# GH_REPO is required for older releases of `gh`. Until we're
|
||||
# reasonably confident that the gh release is new enough,
|
||||
# reasonably confident that that the gh release is new enough,
|
||||
# set GH_REPO to the repository to create the release in.
|
||||
#
|
||||
# See https://github.com/cli/cli/issues/3556
|
||||
|
@ -594,29 +574,32 @@ jobs:
|
|||
run: gh release create "${GITHUB_REF#refs/tags/}" ./artifacts/*.zip ./artifacts/*.tar.gz ./artifacts/*.txt --title "${GITHUB_REF#refs/tags/}"
|
||||
|
||||
publish-images:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [lint, unit-test, unit-test-race-detector, artifacts, integration, integration-k8s, lint-windows, unit-test-windows, artifacts-windows, integration-windows]
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [lint, unit-test, unit-test-race-detector, artifacts, integration, lint-windows, unit-test-windows, artifact-windows, integration-windows]
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
|
||||
env:
|
||||
COSIGN_EXPERIMENTAL: 1
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0
|
||||
uses: sigstore/cosign-installer@11086d25041f77fe8fe7b9ea4e48e3b9192b8f19 # v3.1.2
|
||||
with:
|
||||
cosign-release: v2.2.3
|
||||
cosign-release: v1.13.1
|
||||
- name: Install regctl
|
||||
uses: regclient/actions/regctl-installer@ce5fd131e371ffcdd7508b478cb223b3511a9183 # main
|
||||
uses: regclient/actions/regctl-installer@b6614f5f56245066b533343a85f4109bdc38c8cc # main
|
||||
- name: Download archived images
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: images
|
||||
path: .
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
@ -23,13 +23,6 @@
|
|||
|
||||
declare -A tags_map
|
||||
for element in "${tags_sorted[@]}"; do
|
||||
# Skip 1.32.1 until either a new version of kind is released the problem
|
||||
# with the kindest/node:1.32.1 image is fixed. See upstream kind issue:
|
||||
# https://github.com/kubernetes-sigs/kind/issues/3853
|
||||
if [[ "$element" == "v1.32.1" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Element is in this form: "X.XX.YY"
|
||||
# If not, continue
|
||||
num_dots=$(echo "$element" | grep -o '\.' | wc -l)
|
||||
|
|
|
@ -68,5 +68,5 @@ for img in "${OCI_IMAGES[@]}"; do
|
|||
|
||||
image_digest="$(jq -r '.manifests[0].digest' "${ROOTDIR}oci/${img}/index.json")"
|
||||
|
||||
cosign sign -y "${registry}/${img}@${image_digest}"
|
||||
cosign sign "${registry}/${img}@${image_digest}"
|
||||
done
|
||||
|
|
|
@ -18,7 +18,7 @@ for FILE in test/integration/suites/*; do
|
|||
job_set[$current_runner]+="${FILE##test/integration/} "
|
||||
|
||||
((current_runner++))
|
||||
if [ "$current_runner" -gt "$NUM_RUNNERS" ]; then
|
||||
if [ $current_runner -gt "$NUM_RUNNERS" ]; then
|
||||
current_runner=1
|
||||
fi
|
||||
done
|
||||
|
|
|
@ -18,7 +18,7 @@ for FILE in test/integration/suites/k8s*; do
|
|||
job_set[$current_runner]+="${FILE##test/integration/} "
|
||||
|
||||
((current_runner++))
|
||||
if [ "$current_runner" -gt "$NUM_RUNNERS" ]; then
|
||||
if [ $current_runner -gt "$NUM_RUNNERS" ]; then
|
||||
current_runner=1
|
||||
fi
|
||||
done
|
||||
|
|
|
@ -11,29 +11,12 @@ jobs:
|
|||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
|
||||
- uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0
|
||||
with:
|
||||
days-before-issue-stale: 365 # 1 year
|
||||
days-before-issue-close: 30
|
||||
stale-issue-label: "stale"
|
||||
exempt-issue-labels: "blocked" # Ignore blocked issues
|
||||
stale-issue-message: "This issue is stale because it has been open for 365 days with no activity."
|
||||
close-issue-message: "This issue was closed because it has been inactive for 30 days since being marked as stale."
|
||||
days-before-pr-stale: -1 # Don't handle PRs
|
||||
days-before-pr-close: -1 # Don't handle PRs
|
||||
|
||||
process-stale-blocked-issues:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
|
||||
with:
|
||||
only-labels: "blocked"
|
||||
days-before-issue-stale: 30
|
||||
days-before-issue-close: -1 # Don't close blocked issues
|
||||
stale-issue-label: "stale"
|
||||
stale-issue-message: "This issue has been in the blocked state for 30 days, marking as stale so the blocking issue is re-checked."
|
||||
days-before-pr-stale: -1 # Don't handle PRs
|
||||
days-before-pr-close: -1 # Don't handle PRs
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
.build
|
||||
.cache
|
||||
.data
|
||||
.envrc
|
||||
.glide
|
||||
.tmp
|
||||
.DS_Store
|
||||
|
@ -37,7 +36,3 @@ tools/spire-plugingen/spire-plugingen
|
|||
# oci artifacts
|
||||
*-image.tar
|
||||
oci/
|
||||
|
||||
# Go workspace files
|
||||
go.work
|
||||
go.work.sum
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.24.4
|
||||
1.21.1
|
||||
|
|
|
@ -1,87 +1,31 @@
|
|||
version: "2"
|
||||
run:
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
timeout: 12m
|
||||
|
||||
skip-dirs:
|
||||
- testdata$
|
||||
- test/mock
|
||||
|
||||
skip-files:
|
||||
- ".*\\.pb\\.go"
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- bodyclose
|
||||
- copyloopvar
|
||||
- durationcheck
|
||||
- errorlint
|
||||
- exptostd
|
||||
- gocritic
|
||||
- goimports
|
||||
- revive
|
||||
- gosec
|
||||
- intrange
|
||||
- mirror
|
||||
- misspell
|
||||
- nakedret
|
||||
- nilnesserr
|
||||
- nolintlint
|
||||
- predeclared
|
||||
- reassign
|
||||
- revive
|
||||
- unconvert
|
||||
- unparam
|
||||
- wastedassign
|
||||
- whitespace
|
||||
settings:
|
||||
govet:
|
||||
enable:
|
||||
- sortslice
|
||||
- unusedwrite
|
||||
revive:
|
||||
confidence: 0
|
||||
rules:
|
||||
- name: atomic
|
||||
- name: bool-literal-in-expr
|
||||
- name: constant-logical-expr
|
||||
- name: context-as-argument
|
||||
- name: datarace
|
||||
- name: error-naming
|
||||
- name: error-return
|
||||
- name: errorf
|
||||
- name: identical-branches
|
||||
- name: if-return
|
||||
- name: increment-decrement
|
||||
- name: modifies-value-receiver
|
||||
- name: optimize-operands-order
|
||||
- name: range
|
||||
- name: receiver-naming
|
||||
- name: redundant-import-alias
|
||||
- name: redundant-test-main-exit
|
||||
- name: string-of-int
|
||||
- name: time-equal
|
||||
- name: unconditional-recursion
|
||||
- name: unnecessary-stmt
|
||||
- name: unreachable-code
|
||||
- name: use-any
|
||||
- name: use-errors-new
|
||||
- name: useless-break
|
||||
- name: var-declaration
|
||||
- name: waitgroup-by-value
|
||||
staticcheck:
|
||||
checks:
|
||||
- all
|
||||
- -ST1003
|
||||
- -QF1001
|
||||
- -QF1008
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
rules:
|
||||
- linters:
|
||||
- gosec
|
||||
path: (.*_test\.go$)|(^test/.*)
|
||||
text: integer overflow conversion
|
||||
- linters:
|
||||
- revive
|
||||
text: Import alias "v1" is redundant
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
- gocritic
|
||||
- nolintlint
|
||||
|
||||
linters-settings:
|
||||
revive:
|
||||
# minimal confidence for issues, default is 0.8
|
||||
confidence: 0.0
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
golangci-lint v2.1.6
|
||||
markdown_lint v0.37.0
|
||||
protoc 29.4
|
34
ADOPTERS.md
34
ADOPTERS.md
|
@ -20,7 +20,6 @@ Known end users with notable contributions to the advancement of the project inc
|
|||
|
||||
SPIFFE and SPIRE are being used by numerous other companies, both large and small, to build higher layer products and services. The list includes but is not limited to:
|
||||
|
||||
* AccuKnox
|
||||
* Amazon
|
||||
* Arm
|
||||
* Cisco
|
||||
|
@ -43,24 +42,23 @@ SPIFFE and SPIRE have integrations available with a number of open-source projec
|
|||
|
||||
* [App Mesh Controller](https://github.com/aws/aws-app-mesh-controller-for-k8s)
|
||||
* [Athenz](https://github.com/yahoo/athenz)
|
||||
* [Cert-Manager](https://github.com/cert-manager/csi-driver-spiffe)
|
||||
* [Consul](https://github.com/hashicorp/consul)
|
||||
* [Dapr](https://github.com/dapr)
|
||||
* [Docker](https://github.com/containerd/containerd)
|
||||
* [Emissary](https://github.com/github/emissary)
|
||||
* [Envoy](https://github.com/envoyproxy/envoy)
|
||||
* [Ghostunnel](https://github.com/square/ghostunnel)
|
||||
* [Cert-Manager](https://github.com/cert-manager/csi-driver-spiffe)
|
||||
* [Consul](https://github.com/hashicorp/consul)
|
||||
* [Dapr](https://github.com/dapr)
|
||||
* [Docker](https://github.com/containerd/containerd)
|
||||
* [Emissary](https://github.com/github/emissary)
|
||||
* [Envoy](https://github.com/envoyproxy/envoy)
|
||||
* [Ghostunnel](https://github.com/square/ghostunnel)
|
||||
* [gRPC](https://pkg.go.dev/github.com/spiffe/go-spiffe/v2/examples/spiffe-grpc)
|
||||
* [Hamlet](https://github.com/vmware/hamlet)
|
||||
* [Istio](https://github.com/istio/istio)
|
||||
* [Knox](https://github.com/pinterest/knox)
|
||||
* [Kubernetes](https://github.com/kubernetes/kubernetes)
|
||||
* [Linkerd](https://github.com/linkerd/linkerd2)
|
||||
* [NGINX](http://hg.nginx.org/nginx/)
|
||||
* [Parsec](https://github.com/parallaxsecond/parsec)
|
||||
* [Sigstore](https://github.com/sigstore/fulcio)
|
||||
* [Tekton](https://github.com/tektoncd/chains)
|
||||
* [Tornjak](https://github.com/spiffe/tornjak)
|
||||
* [Hamlet](https://github.com/vmware/hamlet)
|
||||
* [Istio](https://github.com/istio/istio)
|
||||
* [Knox](https://github.com/pinterest/knox)
|
||||
* [Kubernetes](https://github.com/kubernetes/kubernetes)
|
||||
* [NGINX](http://hg.nginx.org/nginx/)
|
||||
* [Parsec](https://github.com/parallaxsecond/parsec)
|
||||
* [Sigstore](https://github.com/sigstore/fulcio)
|
||||
* [Tekton](https://github.com/tektoncd/chains)
|
||||
* [Tornjak](https://github.com/spiffe/tornjak)
|
||||
* [Traefik](https://github.com/traefik/traefik)
|
||||
|
||||
## Case Studies/User Stories
|
||||
|
|
477
CHANGELOG.md
477
CHANGELOG.md
|
@ -1,452 +1,5 @@
|
|||
# Changelog
|
||||
|
||||
## [1.12.4] - 2025-07-01
|
||||
|
||||
### Added
|
||||
|
||||
- `k8s_configmap` BundlePublisher plugin (#6105, #6139)
|
||||
- UpstreamAuthority.SubscribeToLocalBundle RPC to stream updates in the local trust bundle (#6090)
|
||||
- Integration tests running on ARM64 platform (#6059)
|
||||
- The OIDC Discovery Provider can now read the trust bundle from a file (#6025)
|
||||
|
||||
### Changed
|
||||
|
||||
- The "Container id not found" log message in the `k8s` WorkloadAttestor has been lowered to Debug level (#6128)
|
||||
- Improvements in lookup performance for entries (#6100, #6034)
|
||||
- Agent no longer pulls the bundle from `trust_bundle_url` if it is not required (#6065)
|
||||
|
||||
### Fixed
|
||||
|
||||
- The `subject_types_supported` value in the discovery document is now properly populated by the OIDC Discovery Provider (#6126)
|
||||
- SPIRE Server gRPC servers are now gracefully stopped (#6076)
|
||||
|
||||
## [1.12.3] - 2025-06-17
|
||||
|
||||
### Security
|
||||
|
||||
- Fixed an issue in spire-agent where the WorkloadAPI.ValidateJWTSVID endpoint did not enforce the presence of the exp (expiration) claim in JWT-SVIDs, as required by the SPIFFE specification.
|
||||
This vulnerability has limited impact: by default, SPIRE does not issue JWT-SVIDs without an expiration claim. Exploitation would require federating with a misconfigured or non-compliant trust domain.
|
||||
Thanks to Edoardo Geraci for reporting this issue.
|
||||
|
||||
## [1.12.2] - 2025-05-19
|
||||
|
||||
### Fixed
|
||||
|
||||
- Regression where PolicyCredentials set by CredentialComposer plugins were not correctly applied to CA certificates. (#6074)
|
||||
|
||||
## [1.12.1] - 2025-05-06
|
||||
|
||||
### Added
|
||||
|
||||
- Support for Unix sockets in trust bundle URLs (#5932)
|
||||
- Documentation improvements and additions (#5989, #6012)
|
||||
|
||||
### Changed
|
||||
|
||||
- `sql_transaction_timeout` replaced by `event_timeout` and value reduced to 15 minutes (#5966)
|
||||
- Experimental events-based cache performance improvements by batch fetching updated entries (#5970)
|
||||
- Improved error messages when retrieving CGroups (#6030).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Corrected invalid `user-agent` value in OIDC Discovery Provider debug logs (#5981).
|
||||
|
||||
## [1.12.0] - 2025-03-21
|
||||
|
||||
### Added
|
||||
|
||||
- Support for any S3 compatible object storage such as MinIO in the `aws_s3` BundlePublisher plugin (#5757)
|
||||
- Support for Rego V1 in the authorization policy engine (#5769)
|
||||
- Support for SAN-based selectors in the `x509pop` NodeAttestor plugin (#5775)
|
||||
|
||||
### Changed
|
||||
|
||||
- Agents now use the SyncAuthorizedEntries API for periodically synchronization of authorized entries by default (#5906)
|
||||
- Timestamps in logs are now formatted to include nanoseconds (#5798)
|
||||
- Improved entry lookup performance in NewJWTSVID and BatchNewX509SVID server RPCs (#5819)
|
||||
- Increased the maximum number of idle database connections to 100 (#5853)
|
||||
- The maximum idle time per database connection is now set to 30 seconds (#5853)
|
||||
- Small documentation improvements (#5873, #5876)
|
||||
- The experimental events-based cache now supports reading events from read-only replicas when data staleness is tolerated, enhancing read performance (#5911)
|
||||
- The `use_legacy_downstream_x509_ca_ttl` server setting is now set to false by default (#5917)
|
||||
|
||||
### Deprecated
|
||||
|
||||
- `use_sync_authorized_entries` experimental agent setting (#5906)
|
||||
- `use_legacy_downstream_x509_ca_ttl` server setting (#5917)
|
||||
|
||||
### Removed
|
||||
|
||||
- The deprecated `k8s_sat` NodeAttestor plugin (#5703)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Issue where agents did not receive entry updates when new entries with the same entry ID were created while `use_sync_authorized_entries` was enabled (#5764)
|
||||
|
||||
## [1.11.3] - 2025-06-17
|
||||
|
||||
### Security
|
||||
|
||||
- Fixed an issue in spire-agent where the WorkloadAPI.ValidateJWTSVID endpoint did not enforce the presence of the exp (expiration) claim in JWT-SVIDs, as required by the SPIFFE specification.
|
||||
This vulnerability has limited impact: by default, SPIRE does not issue JWT-SVIDs without an expiration claim. Exploitation would require federating with a misconfigured or non-compliant trust domain.
|
||||
Thanks to Edoardo Geraci for reporting this issue.
|
||||
|
||||
## [1.11.2] - 2025-02-13
|
||||
|
||||
### Added
|
||||
|
||||
- `gcp_secretmanager` SVIDStore plugin now supports specifying the regions where secrets are created (#5718)
|
||||
- Support for expanding environment variables in the OIDC Discovery Provider configuration (#5689)
|
||||
- Support for optionally enabling `trust_domain` label for all metrics (#5673)
|
||||
- The JWKS URI returned in the discovery document can now be configured in the OIDC Discovery Provider (#5690)
|
||||
- A server path prefix can now be specified in the OIDC Discovery Provider (#5690)
|
||||
|
||||
### Changed
|
||||
|
||||
- Small documentation improvements (#5809, #5720)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Regression in the hydration of the experimental event-based cache that caused a delay in availability (#5842)
|
||||
- Do not log an error when the Envoy SDS v3 API connection has been closed cleanly (#5835)
|
||||
- SVIDStore plugins to properly parse metadata in entry selectors containing ':' characters (#5750)
|
||||
- Compatibility with deployments that use a server port other than 443 when the `jwt_issuer` configuration is set in the OIDC Discovery Provider (#5690)
|
||||
- Domain verification is now properly done when setting the `jwt_issuer` configuration in the OIDC Discovery Provider (#5690)
|
||||
|
||||
### Security
|
||||
|
||||
- Fixed to properly call the CompareObjectHandles function when it's available on Windows systems, as an extra security measure in the peertracker (#5749)
|
||||
|
||||
## [1.11.1] - 2024-12-12
|
||||
|
||||
### Added
|
||||
|
||||
- The Go based text/template engine used in various plugins has been extended to include a set of functions from the SPRIG library (#5593, #5625)
|
||||
- The JWT-SVID cache in the agent is now configurable (#5633)
|
||||
- The JWT issuer is now configurable in the OIDC Discovery Provider (#5657)
|
||||
|
||||
### Changed
|
||||
|
||||
- CA journal now relies on the authority ID instead of the issued time when updating the status of keys (#5622)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Spelling and grammar fixes (#5571)
|
||||
- Handling of IPv6 address consistently for the binding address of the server and health checks (#5623)
|
||||
- Link to Telemetry documentation in the Contributing guide (#5650)
|
||||
- Handling of registration entries with revision number 0 when the agent syncs entries with the server (#5680)
|
||||
|
||||
### Known Issues
|
||||
|
||||
- Setting the new `jwt_issuer` configuration property in oidc-discovery-provider is not compatible with deployments that use a server port other than 443 (#5696)
|
||||
- Domain verification is bypassed when setting the new `jwt_issuer` configuration property in oidc-discovery-provider (#5697)
|
||||
|
||||
## [1.11.0] - 2024-10-24
|
||||
|
||||
### Added
|
||||
|
||||
- Support for forced rotation and revocation (<https://github.com/orgs/spiffe/projects/21>)
|
||||
- New EJBCA UpstreamAuthority plugin for SPIRE Server (#5378)
|
||||
- Support for variables in templates contained in the config file (#5576)
|
||||
- Support for the configuration validation RPC on all built-in plugins (#5303)
|
||||
- Improved logging when built-in plugins panic (#5476)
|
||||
- Improved CPU and memory resource usage for concurrent Kubernetes Workload attestation (#5408)
|
||||
- Documentation additions and improvements (#5589, #5588, #5499, #5433, #5430, #5269)
|
||||
|
||||
### Changed
|
||||
|
||||
- SPIRE Agent LRU identity cache is now unconditionally enabled. The LRU size can be controlled via the `x509_svid_cache_max_size` configuration option. (#5383, #5531)
|
||||
- Entry API RPCs return per-entry InvalidArgument status when creating/updating malformed entries (#5506)
|
||||
- Support for CGroups v2 in K8s and Docker workload attestors is now enabled by default (#5454)
|
||||
|
||||
### Removed
|
||||
|
||||
- Deprecated -ttl flag from the SPIRE Server `entry create` and `entry update` commands (#5483)
|
||||
- Official support for MySQL 5.X. While SPIRE may continue to work with this version, no explicit testing will be performed by the project (#5487)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Missing TrustDomain field passed to x509pop path template (#5577)
|
||||
- Behavior in the experimental events-based cache causing duplicate entries/agents evaluation in the same cycle (#5509)
|
||||
|
||||
## [1.10.4] - 2024-09-12
|
||||
|
||||
### Fixed
|
||||
|
||||
- Add missing commits to spire-plugin-sdk and spire-api-sdk releases (spiffe/spire-api-sdk#66, spiffe/spire-plugin-sdk#39)
|
||||
|
||||
## [1.10.3] - 2024-09-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- Regression in agent health check, requiring the agent to have an SVID on disk to be healthy (#5459)
|
||||
|
||||
## [1.10.2] - 2024-09-03
|
||||
|
||||
### Added
|
||||
|
||||
- `http_challenge` NodeAttestor plugin (#4909)
|
||||
- Experimental support for validating container image signatures through Sigstore selectors in the docker Workload Attestor (#5272)
|
||||
- Metrics for monitoring the event-based cache (#5411)
|
||||
|
||||
### Changed
|
||||
|
||||
- Delegated Identity API to allow subscription by process ID (#5272)
|
||||
- Agent Debug endpoint to count SVIDs by type (#5352)
|
||||
- Agent health check to report an unhealthy status until the Agent SVID is attested (#5298)
|
||||
- Small documentation improvements (#5393)
|
||||
|
||||
### Fixed
|
||||
|
||||
- `aws_iid` NodeAttestor to properly handle multiple network interfaces (#5300)
|
||||
- Server configuration to correctly propagate the `sql_transaction_timeout` setting in the experimental events-based cache (#5345)
|
||||
|
||||
## [1.10.1] - 2024-08-01
|
||||
|
||||
### Added
|
||||
|
||||
- New Grafana dashboard template (#5188)
|
||||
- `aws_rolesanywhere_trustanchor` BundlePublisher plugin (#5048)
|
||||
|
||||
### Changed
|
||||
|
||||
- `spire` UpstreamAuthority to optionally use the Preferred TTL on intermediate authorities (#5264)
|
||||
- Federation endpoint to support custom bundle and certificates for authorization (#5163)
|
||||
- Small documentation improvements (#5235, #5220)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Event-based cache to handle events missed at the cache startup (#5289)
|
||||
- LRU cache to no longer send update notifications to all subscribers (#5281)
|
||||
|
||||
## [1.10.0] - 2024-06-24
|
||||
|
||||
### Added
|
||||
|
||||
- Plugin reconfiguration support using the `plugin_data_file` configurable (#5166)
|
||||
|
||||
### Changed
|
||||
|
||||
- SPIRE Server and OIDC provider images to use non-root users (#4967, #5227)
|
||||
- `k8s_psat` NodeAttestor attestor to no longer fail when a cluster is not configured (#5216)
|
||||
- Agents are required to renew SVIDs through re-attestation when using a supporting Node Attestor (#5204)
|
||||
- Small documentation improvements (#5181, #5189)
|
||||
- Evicted agents that support reattestation can now reattest without being restarted (#4991)
|
||||
|
||||
### Fixed
|
||||
|
||||
- PSAT node attestor to cross-check the audience fields (#5142)
|
||||
- Events-based cache to handle out of order events (#5071)
|
||||
|
||||
### Deprecated
|
||||
|
||||
- `x509_svid_cache_max_size` and `disable_lru_cache` in agent configuration (#5150)
|
||||
|
||||
### Removed
|
||||
|
||||
- The deprecated `disable_reattest_to_renew` agent configurable (#5217)
|
||||
- The deprecated `key_metadata_file` configurable from the `aws_kms`, `azure_key_vault` and `gcp_kms` server KeyManagers (#5207)
|
||||
- The deprecated `use_msi` configurable from the `azure_key_vault` server KeyManager and `azure_msi` NodeAttestor (#5207, #5209)
|
||||
- The deprecated `exclude_sn_from_ca_subject` server configurable (#5203)
|
||||
- Agent no longer cleans up deprecated bundle and SVID files (#5205)
|
||||
- The CA journal file is no longer stored on disk, and existing CA journal files are cleaned up (#5202)
|
||||
|
||||
## [1.9.6] - 2024-05-14
|
||||
|
||||
### Added
|
||||
|
||||
- Opt-in support for CGroups v2 in K8s and Docker workload attestors (#5076)
|
||||
- `gcp_cloudstorage` BundlePublisher plugin (#4961)
|
||||
- The `aws_iid` node attestor can now check if the AWS account ID is part of an AWS Organization (#4838)
|
||||
- More filtering options to count and show entries and agents (#4714)
|
||||
|
||||
### Changed
|
||||
|
||||
- Credential composer to not convert timestamp related claims (i.e., exp and iat) to floating point values (#5115)
|
||||
- FetchJWTBundles now returns an empty collection of keys instead of null (#5031)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Using expired tokens when connecting to database (#5119)
|
||||
- Server no longer tries to create JWT authority when X.509 authority fails (#5064)
|
||||
- Issues in experimental events-based entry cache (#5030, #5037, #5042)
|
||||
|
||||
## [1.9.5] - 2024-05-07
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to Go 1.21.10 to address CVE-2024-24788
|
||||
|
||||
## [1.9.4] - 2023-04-05
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to google.golang.org/grpc v1.62.2 and golang.org/x/net v0.24.0 to address CVE-2023-45288
|
||||
|
||||
## [1.9.3] - 2024-04-03
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to Go 1.21.9 to address CVE-2023-45288
|
||||
- Limit the preallocation of memory when making paginated requests to the ListEntries and ListAgents RPCs
|
||||
|
||||
## [1.9.2] - 2024-03-25
|
||||
|
||||
### Added
|
||||
|
||||
- Support for AWS IAM-based authentication with AWS RDS backed databases (#4828)
|
||||
- Support for adjusting the SPIRE Server log level at runtime (#4880)
|
||||
- New `retry_bootstrap` option to SPIRE Agent to retry failed bootstrapping with SPIRE Server, with a backoff, in lieu of failing the startup process (#4597)
|
||||
- Improved logging (#4902, #4906)
|
||||
- Documentation improvements (#4895, #4951, #4907)
|
||||
|
||||
## [1.9.1] - 2024-03-05
|
||||
|
||||
### Security
|
||||
|
||||
- Update Go to v1.21.8 to patch CVE-2024-24783
|
||||
|
||||
## [1.9.0] - 2024-02-22
|
||||
|
||||
### Added
|
||||
|
||||
- `uniqueid` CredentialComposer plugin that adds the x509UniqueIdentifier attribute to workload X509-SVIDs (#4862)
|
||||
- Agent's Admin API has now a default location defined (#4856)
|
||||
- Partial selectors from workload attestation are now logged when attestation is interrupted (#4846)
|
||||
- X509-SVIDs minted by SPIRE can now include wildcards in the DNS names (#4814)
|
||||
|
||||
### Changed
|
||||
|
||||
- CA journal data is now stored in the datastore, removing the on-disk dependency of the server (#4690)
|
||||
- `aws_kms`, `azure_key_vault`, and `gcp_kms` KeyManager plugins no longer require storing metadata files on disk (#4700)
|
||||
- Bundle endpoint refresh hint now defaults to 5 minutes (#4847, #4888)
|
||||
- Graceful shutdown is now blocked while built-in plugin RPCs drain (#4820)
|
||||
- Entry cache hydration is now done with paginated requests to the datastore (#4721, #4826)
|
||||
- Agents renew SVIDs through re-attestation by default when using a supporting Node Attestor (#4791)
|
||||
- The SPIRE Agent LRU SVID cache is no longer experimental and is enabled by default (#4773)
|
||||
- Small documentation improvements (#4764, #4787)
|
||||
- Read-replicas are no longer used when hydrating the experimental events-based entry cache (#4868)
|
||||
- Workload gRPC connections are now terminated when the peertracker liveness check fails instead of just failing the RPC calls (#4611)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Missing creation of events in the experimental events-based cache entry when an entry was pruned (#4860)
|
||||
- Bug in SPIRE Agent LRU SVID cache that caused health checks to fail (#4852)
|
||||
- Refreshing of selectors of attested agents when using the experimental events-based entry cache (#4803)
|
||||
|
||||
### Deprecated
|
||||
|
||||
- `k8s_sat` NodeAttestor plugin (#4841)
|
||||
|
||||
### Removed
|
||||
|
||||
- X509-SVIDs issued by the server no longer have the x509UniqueIdentifier attribute as part of the subject (#4862)
|
||||
|
||||
## [1.8.11] - 2024-05-07
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to Go 1.21.10 to address CVE-2024-24788
|
||||
|
||||
## [1.8.10] - 2023-04-05
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to google.golang.org/grpc v1.62.2 and golang.org/x/net v0.24.0 to address CVE-2023-45288
|
||||
|
||||
## [1.8.9] - 2024-04-03
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to Go 1.21.9 to address CVE-2023-45288
|
||||
- Limit the preallocation of memory when making paginated requests to the ListEntries and ListAgents RPCs
|
||||
|
||||
## [1.8.8] - 2024-03-05
|
||||
|
||||
### Security
|
||||
|
||||
- Update Go to v1.21.8 to patch CVE-2024-24783
|
||||
|
||||
## [1.8.7] - 2023-12-21
|
||||
|
||||
### Added
|
||||
|
||||
- Agents can now be configured with an availability target, which establishes the minimum amount of time desired to gracefully handle server or agent downtime, influencing how aggressively X509-SVIDs should be rotated (#4599)
|
||||
- SyncAuthorizedEntries RPC, which allows agents to only sync down changes instead of the entire set of entries. Agents can be configured to use this new RPC through the `use_sync_authorized_entries` experimental setting (#4648)
|
||||
- Experimental support for an events based entry cache which reduces overhead on the database (#4379, #4411, #4527, #4451, #4562, #4723, #4731)
|
||||
|
||||
### Changed
|
||||
|
||||
- The maximum number of open database connections in the datastore now defaults to 100 instead of unlimited (#4656)
|
||||
- Agents now shut down when they can't synchronize entries with the server due to an unknown authority error (#4617)
|
||||
|
||||
### Removed
|
||||
|
||||
- Agents no longer maintains agent SVID and bundle information in the legacy paths in the data directory (#4717)
|
||||
|
||||
## [1.8.6] - 2023-12-07
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to Go 1.21.5 to address CVE-2023-39326
|
||||
|
||||
## [1.8.5] - 2023-11-22
|
||||
|
||||
### Added
|
||||
|
||||
- All credential types supported by Azure can now be used in `azure_msi` NodeAttestor plugin and `azure_key_vault` KeyManager plugin (#4568)
|
||||
- `EnableHostnameLabel` field in Server and Agent `telemetry` configuration section that enables addition of a hostname label to metrics (#4584)
|
||||
|
||||
### Changed
|
||||
|
||||
- Agent SDS API now provides a SPIFFEValidationContext as the default CertificateValidationContext when the Envoy version cannot be determined (#4618)
|
||||
- Server CAs now contain a `serialNumber` attribute in the `Subject` DN (#4585)
|
||||
- Improved accuracy of Agent log message for SVID renewal events (#4654)
|
||||
|
||||
### Deprecated
|
||||
|
||||
- `use_msi` configuration fields in `azure_msi` NodeAttestor plugin and `azure_key_vault` KeyManager plugin are deprecated in favor of the chained Azure SDK credential loading strategy (#4568)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Agent SDS API now provides correct CertificateValidationContext when Envoy registered in SPIRE after the first SDS request (#4611)
|
||||
|
||||
## [1.8.4] - 2023-11-07
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to Go 1.21.4 to address CVE-2023-45283, CVE-2023-45284
|
||||
|
||||
## [1.8.3] - 2023-10-25
|
||||
|
||||
### Added
|
||||
|
||||
- SPIRE Agent distributes sync requests to the SPIRE server to mitigate thundering herd situations (#4534)
|
||||
- Allow configuring prefixes for all metrics (#4535)
|
||||
- Documentation improvements (#4579, #4569)
|
||||
|
||||
### Changed
|
||||
|
||||
- SPIRE Agent performs the initial sync more aggressively when tuned with a longer sync interval (#4479)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Release artifacts have the correct version information (#4564)
|
||||
- The SPIRE Agent `insecureBootstrap` and `trustBundleUrl` configurables are now mutually exclusive (#4532)
|
||||
- Bug preventing JWT-SVIDs from being minted when a Credential Composer plugin is configured (#4489)
|
||||
|
||||
## [1.8.2] - 2023-10-12
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to google.golang.org/grpc v1.58.3 and golang.org/x/net v0.17.0 to address CVE-2023-39325, CVE-2023-44487
|
||||
|
||||
## [1.8.1] - 2023-10-10
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to Go 1.21.3 to address CVE-2023-39325, CVE-2023-44487
|
||||
|
||||
## [1.8.0] - 2023-09-20
|
||||
|
||||
### Added
|
||||
|
@ -476,30 +29,6 @@ Thanks to Edoardo Geraci for reporting this issue.
|
|||
- Server no longer cleans up stale data in the database on startup (#4443)
|
||||
- Server no longer deletes entries with invalid SPIFFE IDs on startup (#4449)
|
||||
|
||||
## [1.7.6] - 2023-12-07
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to Go 1.20.12 to address CVE-2023-39326
|
||||
|
||||
## [1.7.5] - 2023-11-07
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to Go 1.20.11 to address CVE-2023-45283, CVE-2023-45284
|
||||
|
||||
## [1.7.4] - 2023-10-12
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to google.golang.org/grpc v1.58.3 and golang.org/x/net v0.17.0 to address CVE-2023-39325, CVE-2023-44487
|
||||
|
||||
## [1.7.3] - 2023-10-10
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to Go 1.20.10 to address CVE-2023-39325, CVE-2023-44487
|
||||
|
||||
## [1.7.2] - 2023-08-16
|
||||
|
||||
### Added
|
||||
|
@ -1216,7 +745,7 @@ Thanks to Edoardo Geraci for reporting this issue.
|
|||
- Regression preventing agent selectors from showing in `spire-server agent show` command (#2133)
|
||||
- Issue in the token authentication method of the Vault Upstream Authority plugin (#2110)
|
||||
- Reporting of errors in server entry cache telemetry (#2091)
|
||||
- Agent logs an error and automatically shuts down when its SVID has expired, and it requires re-attestation (#2065)
|
||||
- Agent logs an error and automatically shuts down when its SVID has expired and it requires re-attestation (#2065)
|
||||
|
||||
## [0.12.1] - 2021-03-04
|
||||
|
||||
|
@ -1302,7 +831,7 @@ Thanks to Edoardo Geraci for reporting this issue.
|
|||
|
||||
- Fixed Kubernetes Workload Registrar issues (#1814, #1818, #1823)
|
||||
- Fixed BatchCreateEntry return value to match docs, returning the contents of an entry if it already exists (#1824)
|
||||
- Fixed issue preventing brand-new deployments from downgrading successfully (#1829)
|
||||
- Fixed issue preventing brand new deployments from downgrading successfully (#1829)
|
||||
- Fixed a regression introduced in 0.11.0 that caused external node attestor plugins that rely on binary data to fail (#1863)
|
||||
|
||||
## [0.11.0] - 2020-08-28
|
||||
|
@ -1406,7 +935,7 @@ Thanks to Edoardo Geraci for reporting this issue.
|
|||
|
||||
## [0.9.0] - 2019-11-14
|
||||
|
||||
- Users can now opt out of workload executable hashing when enabling the workload path as a selector (#1078)
|
||||
- Users can now opt-out of workload executable hashing when enabling the workload path as a selector (#1078)
|
||||
- Added M3 support to telemetry and other telemetry and logging improvements (#1059, #1085, #1086, #1094, #1102, #1122,#1138,#1160,#1186,#1208)
|
||||
- SQL auto-migration can be disabled (#1089)
|
||||
- SQL schema compatibility checks are aligned with upgrade compatibility guarantees (#1089)
|
||||
|
|
14
CODEOWNERS
14
CODEOWNERS
|
@ -1,27 +1,27 @@
|
|||
* @evan2645 @amartinezfayo @sorindumitru @MarcosDY @rturner3
|
||||
* @evan2645 @amartinezfayo @azdagron @MarcosDY @rturner3
|
||||
|
||||
##########################################
|
||||
# Maintainers
|
||||
##########################################
|
||||
|
||||
# Evan Gilman
|
||||
# SPIRL, Inc.
|
||||
# VMware, Inc
|
||||
# @evan2645
|
||||
|
||||
# Agustin Martínez Fayó
|
||||
# Hewlett-Packard Enterprise
|
||||
# @amartinezfayo
|
||||
|
||||
# Sorin Dumitru
|
||||
# Bloomberg L.P.
|
||||
# @sorindumitru
|
||||
# Andrew Harding
|
||||
# VMware, Inc
|
||||
# @azdagron
|
||||
|
||||
# Marcos Yacob
|
||||
# Hewlett-Packard Enterprise
|
||||
# @MarcosDY
|
||||
|
||||
# Ryan Turner
|
||||
# Cielara AI
|
||||
# Uber Technologies, Inc
|
||||
# @rturner3
|
||||
|
||||
##########################################
|
||||
|
@ -29,5 +29,5 @@
|
|||
##########################################
|
||||
|
||||
# Umair Khan
|
||||
# Stacklet, Inc.
|
||||
# Hewlett-Packard Enterprise
|
||||
# @umairmkhan
|
||||
|
|
|
@ -45,7 +45,7 @@ toolchain and other build related files are cached under the `.build` folder
|
|||
|
||||
### Development in Docker
|
||||
|
||||
You can either build SPIRE on your host or in an Ubuntu docker container. In
|
||||
You can either build SPIRE on your host or in a Ubuntu docker container. In
|
||||
both cases you will use the same Makefile commands.
|
||||
|
||||
To build SPIRE within a container, first build the development image:
|
||||
|
@ -105,14 +105,14 @@ Packages should be exported through interfaces. Interaction with packages must b
|
|||
interfaces
|
||||
|
||||
Interfaces should be defined in their own file, named (in lowercase) after the name of the
|
||||
interface. e.g. `foodata.go` implements `type FooData any`
|
||||
interface. eg. `foodata.go` implements `type FooData interface{}`
|
||||
|
||||
### Metrics
|
||||
|
||||
As much as possible, label names should be constants defined in the `telemetry` package. Additionally,
|
||||
specific metrics should be centrally defined in the `telemetry` package or its subpackages. Functions
|
||||
desiring metrics should delegate counter, gauge, timer, etc. creation to such packages.
|
||||
The metrics emitted by SPIRE are listed in the [telemetry document](doc/telemetry/telemetry.md) and should be kept up to date.
|
||||
The metrics emitted by SPIRE are listed in the [telemetry document](doc/telemetry.md) and should be kept up to date.
|
||||
|
||||
In addition, metrics should be unit-tested where reasonable.
|
||||
|
||||
|
@ -233,20 +233,14 @@ implementation can easily serve the needs for an entire suite of tests and
|
|||
the behavior is in a centralized location when it needs to be updated. Fakes
|
||||
are also less inclined to be impacted by changes to usage patterns.
|
||||
|
||||
## Example [direnv][direnv_link] .envrc
|
||||
## Git hooks
|
||||
|
||||
We have committed a basic `.envrc.example`. If you use [direnv][direnv_link],
|
||||
copy it into `.envrc`, edit as desired, and enable it with `direnv allow`. The
|
||||
`.envrc` is `.gitignored`. Be aware that [source_env][source_env] is insecure
|
||||
so keep your customizations in `.envrc`.
|
||||
We have checked in a pre-commit hook which enforces `go fmt` styling. Please install it
|
||||
before sending a pull request. From the project root:
|
||||
|
||||
[direnv_link]: https://direnv.net/
|
||||
[source_env]: https://direnv.net/man/direnv-stdlib.1.html#codesourceenv-ltfileordirpathgtcode
|
||||
|
||||
## Project Tool Versions
|
||||
|
||||
This project uses a `.spire-tool-versions` file to centralize the versions of various tools used for
|
||||
development, linting, and other tasks.
|
||||
```shell
|
||||
$ ln -s .githooks/pre-commit .git/hooks/pre-commit
|
||||
```
|
||||
|
||||
## Reporting security vulnerabilities
|
||||
|
||||
|
|
87
Dockerfile
87
Dockerfile
|
@ -1,8 +1,8 @@
|
|||
# syntax = docker/dockerfile:1.6.0@sha256:ac85f380a63b13dfcefa89046420e1781752bab202122f8f50032edf31be0021
|
||||
# syntax = docker/dockerfile:1.4.2@sha256:443aab4ca21183e069e7d8b2dc68006594f40bddf1b15bbd83f5137bd93e80e2
|
||||
|
||||
# Build stage
|
||||
ARG goversion
|
||||
FROM --platform=${BUILDPLATFORM} golang:${goversion}-alpine3.22 as base
|
||||
FROM --platform=${BUILDPLATFORM} golang:${goversion}-alpine as base
|
||||
WORKDIR /spire
|
||||
RUN apk --no-cache --update add file bash clang lld pkgconfig git make
|
||||
COPY go.* ./
|
||||
|
@ -13,73 +13,76 @@ COPY . .
|
|||
# xx is a helper for cross-compilation
|
||||
# when bumping to a new version analyze the new version for security issues
|
||||
# then use crane to lookup the digest of that version so we are immutable
|
||||
# crane digest tonistiigi/xx:1.3.0
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0@sha256:0c6a569797744e45955f39d4f7538ac344bfb7ebf0a54006a0a4297b153ccf0f AS xx
|
||||
# crane digest tonistiigi/xx:1.1.2
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx@sha256:9dde7edeb9e4a957ce78be9f8c0fbabe0129bf5126933cd3574888f443731cda AS xx
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} base as builder
|
||||
ARG TAG
|
||||
ARG TARGETPLATFORM
|
||||
ARG TARGETARCH
|
||||
COPY --link --from=xx / /
|
||||
|
||||
# For users that wish to run SPIRE containers as a non-root user,
|
||||
# provide a default unprivileged user such that the default paths
|
||||
# that SPIRE will try to read from, write to, and create at runtime
|
||||
# can be given the correct file ownership/permissions at build time.
|
||||
ARG spireuid=1000
|
||||
ARG spiregid=1000
|
||||
|
||||
# Set up directories that SPIRE expects by default
|
||||
# Set up base directories
|
||||
RUN install -d -o root -g root -m 777 /spireroot
|
||||
RUN install -d -o root -g root -m 755 /spireroot/etc/ssl/certs
|
||||
RUN install -d -o root -g root -m 755 /spireroot/run
|
||||
RUN install -d -o root -g root -m 755 /spireroot/var/lib
|
||||
RUN install -d -o root -g root -m 1777 /spireroot/tmp
|
||||
|
||||
# Set up directories used by SPIRE
|
||||
RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireroot/etc/spire
|
||||
RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireroot/run/spire
|
||||
RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireroot/var/lib/spire
|
||||
|
||||
# Set up spire-server directories
|
||||
RUN cp -r /spireroot /spireserverroot
|
||||
RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireserverroot/etc/spire/server
|
||||
RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireserverroot/run/spire/server/private
|
||||
RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireserverroot/var/lib/spire/server
|
||||
|
||||
# Set up spire-agent directories
|
||||
RUN cp -r /spireroot /spireagentroot
|
||||
RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireagentroot/etc/spire/agent
|
||||
RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireagentroot/run/spire/agent/public
|
||||
RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireagentroot/var/lib/spire/agent
|
||||
|
||||
RUN xx-go --wrap
|
||||
RUN set -e ; xx-apk --no-cache --update add build-base musl-dev libseccomp-dev
|
||||
ENV CGO_ENABLED=1
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
if [ "$TARGETARCH" = "arm64" ]; then CC=aarch64-alpine-linux-musl; elif [ "$TARGETARCH" = "s390x" ]; then CC=s390x-alpine-linux-musl; fi && \
|
||||
make build-static git_tag=$TAG git_dirty="" && \
|
||||
for f in $(find bin -executable -type f); do xx-verify --static $f; done
|
||||
make build-static && \
|
||||
for f in $(find bin -executable -type f); do xx-verify $f; done
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} scratch AS spire-base
|
||||
COPY --link --from=builder --chown=root:root --chmod=755 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
WORKDIR /opt/spire
|
||||
|
||||
# Preparation environment for setting up directories
|
||||
FROM alpine as prep-spire-server
|
||||
RUN mkdir -p /spireroot/opt/spire/bin \
|
||||
/spireroot/etc/spire/server \
|
||||
/spireroot/run/spire/server/private \
|
||||
/spireroot/tmp/spire-server/private \
|
||||
/spireroot/var/lib/spire/server
|
||||
|
||||
FROM alpine as prep-spire-agent
|
||||
RUN mkdir -p /spireroot/opt/spire/bin \
|
||||
/spireroot/etc/spire/agent \
|
||||
/spireroot/run/spire/agent/public \
|
||||
/spireroot/tmp/spire-agent/public \
|
||||
/spireroot/var/lib/spire/agent
|
||||
|
||||
# For users that wish to run SPIRE containers with a specific uid and gid, the
|
||||
# spireuid and spiregid arguments are provided. The default paths that SPIRE
|
||||
# will try to read from, write to, and create at runtime are given the
|
||||
# corresponding file ownership/permissions at build time.
|
||||
# A default non-root user is defined for SPIRE Server and the OIDC Discovery
|
||||
# Provider. The SPIRE Agent image runs as root by default to facilitate the
|
||||
# sharing of the agent socket in Kubernetes environments.
|
||||
CMD []
|
||||
COPY --link --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
|
||||
# SPIRE Server
|
||||
FROM spire-base AS spire-server
|
||||
ARG spireuid=1000
|
||||
ARG spiregid=1000
|
||||
USER ${spireuid}:${spiregid}
|
||||
ENTRYPOINT ["/opt/spire/bin/spire-server", "run"]
|
||||
COPY --link --from=prep-spire-server --chown=${spireuid}:${spiregid} --chmod=755 /spireroot /
|
||||
COPY --link --from=builder --chown=${spireuid}:${spiregid} --chmod=755 /spire/bin/static/spire-server /opt/spire/bin/
|
||||
COPY --link --from=builder /spireserverroot /
|
||||
COPY --link --from=builder /spire/bin/static/spire-server bin/
|
||||
|
||||
# SPIRE Agent
|
||||
FROM spire-base AS spire-agent
|
||||
ARG spireuid=0
|
||||
ARG spiregid=0
|
||||
USER ${spireuid}:${spiregid}
|
||||
ENTRYPOINT ["/opt/spire/bin/spire-agent", "run"]
|
||||
COPY --link --from=prep-spire-agent --chown=${spireuid}:${spiregid} --chmod=755 /spireroot /
|
||||
COPY --link --from=builder --chown=${spireuid}:${spiregid} --chmod=755 /spire/bin/static/spire-agent /opt/spire/bin/
|
||||
COPY --link --from=builder /spireagentroot /
|
||||
COPY --link --from=builder /spire/bin/static/spire-agent bin/
|
||||
|
||||
# OIDC Discovery Provider
|
||||
FROM spire-base AS oidc-discovery-provider
|
||||
ARG spireuid=1000
|
||||
ARG spiregid=1000
|
||||
USER ${spireuid}:${spiregid}
|
||||
ENTRYPOINT ["/opt/spire/bin/oidc-discovery-provider"]
|
||||
COPY --link --from=builder --chown=${spireuid}:${spiregid} --chmod=755 /spire/bin/static/oidc-discovery-provider /opt/spire/bin/
|
||||
COPY --link --from=builder /spire/bin/static/oidc-discovery-provider bin/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM ubuntu:24.04
|
||||
FROM ubuntu:xenial
|
||||
WORKDIR /spire
|
||||
RUN apt-get update && apt-get -y install \
|
||||
curl unzip git build-essential ca-certificates libssl-dev
|
||||
|
|
|
@ -31,9 +31,9 @@ This section of the document can and should be updated as the above consideratio
|
|||
|
||||
### Changes in Maintainership
|
||||
|
||||
SPIRE maintainers are appointed according to the [process described in the governance document][2]. Maintainers may voluntarily step down at any time. Unseating a maintainer against their will requires a unanimous vote except the unseated.
|
||||
SPIRE maintainers are appointed according to the [process described in the governance document][2]. Maintainers may voluntarily step down at any time. Unseating a maintainer against their will requires a unanimous vote with the exception of the unseated.
|
||||
|
||||
Unseating a maintainer is an extraordinary circumstance. A process to do so is necessary, but its use is not intended. Careful consideration should be made when voting in a new maintainer, particularly in validating that they pledge to uphold the terms of this document. To ensure that these decisions are not taken lightly, and to maintain long term project stability and foresight, no more than one maintainer can be involuntarily unseated in any given nine-month period.
|
||||
Unseating a maintainer is an extraordinary circumstance. A process to do so is necessary, but its use is not intended. Careful consideration should be made when voting in a new maintainer, particularly in validating that they pledge to uphold the terms of this document. To ensure that these decisions are not taken lightly, and to maintain long term project stability and foresight, no more than one maintainer can be involuntarily unseated in any given nine month period.
|
||||
|
||||
The CNCF MUST be notified of any changes in maintainership via the CNCF Service Desk.
|
||||
|
||||
|
@ -103,7 +103,7 @@ This is a very important aspect of SPIRE maintainership. Adoption and contributi
|
|||
|
||||
## Product Management and Roadmap Curation
|
||||
|
||||
In addition to the maintainer seats, the SPIRE project designates one product manager seat. While maintainers strive to ensure that project development and direction is a function of community needs, and interact with end users and contributors on a daily basis, the product manager works to clarify user needs by gathering additional information and context. This includes, but is not limited to, conducting user research and field-testing to better inform maintainers, and communicating project development information to the community.
|
||||
In addition to the maintainer seats, the SPIRE project designates one product manager seat. While maintainers strive to ensure that project development and direction is a function of community needs, and interact with end users and contributors on a daily basis, the product manager works to clarify user needs by gathering additional information and context. This includes, but is not limited to, conducting user research and field testing to better inform maintainers, and communicating project development information to the community.
|
||||
|
||||
Maintainers are expected to have heavy participation in the community, but it may be impractical to dedicate themselves to gathering and analyzing community feedback and end-user pain points. Based on data collection, the role of the product manager is intended to aid maintainers to validate the desirability, feasibility, and viability of efforts to help drive project direction and priorities in long term planning.
|
||||
|
||||
|
|
36
Makefile
36
Makefile
|
@ -32,7 +32,6 @@ help:
|
|||
@echo " $(cyan)race-test$(reset) - run unit tests with race detection"
|
||||
@echo " $(cyan)integration$(reset) - run integration tests (requires Docker images)"
|
||||
@echo " support 'SUITES' variable for executing specific tests"
|
||||
@echo " and 'IGNORE_SUITES' variable for ignoring tests"
|
||||
@echo " e.g. SUITES='suites/join-token suites/k8s' make integration"
|
||||
@echo " $(cyan)integration-windows$(reset) - run integration tests for windows (requires Docker images)"
|
||||
@echo " support 'SUITES' variable for executing specific tests"
|
||||
|
@ -104,8 +103,6 @@ else
|
|||
$(error unsupported ARCH: $(arch1))
|
||||
endif
|
||||
|
||||
ignore_suites := $(IGNORE_SUITES)
|
||||
|
||||
############################################################################
|
||||
# Docker TLS detection for buildx
|
||||
############################################################################
|
||||
|
@ -139,14 +136,15 @@ endif
|
|||
|
||||
go_path := PATH="$(go_bin_dir):$(PATH)"
|
||||
|
||||
golangci_lint_version := $(shell awk '/golangci-lint/{print $$2}' .spire-tool-versions)
|
||||
golangci_lint_version = v1.54.1
|
||||
golangci_lint_dir = $(build_dir)/golangci_lint/$(golangci_lint_version)
|
||||
golangci_lint_bin = $(golangci_lint_dir)/golangci-lint
|
||||
golangci_lint_cache = $(golangci_lint_dir)/cache
|
||||
|
||||
markdown_lint_version := $(shell awk '/markdown_lint/{print $$2}' .spire-tool-versions)
|
||||
markdown_lint_version = v0.35.0
|
||||
markdown_lint_image = ghcr.io/igorshubovych/markdownlint-cli:$(markdown_lint_version)
|
||||
|
||||
protoc_version := $(shell awk '/protoc/{print $$2}' .spire-tool-versions)
|
||||
protoc_version = 3.20.1
|
||||
ifeq ($(os1),windows)
|
||||
protoc_url = https://github.com/protocolbuffers/protobuf/releases/download/v$(protoc_version)/protoc-$(protoc_version)-win64.zip
|
||||
else ifeq ($(arch2),arm64)
|
||||
|
@ -166,7 +164,7 @@ protoc_gen_go_base_dir := $(build_dir)/protoc-gen-go
|
|||
protoc_gen_go_dir := $(protoc_gen_go_base_dir)/$(protoc_gen_go_version)-go$(go_version)
|
||||
protoc_gen_go_bin := $(protoc_gen_go_dir)/protoc-gen-go
|
||||
|
||||
protoc_gen_go_grpc_version := v1.3.0
|
||||
protoc_gen_go_grpc_version := v1.1.0
|
||||
protoc_gen_go_grpc_base_dir := $(build_dir)/protoc-gen-go-grpc
|
||||
protoc_gen_go_grpc_dir := $(protoc_gen_go_grpc_base_dir)/$(protoc_gen_go_grpc_version)-go$(go_version)
|
||||
protoc_gen_go_grpc_bin := $(protoc_gen_go_grpc_dir)/protoc-gen-go-grpc
|
||||
|
@ -286,6 +284,7 @@ bin/static/%: cmd/% FORCE | go-check
|
|||
$(E)$(go_build_static) $@$(exe) ./$<
|
||||
|
||||
bin/static/%: support/% FORCE | go-check
|
||||
@echo Building $@…
|
||||
$(E)$(go_build_static) $@$(exe) ./$<
|
||||
|
||||
#############################################################################
|
||||
|
@ -312,11 +311,11 @@ integration:
|
|||
ifeq ($(os1), windows)
|
||||
$(error Integration tests are not supported on windows)
|
||||
else
|
||||
$(E)$(go_path) IGNORE_SUITES='$(ignore_suites)' ./test/integration/test.sh $(SUITES)
|
||||
$(E)$(go_path) ./test/integration/test.sh $(SUITES)
|
||||
endif
|
||||
|
||||
integration-windows:
|
||||
$(E)$(go_path) IGNORE_SUITES='$(ignore_suites)' ./test/integration/test-windows.sh $(SUITES)
|
||||
$(E)./test/integration/test-windows.sh $(SUITES)
|
||||
|
||||
#############################################################################
|
||||
# Docker Images
|
||||
|
@ -338,7 +337,6 @@ $1: $3 container-builder
|
|||
$(E)docker buildx build \
|
||||
--platform $(PLATFORMS) \
|
||||
--build-arg goversion=$(go_version) \
|
||||
--build-arg TAG=$(TAG) \
|
||||
--target $2 \
|
||||
-o type=oci,dest=$2-image.tar \
|
||||
-f $3 \
|
||||
|
@ -404,11 +402,8 @@ endif
|
|||
|
||||
lint: lint-code lint-md
|
||||
|
||||
lint-code: | go-check
|
||||
$(E)mkdir -p $(golangci_lint_cache)
|
||||
$(E)$(go_path) GOLANGCI_LINT_CACHE="$(golangci_lint_cache)" \
|
||||
go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(golangci_lint_version) \
|
||||
run --max-issues-per-linter=0 --max-same-issues=0 ./...
|
||||
lint-code: $(golangci_lint_bin)
|
||||
$(E)PATH="$(go_bin_dir):$(PATH)" GOLANGCI_LINT_CACHE="$(golangci_lint_cache)" $(golangci_lint_bin) run ./...
|
||||
|
||||
lint-md:
|
||||
$(E)docker run --rm -v "$(DIR):/workdir" $(markdown_lint_image) "**/*.md"
|
||||
|
@ -512,7 +507,7 @@ endif
|
|||
go-bin-path: go-check
|
||||
@echo "$(go_bin_dir):${PATH}"
|
||||
|
||||
install-toolchain: install-protoc install-protoc-gen-go | go-check
|
||||
install-toolchain: install-protoc install-golangci-lint install-protoc-gen-go install-protoc-gen-doc | go-check
|
||||
|
||||
install-protoc: $(protoc_bin)
|
||||
|
||||
|
@ -522,6 +517,15 @@ $(protoc_bin):
|
|||
$(E)mkdir -p $(protoc_dir)
|
||||
$(E)curl -sSfL $(protoc_url) -o $(build_dir)/tmp.zip; unzip -q -d $(protoc_dir) $(build_dir)/tmp.zip; rm $(build_dir)/tmp.zip
|
||||
|
||||
install-golangci-lint: $(golangci_lint_bin)
|
||||
|
||||
$(golangci_lint_bin): | go-check
|
||||
@echo "Installing golangci-lint $(golangci_lint_version)..."
|
||||
$(E)rm -rf $(dir $(golangci_lint_dir))
|
||||
$(E)mkdir -p $(golangci_lint_dir)
|
||||
$(E)mkdir -p $(golangci_lint_cache)
|
||||
$(E)GOBIN=$(golangci_lint_dir) $(go_path) go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(golangci_lint_version)
|
||||
|
||||
install-protoc-gen-go: $(protoc_gen_go_bin)
|
||||
|
||||
$(protoc_gen_go_bin): | go-check
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
[](https://bestpractices.coreinfrastructure.org/projects/3303)
|
||||
[](https://github.com/spiffe/spire/actions/workflows/pr_build.yaml)
|
||||
[](https://goreportcard.com/report/github.com/spiffe/spire)
|
||||
[](https://slack.spiffe.io)
|
||||
[](https://github.com/spiffe/spiffe/blob/main/MATURITY.md#production)
|
||||
|
||||
SPIRE (the [SPIFFE](https://github.com/spiffe/spiffe) Runtime Environment) is a toolchain of APIs for establishing trust between software systems across a wide variety of hosting platforms. SPIRE exposes the [SPIFFE Workload API](https://github.com/spiffe/go-spiffe/blob/main/v2/proto/spiffe/workload/workload.proto), which can attest running software systems and issue [SPIFFE IDs](https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE-ID.md) and [SVID](https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE-ID.md)s to them. This in turn allows two workloads to establish trust between each other, for example by establishing an mTLS connection or by signing and verifying a JWT token. SPIRE can also enable workloads to securely authenticate to a secret store, a database, or a cloud provider service.
|
||||
|
@ -61,8 +62,8 @@ The SPIFFE community maintains the SPIRE project. Information on the various SIG
|
|||
A third party security firm ([Cure53](https://cure53.de/)) completed a security audit of SPIFFE and SPIRE in February of 2021. Additionally, the [CNCF Technical Advisory Group for Security](https://github.com/cncf/tag-security) conducted two assessments on SPIFFE and SPIRE in 2018 and 2020. Please find the reports and supporting material, including the threat model exercise results, below.
|
||||
|
||||
- [Cure53 Security Audit Report](doc/cure53-report.pdf)
|
||||
- [SIG-Security SPIFFE/SPIRE Security Assessment: summary](https://github.com/cncf/sig-security/tree/main/community/assessments/projects/spiffe-spire)
|
||||
- [SIG-Security SPIFFE/SPIRE Security Assessment: full assessment](https://github.com/cncf/sig-security/blob/main/community/assessments/projects/spiffe-spire/self-assessment.md)
|
||||
- [SIG-Security SPIFFE/SPIRE Security Assessment: summary](https://github.com/cncf/sig-security/tree/main/assessments/projects/spiffe-spire)
|
||||
- [SIG-Security SPIFFE/SPIRE Security Assessment: full assessment](https://github.com/cncf/sig-security/blob/main/assessments/projects/spiffe-spire/self-assessment.md)
|
||||
- [Scrutinizing SPIRE to Sensibly Strengthen SPIFFE Security](https://blog.spiffe.io/scrutinizing-spire-security-9c82ba542019)
|
||||
|
||||
### Reporting Security Vulnerabilities
|
||||
|
|
30
RELEASING.md
30
RELEASING.md
|
@ -1,6 +1,6 @@
|
|||
# Release and Branch Management
|
||||
|
||||
The SPIRE project maintains active support for both the current and the previous minor versions. All active development occurs in the `main` branch. Version branches are used for patch releases of the previous minor version when necessary.
|
||||
The SPIRE project maintains active support for both the current and the previous major versions. All active development occurs in the `main` branch. Version branches are used for minor releases of the previous major version when necessary.
|
||||
|
||||
## Version Branches
|
||||
|
||||
|
@ -14,7 +14,7 @@ The base commit of the release branch is based on the type of release being gene
|
|||
|
||||
When a bug is discovered in the latest release that also affects releases of the prior minor version, it is necessary to backport the fix.
|
||||
|
||||
Once the version branch is created, the patch is either cherry-picked or backported into a PR against the version branch. The version branch is maintained via the same process as the main branch, including PR approval process etc.
|
||||
Once the version branch is created, the patch is either cherry picked or backported into a PR against the version branch. The version branch is maintained via the same process as the main branch, including PR approval process etc.
|
||||
|
||||
Ensure that the CHANGELOG is updated in both `main` and the version branch to reflect the new release.
|
||||
|
||||
|
@ -59,7 +59,7 @@ The following steps must be completed by the primary on-call maintainer to perfo
|
|||
* If the build fails, or anything unusual is encountered, abort the release.
|
||||
* Ensure that the GitHub release, container images, and release artifacts are deleted/rolled back if necessary.
|
||||
* Visit the releases page on GitHub, copy the release notes, click edit and paste them back in. This works around a GitHub Markdown rendering bug that you will notice before completing this task.
|
||||
* Cut new SDK releases (see [SDK Releases](#sdk-releases)).
|
||||
* Create Git tags (not annotated) with the name `vX.Y.Z` in the [spire-api-sdk](https://github.com/spiffe/spire-api-sdk) and [spire-plugin-sdk](https://github.com/spiffe/spire-plugin-sdk) repositories for the HEAD commit of the main branch.
|
||||
* Open a PR targeted for the main branch with the following changes:
|
||||
* Cherry-pick of the changelog commit from the latest release so that the changelog on the main branch contains all the release notes.
|
||||
* Bump the SPIRE version to the next projected version. As for determining the next projected version, the project generally releases three patch releases per minor release cycle (e.g. `vX.Y.[0-3]`), not including dedicated security releases. The version needs to be updated in the following places:
|
||||
|
@ -75,27 +75,3 @@ The following steps must be completed by the primary on-call maintainer to perfo
|
|||
|
||||
* PRs to update spiffe.io and spire-examples repo to the latest major version must be merged.
|
||||
* Ensure that the PRs have been updated to use the version tag instead of the commit sha.
|
||||
|
||||
### SDK Releases
|
||||
|
||||
SPIRE has two SDK repositories:
|
||||
|
||||
* [API SDK](https://github.com/spiffe/spire-api-sdk)
|
||||
* [Plugin SDK](https://github.com/spiffe/spire-plugin-sdk)
|
||||
|
||||
SPIRE consumes these SDKs using pseudo-versions from the `next` branch in each SDK repository. This allows unreleased changes to be reviewed, merged, and consumed by SPIRE.
|
||||
|
||||
These SDKs need to be released with each SPIRE release.
|
||||
|
||||
SDK releases take place using tagged commits from the `main` branch in each repository. When cutting a new release, the `main` branch needs to be prepared with any previously unreleased changes that are part of the new release.
|
||||
|
||||
To create a release for an SDK, perform the following steps:
|
||||
|
||||
1. Review the diff between `next` and `main`.
|
||||
1. Determine the commits in `next` that are missing from `main`, in other words, commits containing features that were under development that are now publicly available through the new SPIRE release (e.g. API or plugin interface additions).
|
||||
1. Cherry-pick those commits, if any, into `main`.
|
||||
1. Create a git tag (not annotated) with the name `vX.Y.Z`, corresponding to the SPIRE release version, for the `HEAD` commit of the main branch.
|
||||
1. Push the `vX.Y.Z` tag to Github.
|
||||
|
||||
> [!WARNING]
|
||||
> Extra care should be taken to ensure that the tagged commit is correct before pushing. Once it has been pushed, anyone running `go get <SDK module>@latest` will cause the repository to be pulled into the Go module cache at that cache. Changing it afterwards is not without consequence.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package api
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ import (
|
|||
"github.com/mitchellh/cli"
|
||||
"github.com/spiffe/go-spiffe/v2/proto/spiffe/workload"
|
||||
"github.com/spiffe/go-spiffe/v2/spiffeid"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/common"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/x509util"
|
||||
"github.com/spiffe/spire/test/clitest"
|
||||
"github.com/spiffe/spire/test/fakes/fakeworkloadapi"
|
||||
"github.com/spiffe/spire/test/spiretest"
|
||||
"github.com/spiffe/spire/test/testca"
|
||||
|
@ -416,10 +416,9 @@ func TestValidateJWTCommand(t *testing.T) {
|
|||
Claims: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"aud": {
|
||||
Kind: &structpb.Value_ListValue{
|
||||
ListValue: &structpb.ListValue{
|
||||
Values: []*structpb.Value{{Kind: &structpb.Value_StringValue{StringValue: "foo"}}},
|
||||
},
|
||||
Kind: &structpb.Value_ListValue{ListValue: &structpb.ListValue{
|
||||
Values: []*structpb.Value{{Kind: &structpb.Value_StringValue{StringValue: "foo"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -505,7 +504,7 @@ func setupTest(t *testing.T, newCmd func(env *commoncli.Env, clientMaker workloa
|
|||
}, newWorkloadClient)
|
||||
|
||||
test := &apiTest{
|
||||
addr: clitest.GetAddr(addr),
|
||||
addr: common.GetAddr(addr),
|
||||
stdin: stdin,
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
|
@ -539,7 +538,7 @@ func (s *apiTest) afterTest(t *testing.T) {
|
|||
}
|
||||
|
||||
func (s *apiTest) args(extra ...string) []string {
|
||||
return append([]string{clitest.AddrArg, s.addr}, extra...)
|
||||
return append([]string{common.AddrArg, s.addr}, extra...)
|
||||
}
|
||||
|
||||
func assertOutputBasedOnFormat(t *testing.T, format, stdoutString, expectedStdoutJSON string, expectedStdoutPretty ...string) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package api
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ func newWorkloadClient(ctx context.Context, addr net.Addr, timeout time.Duration
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn, err := util.NewGRPCClient(target)
|
||||
conn, err := util.GRPCDialContext(ctx, target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ func (c *fetchJWTCommand) fetchJWTBundles(ctx context.Context, client *workloadC
|
|||
return stream.Recv()
|
||||
}
|
||||
|
||||
func printPrettyResult(env *commoncli.Env, results ...any) error {
|
||||
func printPrettyResult(env *commoncli.Env, results ...interface{}) error {
|
||||
svidResp, ok := results[0].(*workload.JWTSVIDResponse)
|
||||
if !ok {
|
||||
env.Println(cliprinter.ErrInternalCustomPrettyFunc.Error())
|
||||
|
|
|
@ -151,7 +151,7 @@ func (c *fetchX509Command) writeFile(filename string, data []byte) error {
|
|||
return diskutil.WritePubliclyReadableFile(filename, data)
|
||||
}
|
||||
|
||||
func (c *fetchX509Command) prettyPrintFetchX509(env *commoncli.Env, results ...any) error {
|
||||
func (c *fetchX509Command) prettyPrintFetchX509(env *commoncli.Env, results ...interface{}) error {
|
||||
resp, ok := results[0].(*workload.X509SVIDResponse)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
|
|
@ -76,7 +76,7 @@ func (c *validateJWTCommand) validateJWTSVID(ctx context.Context, client *worklo
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
func prettyPrintValidate(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintValidate(env *commoncli.Env, results ...interface{}) error {
|
||||
resp, ok := results[0].(*workload.ValidateJWTSVIDResponse)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package common
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package common
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package common
|
||||
|
||||
const (
|
||||
// DefaultSocketPath is the SPIRE agent's default socket path
|
||||
DefaultSocketPath = "/tmp/spire-agent/public/api.sock"
|
||||
// DefaultAdminSocketPath is the SPIRE agent's default admin socket path
|
||||
DefaultAdminSocketPath = "/tmp/spire-agent/private/admin.sock"
|
||||
)
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package common
|
||||
|
||||
const (
|
||||
// DefaultNamedPipeName is the SPIRE agent's default named pipe name
|
||||
DefaultNamedPipeName = "\\spire-agent\\public\\api"
|
||||
// DefaultAdminNamedPipeName is the SPIRE agent's default admin named pipe name
|
||||
DefaultAdminNamedPipeName = "\\spire-agent\\private\\admin"
|
||||
)
|
||||
|
|
|
@ -79,7 +79,7 @@ func (c *healthCheckCommand) run() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conn, err := util.NewGRPCClient(target)
|
||||
conn, err := util.GRPCDialContext(context.Background(), target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package healthcheck
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package healthcheck
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package healthcheck
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package healthcheck
|
||||
|
||||
|
|
|
@ -2,11 +2,13 @@ package run
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
@ -24,18 +26,18 @@ import (
|
|||
"github.com/imdario/mergo"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spiffe/go-spiffe/v2/spiffeid"
|
||||
"github.com/spiffe/spire/pkg/agent"
|
||||
"github.com/spiffe/spire/pkg/agent/trustbundlesources"
|
||||
"github.com/spiffe/spire/pkg/agent/workloadkey"
|
||||
"github.com/spiffe/spire/pkg/common/bundleutil"
|
||||
"github.com/spiffe/spire/pkg/common/catalog"
|
||||
common_cli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/config"
|
||||
"github.com/spiffe/spire/pkg/common/fflag"
|
||||
"github.com/spiffe/spire/pkg/common/health"
|
||||
"github.com/spiffe/spire/pkg/common/idutil"
|
||||
"github.com/spiffe/spire/pkg/common/log"
|
||||
"github.com/spiffe/spire/pkg/common/pemutil"
|
||||
"github.com/spiffe/spire/pkg/common/telemetry"
|
||||
"github.com/spiffe/spire/pkg/common/tlspolicy"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -51,7 +53,8 @@ const (
|
|||
defaultDefaultAllBundlesName = "ALL"
|
||||
defaultDisableSPIFFECertValidation = false
|
||||
|
||||
minimumAvailabilityTarget = 24 * time.Hour
|
||||
bundleFormatPEM = "pem"
|
||||
bundleFormatSPIFFE = "spiffe"
|
||||
)
|
||||
|
||||
// Config contains all available configurables, arranged by section
|
||||
|
@ -67,7 +70,6 @@ type agentConfig struct {
|
|||
DataDir string `hcl:"data_dir"`
|
||||
AdminSocketPath string `hcl:"admin_socket_path"`
|
||||
InsecureBootstrap bool `hcl:"insecure_bootstrap"`
|
||||
RetryBootstrap *bool `hcl:"retry_bootstrap"`
|
||||
JoinToken string `hcl:"join_token"`
|
||||
LogFile string `hcl:"log_file"`
|
||||
LogFormat string `hcl:"log_format"`
|
||||
|
@ -80,14 +82,10 @@ type agentConfig struct {
|
|||
WorkloadX509SVIDKeyType string `hcl:"workload_x509_svid_key_type"`
|
||||
TrustBundleFormat string `hcl:"trust_bundle_format"`
|
||||
TrustBundlePath string `hcl:"trust_bundle_path"`
|
||||
TrustBundleUnixSocket string `hcl:"trust_bundle_unix_socket"`
|
||||
TrustBundleURL string `hcl:"trust_bundle_url"`
|
||||
TrustDomain string `hcl:"trust_domain"`
|
||||
AllowUnauthenticatedVerifiers bool `hcl:"allow_unauthenticated_verifiers"`
|
||||
AllowedForeignJWTClaims []string `hcl:"allowed_foreign_jwt_claims"`
|
||||
AvailabilityTarget string `hcl:"availability_target"`
|
||||
X509SVIDCacheMaxSize int `hcl:"x509_svid_cache_max_size"`
|
||||
JWTSVIDCacheMaxSize int `hcl:"jwt_svid_cache_max_size"`
|
||||
|
||||
AuthorizedDelegates []string `hcl:"authorized_delegates"`
|
||||
|
||||
|
@ -112,13 +110,14 @@ type sdsConfig struct {
|
|||
}
|
||||
|
||||
type experimentalConfig struct {
|
||||
SyncInterval string `hcl:"sync_interval"`
|
||||
NamedPipeName string `hcl:"named_pipe_name"`
|
||||
AdminNamedPipeName string `hcl:"admin_named_pipe_name"`
|
||||
UseSyncAuthorizedEntries *bool `hcl:"use_sync_authorized_entries"`
|
||||
RequirePQKEM bool `hcl:"require_pq_kem"`
|
||||
SyncInterval string `hcl:"sync_interval"`
|
||||
NamedPipeName string `hcl:"named_pipe_name"`
|
||||
AdminNamedPipeName string `hcl:"admin_named_pipe_name"`
|
||||
|
||||
Flags fflag.RawConfig `hcl:"feature_flags"`
|
||||
|
||||
UnusedKeyPositions map[string][]token.Pos `hcl:",unusedKeyPositions"`
|
||||
X509SVIDCacheMaxSize int `hcl:"x509_svid_cache_max_size"`
|
||||
}
|
||||
|
||||
type Command struct {
|
||||
|
@ -234,21 +233,11 @@ func (c *agentConfig) validate() error {
|
|||
return errors.New("trust_domain must be configured")
|
||||
}
|
||||
|
||||
// If insecure_bootstrap is set, trust_bundle_path or trust_bundle_url cannot be set
|
||||
// If trust_bundle_url is set, download the trust bundle using HTTP and parse it from memory
|
||||
// If trust_bundle_path is set, parse the trust bundle file on disk
|
||||
// Both cannot be set
|
||||
// The trust bundle URL must start with HTTPS
|
||||
if c.InsecureBootstrap {
|
||||
switch {
|
||||
case c.TrustBundleURL != "" && c.TrustBundlePath != "":
|
||||
return errors.New("only one of insecure_bootstrap, trust_bundle_url, or trust_bundle_path can be specified, not the three options")
|
||||
case c.TrustBundleURL != "":
|
||||
return errors.New("only one of insecure_bootstrap or trust_bundle_url can be specified, not both")
|
||||
case c.TrustBundlePath != "":
|
||||
return errors.New("only one of insecure_bootstrap or trust_bundle_path can be specified, not both")
|
||||
}
|
||||
} else if c.TrustBundlePath == "" && c.TrustBundleURL == "" {
|
||||
if c.TrustBundlePath == "" && c.TrustBundleURL == "" && !c.InsecureBootstrap {
|
||||
return errors.New("trust_bundle_path or trust_bundle_url must be configured unless insecure_bootstrap is set")
|
||||
}
|
||||
|
||||
|
@ -256,32 +245,16 @@ func (c *agentConfig) validate() error {
|
|||
return errors.New("only one of trust_bundle_url or trust_bundle_path can be specified, not both")
|
||||
}
|
||||
|
||||
if c.TrustBundleFormat != trustbundlesources.BundleFormatPEM && c.TrustBundleFormat != trustbundlesources.BundleFormatSPIFFE {
|
||||
return fmt.Errorf("invalid value for trust_bundle_format, expected %q or %q", trustbundlesources.BundleFormatPEM, trustbundlesources.BundleFormatSPIFFE)
|
||||
if c.TrustBundleFormat != bundleFormatPEM && c.TrustBundleFormat != bundleFormatSPIFFE {
|
||||
return fmt.Errorf("invalid value for trust_bundle_format, expected %q or %q", bundleFormatPEM, bundleFormatSPIFFE)
|
||||
}
|
||||
|
||||
if c.TrustBundleUnixSocket != "" && c.TrustBundleURL == "" {
|
||||
return errors.New("if trust_bundle_unix_socket is specified, so must be trust_bundle_url")
|
||||
}
|
||||
if c.TrustBundleURL != "" {
|
||||
u, err := url.Parse(c.TrustBundleURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse trust bundle URL: %w", err)
|
||||
}
|
||||
if c.TrustBundleUnixSocket != "" {
|
||||
if u.Scheme != "http" {
|
||||
return errors.New("trust bundle URL must start with http:// when used with trust bundle unix socket")
|
||||
}
|
||||
params := u.Query()
|
||||
for key := range params {
|
||||
if strings.HasPrefix(key, "spiffe-") {
|
||||
return errors.New("trust_bundle_url query params can not start with spiffe-")
|
||||
}
|
||||
if strings.HasPrefix(key, "spire-") {
|
||||
return errors.New("trust_bundle_url query params can not start with spire-")
|
||||
}
|
||||
}
|
||||
} else if u.Scheme != "https" {
|
||||
if u.Scheme != "https" {
|
||||
return errors.New("trust bundle URL must start with https://")
|
||||
}
|
||||
}
|
||||
|
@ -315,7 +288,7 @@ func ParseFile(path string, expandEnv bool) (*Config, error) {
|
|||
|
||||
// If envTemplate flag is passed, substitute $VARIABLES in configuration file
|
||||
if expandEnv {
|
||||
data = config.ExpandEnv(data)
|
||||
data = os.ExpandEnv(data)
|
||||
}
|
||||
|
||||
if err := hcl.Decode(&c, data); err != nil {
|
||||
|
@ -329,7 +302,6 @@ func parseFlags(name string, args []string, output io.Writer) (*agentConfig, err
|
|||
flags := flag.NewFlagSet(name, flag.ContinueOnError)
|
||||
flags.SetOutput(output)
|
||||
c := &agentConfig{}
|
||||
retryBootstrap := false
|
||||
|
||||
flags.StringVar(&c.ConfigPath, "config", defaultConfigPath, "Path to a SPIRE config file")
|
||||
flags.StringVar(&c.DataDir, "dataDir", "", "A directory the agent can use for its runtime data")
|
||||
|
@ -343,10 +315,9 @@ func parseFlags(name string, args []string, output io.Writer) (*agentConfig, err
|
|||
flags.StringVar(&c.TrustDomain, "trustDomain", "", "The trust domain that this agent belongs to")
|
||||
flags.StringVar(&c.TrustBundlePath, "trustBundle", "", "Path to the SPIRE server CA bundle")
|
||||
flags.StringVar(&c.TrustBundleURL, "trustBundleUrl", "", "URL to download the SPIRE server CA bundle")
|
||||
flags.StringVar(&c.TrustBundleFormat, "trustBundleFormat", "", fmt.Sprintf("Format of the bootstrap trust bundle, %q or %q", trustbundlesources.BundleFormatPEM, trustbundlesources.BundleFormatSPIFFE))
|
||||
flags.StringVar(&c.TrustBundleFormat, "trustBundleFormat", "", fmt.Sprintf("Format of the bootstrap trust bundle, %q or %q", bundleFormatPEM, bundleFormatSPIFFE))
|
||||
flags.BoolVar(&c.AllowUnauthenticatedVerifiers, "allowUnauthenticatedVerifiers", false, "If true, the agent permits the retrieval of X509 certificate bundles by unregistered clients")
|
||||
flags.BoolVar(&c.InsecureBootstrap, "insecureBootstrap", false, "If true, the agent bootstraps without verifying the server's identity")
|
||||
flags.BoolVar(&retryBootstrap, "retryBootstrap", true, "If true, the agent retries bootstrap with backoff")
|
||||
flags.BoolVar(&c.ExpandEnv, "expandEnv", false, "Expand environment variables in SPIRE config file")
|
||||
|
||||
c.addOSFlags(flags)
|
||||
|
@ -356,12 +327,6 @@ func parseFlags(name string, args []string, output io.Writer) (*agentConfig, err
|
|||
return nil, err
|
||||
}
|
||||
|
||||
flags.Visit(func(f *flag.Flag) {
|
||||
if f.Name == "retryBootstrap" {
|
||||
c.RetryBootstrap = &retryBootstrap
|
||||
}
|
||||
})
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
@ -387,6 +352,87 @@ func mergeInput(fileInput *Config, cliInput *agentConfig) (*Config, error) {
|
|||
return c, nil
|
||||
}
|
||||
|
||||
func parseTrustBundle(bundleBytes []byte, trustBundleContentType string) ([]*x509.Certificate, error) {
|
||||
switch trustBundleContentType {
|
||||
case bundleFormatPEM:
|
||||
bundle, err := pemutil.ParseCertificates(bundleBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bundle, nil
|
||||
case bundleFormatSPIFFE:
|
||||
bundle, err := bundleutil.Unmarshal(spiffeid.TrustDomain{}, bundleBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse SPIFFE trust bundle: %w", err)
|
||||
}
|
||||
return bundle.X509Authorities(), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown trust bundle format: %s", trustBundleContentType)
|
||||
}
|
||||
|
||||
func downloadTrustBundle(trustBundleURL string) ([]byte, error) {
|
||||
// Download the trust bundle URL from the user specified URL
|
||||
// We use gosec -- the annotation below will disable a security check that URLs are not tainted
|
||||
/* #nosec G107 */
|
||||
resp, err := http.Get(trustBundleURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to fetch trust bundle URL %s: %w", trustBundleURL, err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("error downloading trust bundle: %s", resp.Status)
|
||||
}
|
||||
pemBytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read from trust bundle URL %s: %w", trustBundleURL, err)
|
||||
}
|
||||
|
||||
return pemBytes, nil
|
||||
}
|
||||
|
||||
func setupTrustBundle(ac *agent.Config, c *Config) error {
|
||||
// Either download the trust bundle if TrustBundleURL is set, or read it
|
||||
// from disk if TrustBundlePath is set
|
||||
ac.InsecureBootstrap = c.Agent.InsecureBootstrap
|
||||
|
||||
var bundleBytes []byte
|
||||
var err error
|
||||
|
||||
switch {
|
||||
case c.Agent.TrustBundleURL != "":
|
||||
bundleBytes, err = downloadTrustBundle(c.Agent.TrustBundleURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case c.Agent.TrustBundlePath != "":
|
||||
bundleBytes, err = loadTrustBundle(c.Agent.TrustBundlePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse trust bundle: %w", err)
|
||||
}
|
||||
default:
|
||||
// If InsecureBootstrap is configured, the bundle is not required
|
||||
if ac.InsecureBootstrap {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
bundle, err := parseTrustBundle(bundleBytes, c.Agent.TrustBundleFormat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(bundle) == 0 {
|
||||
return errors.New("no certificates found in trust bundle")
|
||||
}
|
||||
|
||||
ac.TrustBundle = bundle
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool) (*agent.Config, error) {
|
||||
ac := &agent.Config{}
|
||||
|
||||
|
@ -402,6 +448,11 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool)
|
|||
}
|
||||
}
|
||||
|
||||
if c.Agent.Experimental.X509SVIDCacheMaxSize < 0 {
|
||||
return nil, errors.New("x509_svid_cache_max_size should not be negative")
|
||||
}
|
||||
ac.X509SVIDCacheMaxSize = c.Agent.Experimental.X509SVIDCacheMaxSize
|
||||
|
||||
serverHostPort := net.JoinHostPort(c.Agent.ServerAddress, strconv.Itoa(c.Agent.ServerPort))
|
||||
ac.ServerAddress = fmt.Sprintf("dns:///%s", serverHostPort)
|
||||
|
||||
|
@ -414,8 +465,7 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool)
|
|||
}
|
||||
var reopenableFile *log.ReopenableFile
|
||||
if c.Agent.LogFile != "" {
|
||||
var err error
|
||||
reopenableFile, err = log.NewReopenableFile(c.Agent.LogFile)
|
||||
reopenableFile, err := log.NewReopenableFile(c.Agent.LogFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -431,28 +481,6 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool)
|
|||
ac.LogReopener = log.ReopenOnSignal(logger, reopenableFile)
|
||||
}
|
||||
|
||||
ac.RetryBootstrap = true
|
||||
if c.Agent.RetryBootstrap != nil {
|
||||
ac.Log.Warn("The 'retry_bootstrap' configuration is deprecated. It will be removed in SPIRE 1.14. Please test without the flag before upgrading.")
|
||||
ac.RetryBootstrap = *c.Agent.RetryBootstrap
|
||||
}
|
||||
|
||||
ac.UseSyncAuthorizedEntries = true
|
||||
if c.Agent.Experimental.UseSyncAuthorizedEntries != nil {
|
||||
ac.Log.Warn("The 'use_sync_authorized_entries' configuration is deprecated. The option to disable it will be removed in SPIRE 1.13.")
|
||||
ac.UseSyncAuthorizedEntries = *c.Agent.Experimental.UseSyncAuthorizedEntries
|
||||
}
|
||||
|
||||
if c.Agent.X509SVIDCacheMaxSize < 0 {
|
||||
return nil, errors.New("x509_svid_cache_max_size should not be negative")
|
||||
}
|
||||
ac.X509SVIDCacheMaxSize = c.Agent.X509SVIDCacheMaxSize
|
||||
|
||||
if c.Agent.JWTSVIDCacheMaxSize < 0 {
|
||||
return nil, errors.New("jwt_svid_cache_max_size should not be negative")
|
||||
}
|
||||
ac.JWTSVIDCacheMaxSize = c.Agent.JWTSVIDCacheMaxSize
|
||||
|
||||
td, err := common_cli.ParseTrustDomain(c.Agent.TrustDomain, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -482,16 +510,11 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool)
|
|||
}
|
||||
ac.DisableSPIFFECertValidation = c.Agent.SDS.DisableSPIFFECertValidation
|
||||
|
||||
ts := &trustbundlesources.Config{
|
||||
InsecureBootstrap: c.Agent.InsecureBootstrap,
|
||||
TrustBundleFormat: c.Agent.TrustBundleFormat,
|
||||
TrustBundlePath: c.Agent.TrustBundlePath,
|
||||
TrustBundleURL: c.Agent.TrustBundleURL,
|
||||
TrustBundleUnixSocket: c.Agent.TrustBundleUnixSocket,
|
||||
err = setupTrustBundle(ac, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ac.TrustBundleSources = trustbundlesources.New(ts, ac.Log.WithField("Logger", "TrustBundleSources"))
|
||||
|
||||
ac.WorkloadKeyType = workloadkey.ECP256
|
||||
if c.Agent.WorkloadX509SVIDKeyType != "" {
|
||||
ac.WorkloadKeyType, err = workloadkey.KeyTypeFromString(c.Agent.WorkloadX509SVIDKeyType)
|
||||
|
@ -531,23 +554,6 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool)
|
|||
|
||||
ac.AuthorizedDelegates = c.Agent.AuthorizedDelegates
|
||||
|
||||
if c.Agent.AvailabilityTarget != "" {
|
||||
t, err := time.ParseDuration(c.Agent.AvailabilityTarget)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse availability_target: %w", err)
|
||||
}
|
||||
if t < minimumAvailabilityTarget {
|
||||
return nil, fmt.Errorf("availability_target must be at least %s", minimumAvailabilityTarget.String())
|
||||
}
|
||||
ac.AvailabilityTarget = t
|
||||
}
|
||||
|
||||
ac.TLSPolicy = tlspolicy.Policy{
|
||||
RequirePQKEM: c.Agent.Experimental.RequirePQKEM,
|
||||
}
|
||||
|
||||
tlspolicy.LogPolicy(ac.TLSPolicy, log.NewHCLogAdapter(logger, "tlspolicy"))
|
||||
|
||||
if cmp.Diff(experimentalConfig{}, c.Agent.Experimental) != "" {
|
||||
logger.Warn("Experimental features have been enabled. Please see doc/upgrading.md for upgrade and compatibility considerations for experimental features.")
|
||||
}
|
||||
|
@ -636,7 +642,7 @@ func defaultConfig() *Config {
|
|||
DataDir: defaultDataDir,
|
||||
LogLevel: defaultLogLevel,
|
||||
LogFormat: log.DefaultFormat,
|
||||
TrustBundleFormat: trustbundlesources.BundleFormatPEM,
|
||||
TrustBundleFormat: bundleFormatPEM,
|
||||
SDS: sdsConfig{
|
||||
DefaultBundleName: defaultDefaultBundleName,
|
||||
DefaultSVIDName: defaultDefaultSVIDName,
|
||||
|
@ -649,3 +655,12 @@ func defaultConfig() *Config {
|
|||
|
||||
return c
|
||||
}
|
||||
|
||||
func loadTrustBundle(path string) ([]byte, error) {
|
||||
bundleBytes, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bundleBytes, nil
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package run
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package run
|
||||
|
||||
|
@ -6,7 +7,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/spiffe/spire/pkg/agent"
|
||||
|
@ -16,7 +17,6 @@ import (
|
|||
"github.com/spiffe/spire/pkg/common/log"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestCommand_Run(t *testing.T) {
|
||||
|
@ -130,8 +130,8 @@ func TestCommand_Run(t *testing.T) {
|
|||
}
|
||||
if testCase.want.agentUdsDirCreated {
|
||||
assert.DirExistsf(t, testAgentSocketDir, "spire-agent uds dir should be created")
|
||||
currentUmask := unix.Umask(0)
|
||||
assert.Equalf(t, currentUmask, 0o027, "spire-agent process should be created with 0027 umask")
|
||||
currentUmask := syscall.Umask(0)
|
||||
assert.Equalf(t, currentUmask, 0027, "spire-agent process should be created with 0027 umask")
|
||||
} else {
|
||||
assert.NoDirExistsf(t, testAgentSocketDir, "spire-agent uds dir should not be created")
|
||||
}
|
||||
|
@ -187,28 +187,28 @@ func TestParseConfigGood(t *testing.T) {
|
|||
// Check for plugins configurations
|
||||
expectedPluginConfigs := catalog.PluginConfigs{
|
||||
{
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_name_agent",
|
||||
Path: "./pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
DataSource: catalog.FixedData(data),
|
||||
Disabled: false,
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_name_agent",
|
||||
Path: "./pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
Data: data,
|
||||
Disabled: false,
|
||||
},
|
||||
{
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_disabled",
|
||||
Path: "./pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
DataSource: catalog.FixedData(data),
|
||||
Disabled: true,
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_disabled",
|
||||
Path: "./pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
Data: data,
|
||||
Disabled: true,
|
||||
},
|
||||
{
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_enabled",
|
||||
Path: "./pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
DataSource: catalog.FileData("plugin.conf"),
|
||||
Disabled: false,
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_enabled",
|
||||
Path: "./pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
Data: data,
|
||||
Disabled: false,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ func mergeInputCasesOS() []mergeInputCase {
|
|||
},
|
||||
},
|
||||
{
|
||||
msg: "socket_path should be configurable by CLI flag",
|
||||
msg: "socket_path should be configuable by CLI flag",
|
||||
fileInput: func(c *Config) {},
|
||||
cliInput: func(c *agentConfig) {
|
||||
c.SocketPath = "foo"
|
||||
|
@ -272,9 +272,7 @@ func mergeInputCasesOS() []mergeInputCase {
|
|||
}
|
||||
}
|
||||
|
||||
func newAgentConfigCasesOS(t *testing.T) []newAgentConfigCase {
|
||||
testDir := t.TempDir()
|
||||
|
||||
func newAgentConfigCasesOS() []newAgentConfigCase {
|
||||
return []newAgentConfigCase{
|
||||
{
|
||||
msg: "socket_path should be correctly configured",
|
||||
|
@ -362,15 +360,5 @@ func newAgentConfigCasesOS(t *testing.T) []newAgentConfigCase {
|
|||
require.Nil(t, c.AdminBindAddress)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "log_file allows to reopen",
|
||||
input: func(c *Config) {
|
||||
c.Agent.LogFile = path.Join(testDir, "foo")
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.NotNil(t, c.Log)
|
||||
require.NotNil(t, c.LogReopener)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,13 @@ package run
|
|||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/hcl/hcl/ast"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -29,12 +30,124 @@ type mergeInputCase struct {
|
|||
}
|
||||
|
||||
type newAgentConfigCase struct {
|
||||
msg string
|
||||
expectError bool
|
||||
requireErrorPrefix string
|
||||
input func(*Config)
|
||||
logOptions func(t *testing.T) []log.Option
|
||||
test func(*testing.T, *agent.Config)
|
||||
msg string
|
||||
expectError bool
|
||||
input func(*Config)
|
||||
logOptions func(t *testing.T) []log.Option
|
||||
test func(*testing.T, *agent.Config)
|
||||
}
|
||||
|
||||
func TestDownloadTrustBundle(t *testing.T) {
|
||||
testTB, _ := os.ReadFile(path.Join(util.ProjectRoot(), "conf/agent/dummy_root_ca.crt"))
|
||||
testTBSPIFFE := `{
|
||||
"keys": [
|
||||
{
|
||||
"use": "x509-svid",
|
||||
"kty": "EC",
|
||||
"crv": "P-384",
|
||||
"x": "WjB-nSGSxIYiznb84xu5WGDZj80nL7W1c3zf48Why0ma7Y7mCBKzfQkrgDguI4j0",
|
||||
"y": "Z-0_tDH_r8gtOtLLrIpuMwWHoe4vbVBFte1vj6Xt6WeE8lXwcCvLs_mcmvPqVK9j",
|
||||
"x5c": [
|
||||
"MIIBzDCCAVOgAwIBAgIJAJM4DhRH0vmuMAoGCCqGSM49BAMEMB4xCzAJBgNVBAYTAlVTMQ8wDQYDVQQKDAZTUElGRkUwHhcNMTgwNTEzMTkzMzQ3WhcNMjMwNTEyMTkzMzQ3WjAeMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGU1BJRkZFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEWjB+nSGSxIYiznb84xu5WGDZj80nL7W1c3zf48Why0ma7Y7mCBKzfQkrgDguI4j0Z+0/tDH/r8gtOtLLrIpuMwWHoe4vbVBFte1vj6Xt6WeE8lXwcCvLs/mcmvPqVK9jo10wWzAdBgNVHQ4EFgQUh6XzV6LwNazA+GTEVOdu07o5yOgwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwGQYDVR0RBBIwEIYOc3BpZmZlOi8vbG9jYWwwCgYIKoZIzj0EAwQDZwAwZAIwE4Me13qMC9i6Fkx0h26y09QZIbuRqA9puLg9AeeAAyo5tBzRl1YL0KNEp02VKSYJAjBdeJvqjJ9wW55OGj1JQwDFD7kWeEB6oMlwPbI/5hEY3azJi16I0uN1JSYTSWGSqWc="
|
||||
]
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
cases := []struct {
|
||||
msg string
|
||||
status int
|
||||
fileContents string
|
||||
format string
|
||||
expectDownloadError bool
|
||||
expectParseError bool
|
||||
}{
|
||||
{
|
||||
msg: "if URL is not found, should be an error",
|
||||
status: http.StatusNotFound,
|
||||
fileContents: "",
|
||||
format: bundleFormatPEM,
|
||||
expectDownloadError: true,
|
||||
expectParseError: false,
|
||||
},
|
||||
{
|
||||
msg: "if URL returns error 500, should be an error",
|
||||
status: http.StatusInternalServerError,
|
||||
fileContents: "",
|
||||
format: bundleFormatPEM,
|
||||
expectDownloadError: true,
|
||||
expectParseError: false,
|
||||
},
|
||||
{
|
||||
msg: "if file is not parseable, should be an error",
|
||||
status: http.StatusOK,
|
||||
fileContents: "NON PEM PARSEABLE TEXT HERE",
|
||||
format: bundleFormatPEM,
|
||||
expectDownloadError: false,
|
||||
expectParseError: true,
|
||||
},
|
||||
{
|
||||
msg: "if file is empty, should be an error",
|
||||
status: http.StatusOK,
|
||||
fileContents: "",
|
||||
format: bundleFormatPEM,
|
||||
expectDownloadError: false,
|
||||
expectParseError: true,
|
||||
},
|
||||
{
|
||||
msg: "if file is valid, should not be an error",
|
||||
status: http.StatusOK,
|
||||
fileContents: string(testTB),
|
||||
format: bundleFormatPEM,
|
||||
expectDownloadError: false,
|
||||
expectParseError: false,
|
||||
},
|
||||
{
|
||||
msg: "if file is not parseable, format is SPIFFE, should not be an error",
|
||||
status: http.StatusOK,
|
||||
fileContents: "[}",
|
||||
format: bundleFormatSPIFFE,
|
||||
expectDownloadError: false,
|
||||
expectParseError: true,
|
||||
},
|
||||
{
|
||||
msg: "if file is valid, format is SPIFFE, should not be an error",
|
||||
status: http.StatusOK,
|
||||
fileContents: testTBSPIFFE,
|
||||
format: bundleFormatSPIFFE,
|
||||
expectDownloadError: false,
|
||||
expectParseError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range cases {
|
||||
testCase := testCase
|
||||
|
||||
t.Run(testCase.msg, func(t *testing.T) {
|
||||
testServer := httptest.NewServer(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(testCase.status)
|
||||
_, _ = io.WriteString(w, testCase.fileContents)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
}))
|
||||
defer testServer.Close()
|
||||
bundleBytes, err := downloadTrustBundle(testServer.URL)
|
||||
if testCase.expectDownloadError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err := parseTrustBundle(bundleBytes, testCase.format)
|
||||
if testCase.expectParseError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeInput(t *testing.T) {
|
||||
|
@ -500,20 +613,12 @@ func TestMergeInput(t *testing.T) {
|
|||
require.Equal(t, "bar", c.Agent.TrustDomain)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "require_pq_kem should be configurable by file",
|
||||
fileInput: func(c *Config) {
|
||||
c.Agent.Experimental.RequirePQKEM = true
|
||||
},
|
||||
cliInput: func(c *agentConfig) {},
|
||||
test: func(t *testing.T, c *Config) {
|
||||
require.True(t, c.Agent.Experimental.RequirePQKEM)
|
||||
},
|
||||
},
|
||||
}
|
||||
cases = append(cases, mergeInputCasesOS()...)
|
||||
|
||||
for _, testCase := range cases {
|
||||
testCase := testCase
|
||||
|
||||
fileInput := &Config{Agent: &agentConfig{}}
|
||||
cliInput := &agentConfig{}
|
||||
|
||||
|
@ -566,39 +671,16 @@ func TestNewAgentConfig(t *testing.T) {
|
|||
c.Agent.InsecureBootstrap = false
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.False(t, c.TrustBundleSources.GetInsecureBootstrap())
|
||||
require.False(t, c.InsecureBootstrap)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "insecure_bootstrap should be correctly set to true",
|
||||
input: func(c *Config) {
|
||||
// in this case, remove trust_bundle_path provided by defaultValidConfig()
|
||||
// because trust_bundle_path and insecure_bootstrap cannot be set at the same time
|
||||
c.Agent.TrustBundlePath = ""
|
||||
c.Agent.InsecureBootstrap = true
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.True(t, c.TrustBundleSources.GetInsecureBootstrap())
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "retry_bootstrap should be correctly set to false",
|
||||
input: func(c *Config) {
|
||||
rb := false
|
||||
c.Agent.RetryBootstrap = &rb
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.False(t, c.RetryBootstrap)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "retry_bootstrap should be correctly set to true",
|
||||
input: func(c *Config) {
|
||||
rb := true
|
||||
c.Agent.RetryBootstrap = &rb
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.True(t, c.RetryBootstrap)
|
||||
require.True(t, c.InsecureBootstrap)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -648,9 +730,8 @@ func TestNewAgentConfig(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
msg: "trust_bundle_path and trust_bundle_url cannot both be set",
|
||||
expectError: true,
|
||||
requireErrorPrefix: "only one of trust_bundle_url or trust_bundle_path can be specified, not both",
|
||||
msg: "trust_bundle_path and trust_bundle_url cannot both be set",
|
||||
expectError: true,
|
||||
input: func(c *Config) {
|
||||
c.Agent.TrustBundlePath = "foo"
|
||||
c.Agent.TrustBundleURL = "foo2"
|
||||
|
@ -660,111 +741,10 @@ func TestNewAgentConfig(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
msg: "insecure_bootstrap and trust_bundle_path cannot both be set",
|
||||
expectError: true,
|
||||
requireErrorPrefix: "only one of insecure_bootstrap or trust_bundle_path can be specified, not both",
|
||||
msg: "insecure_bootstrap and trust_bundle_url cannot both be set",
|
||||
expectError: true,
|
||||
input: func(c *Config) {
|
||||
c.Agent.TrustBundlePath = "foo"
|
||||
c.Agent.InsecureBootstrap = true
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Nil(t, c)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "insecure_bootstrap and trust_bundle_url cannot both be set",
|
||||
expectError: true,
|
||||
requireErrorPrefix: "only one of insecure_bootstrap or trust_bundle_url can be specified, not both",
|
||||
input: func(c *Config) {
|
||||
// in this case, remove trust_bundle_path provided by defaultValidConfig()
|
||||
c.Agent.TrustBundlePath = ""
|
||||
c.Agent.TrustBundleURL = "foo"
|
||||
c.Agent.InsecureBootstrap = true
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Nil(t, c)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "insecure_bootstrap, trust_bundle_url, trust_bundle_path cannot be set at the same time",
|
||||
expectError: true,
|
||||
requireErrorPrefix: "only one of insecure_bootstrap, trust_bundle_url, or trust_bundle_path can be specified, not the three options",
|
||||
input: func(c *Config) {
|
||||
c.Agent.TrustBundlePath = "bar"
|
||||
c.Agent.TrustBundleURL = "foo"
|
||||
c.Agent.InsecureBootstrap = true
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Nil(t, c)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "trust_bundle_path or trust_bundle_url must be configured unless insecure_bootstrap is set",
|
||||
expectError: true,
|
||||
requireErrorPrefix: "trust_bundle_path or trust_bundle_url must be configured unless insecure_bootstrap is set",
|
||||
input: func(c *Config) {
|
||||
// in this case, remove trust_bundle_path provided by defaultValidConfig()
|
||||
c.Agent.TrustBundlePath = ""
|
||||
c.Agent.TrustBundleURL = ""
|
||||
c.Agent.InsecureBootstrap = false
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Nil(t, c)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "trust_bundle_url must start with https://",
|
||||
expectError: true,
|
||||
requireErrorPrefix: "trust bundle URL must start with https://",
|
||||
input: func(c *Config) {
|
||||
// remove trust_bundle_path provided by defaultValidConfig()
|
||||
c.Agent.TrustBundlePath = ""
|
||||
c.Agent.TrustBundleURL = "foo.bar"
|
||||
c.Agent.InsecureBootstrap = false
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Nil(t, c)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "trust_bundle_url must start with http:// when unix socket",
|
||||
expectError: true,
|
||||
requireErrorPrefix: "trust bundle URL must start with http://",
|
||||
input: func(c *Config) {
|
||||
// remove trust_bundle_path provided by defaultValidConfig()
|
||||
c.Agent.TrustBundlePath = ""
|
||||
c.Agent.TrustBundleURL = "foo.bar"
|
||||
c.Agent.TrustBundleUnixSocket = "foo.bar"
|
||||
c.Agent.InsecureBootstrap = false
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Nil(t, c)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "trust_bundle_url query params can not start with spiffe- when unix socket",
|
||||
expectError: true,
|
||||
requireErrorPrefix: "trust_bundle_url query params can not start with spiffe-",
|
||||
input: func(c *Config) {
|
||||
// remove trust_bundle_path provided by defaultValidConfig()
|
||||
c.Agent.TrustBundlePath = ""
|
||||
c.Agent.TrustBundleURL = "http://localhost/trustbundle?spiffe-test=foo"
|
||||
c.Agent.TrustBundleUnixSocket = "foo.bar"
|
||||
c.Agent.InsecureBootstrap = false
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Nil(t, c)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "trust_bundle_url query params can not start with spire- when unix socket",
|
||||
expectError: true,
|
||||
requireErrorPrefix: "trust_bundle_url query params can not start with spire-",
|
||||
input: func(c *Config) {
|
||||
// remove trust_bundle_path provided by defaultValidConfig()
|
||||
c.Agent.TrustBundlePath = ""
|
||||
c.Agent.TrustBundleURL = "http://localhost/trustbundle?spire-test=foo"
|
||||
c.Agent.TrustBundleUnixSocket = "foo.bar"
|
||||
c.Agent.InsecureBootstrap = false
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
|
@ -840,7 +820,7 @@ func TestNewAgentConfig(t *testing.T) {
|
|||
{
|
||||
msg: "x509_svid_cache_max_size is set",
|
||||
input: func(c *Config) {
|
||||
c.Agent.X509SVIDCacheMaxSize = 100
|
||||
c.Agent.Experimental.X509SVIDCacheMaxSize = 100
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.EqualValues(t, 100, c.X509SVIDCacheMaxSize)
|
||||
|
@ -857,7 +837,7 @@ func TestNewAgentConfig(t *testing.T) {
|
|||
{
|
||||
msg: "x509_svid_cache_max_size is zero",
|
||||
input: func(c *Config) {
|
||||
c.Agent.X509SVIDCacheMaxSize = 0
|
||||
c.Agent.Experimental.X509SVIDCacheMaxSize = 0
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.EqualValues(t, 0, c.X509SVIDCacheMaxSize)
|
||||
|
@ -867,7 +847,7 @@ func TestNewAgentConfig(t *testing.T) {
|
|||
msg: "x509_svid_cache_max_size is negative",
|
||||
expectError: true,
|
||||
input: func(c *Config) {
|
||||
c.Agent.X509SVIDCacheMaxSize = -10
|
||||
c.Agent.Experimental.X509SVIDCacheMaxSize = -10
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Nil(t, c)
|
||||
|
@ -918,7 +898,7 @@ func TestNewAgentConfig(t *testing.T) {
|
|||
t.Cleanup(func() {
|
||||
spiretest.AssertLogsContainEntries(t, hook.AllEntries(), []spiretest.LogEntry{
|
||||
{
|
||||
Data: map[string]any{"trust_domain": strings.Repeat("a", 256)},
|
||||
Data: map[string]interface{}{"trust_domain": strings.Repeat("a", 256)},
|
||||
Level: logrus.WarnLevel,
|
||||
Message: "Configured trust domain name should be less than 255 characters to be " +
|
||||
"SPIFFE compliant; a longer trust domain name may impact interoperability",
|
||||
|
@ -933,45 +913,11 @@ func TestNewAgentConfig(t *testing.T) {
|
|||
assert.NotNil(t, c)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "availability_target parses a duration",
|
||||
input: func(c *Config) {
|
||||
c.Agent.AvailabilityTarget = "24h"
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.EqualValues(t, 24*time.Hour, c.AvailabilityTarget)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "availability_target is too short",
|
||||
expectError: true,
|
||||
input: func(c *Config) {
|
||||
c.Agent.AvailabilityTarget = "1h"
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Nil(t, c)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
msg: "require PQ KEM is disabled (default)",
|
||||
input: func(c *Config) {},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Equal(t, false, c.TLSPolicy.RequirePQKEM)
|
||||
},
|
||||
},
|
||||
{
|
||||
msg: "require PQ KEM is enabled",
|
||||
input: func(c *Config) {
|
||||
c.Agent.Experimental.RequirePQKEM = true
|
||||
},
|
||||
test: func(t *testing.T, c *agent.Config) {
|
||||
require.Equal(t, true, c.TLSPolicy.RequirePQKEM)
|
||||
},
|
||||
},
|
||||
}
|
||||
cases = append(cases, newAgentConfigCasesOS(t)...)
|
||||
cases = append(cases, newAgentConfigCasesOS()...)
|
||||
for _, testCase := range cases {
|
||||
testCase := testCase
|
||||
|
||||
input := defaultValidConfig()
|
||||
|
||||
testCase.input(input)
|
||||
|
@ -985,9 +931,6 @@ func TestNewAgentConfig(t *testing.T) {
|
|||
ac, err := NewAgentConfig(input, logOpts, false)
|
||||
if testCase.expectError {
|
||||
require.Error(t, err)
|
||||
if testCase.requireErrorPrefix != "" {
|
||||
spiretest.RequireErrorPrefix(t, err, testCase.requireErrorPrefix)
|
||||
}
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
@ -1134,6 +1077,8 @@ func TestWarnOnUnknownConfig(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, testCase := range cases {
|
||||
testCase := testCase
|
||||
|
||||
c, err := ParseFile(filepath.Join(testFileDir, testCase.confFile), false)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package run
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package run
|
||||
|
||||
|
@ -173,28 +174,28 @@ func TestParseConfigGood(t *testing.T) {
|
|||
// Check for plugins configurations
|
||||
expectedPluginConfigs := catalog.PluginConfigs{
|
||||
{
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_name_agent",
|
||||
Path: "./pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
DataSource: catalog.FixedData(data),
|
||||
Disabled: false,
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_name_agent",
|
||||
Path: "./pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
Data: data,
|
||||
Disabled: false,
|
||||
},
|
||||
{
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_disabled",
|
||||
Path: ".\\pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
DataSource: catalog.FixedData(data),
|
||||
Disabled: true,
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_disabled",
|
||||
Path: ".\\pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
Data: data,
|
||||
Disabled: true,
|
||||
},
|
||||
{
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_enabled",
|
||||
Path: "c:/temp/pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
DataSource: catalog.FileData("plugin.conf"),
|
||||
Disabled: false,
|
||||
Type: "plugin_type_agent",
|
||||
Name: "plugin_enabled",
|
||||
Path: "c:/temp/pluginAgentCmd",
|
||||
Checksum: "pluginAgentChecksum",
|
||||
Data: data,
|
||||
Disabled: false,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -224,7 +225,7 @@ func mergeInputCasesOS() []mergeInputCase {
|
|||
},
|
||||
},
|
||||
{
|
||||
msg: "named_pipe_name should be configurable by CLI flag",
|
||||
msg: "named_pipe_name should be configuable by CLI flag",
|
||||
fileInput: func(c *Config) {},
|
||||
cliInput: func(c *agentConfig) {
|
||||
c.Experimental.NamedPipeName = "foo"
|
||||
|
@ -258,7 +259,7 @@ func mergeInputCasesOS() []mergeInputCase {
|
|||
}
|
||||
}
|
||||
|
||||
func newAgentConfigCasesOS(*testing.T) []newAgentConfigCase {
|
||||
func newAgentConfigCasesOS() []newAgentConfigCase {
|
||||
return []newAgentConfigCase{
|
||||
{
|
||||
msg: "named_pipe_name should be correctly configured",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package agent_test
|
||||
|
||||
|
@ -14,14 +15,6 @@ var (
|
|||
Path to the SPIRE Server API socket (default "/tmp/spire-server/private/api.sock")
|
||||
`
|
||||
listUsage = `Usage of agent list:
|
||||
-attestationType string
|
||||
Filter by attestation type, like join_token or x509pop.
|
||||
-banned value
|
||||
Filter based on string received, 'true': banned agents, 'false': not banned agents, other value will return all.
|
||||
-canReattest value
|
||||
Filter based on string received, 'true': agents that can reattest, 'false': agents that can't reattest, other value will return all.
|
||||
-expiresBefore string
|
||||
Filter by expiration time (format: "2006-01-02 15:04:05 -0700 -07")
|
||||
-matchSelectorsOn string
|
||||
The match mode used when filtering by selectors. Options: exact, any, superset and subset (default "superset")
|
||||
-output value
|
||||
|
@ -48,20 +41,8 @@ var (
|
|||
The SPIFFE ID of the agent to evict (agent identity)
|
||||
`
|
||||
countUsage = `Usage of agent count:
|
||||
-attestationType string
|
||||
Filter by attestation type, like join_token or x509pop.
|
||||
-banned value
|
||||
Filter based on string received, 'true': banned agents, 'false': not banned agents, other value will return all.
|
||||
-canReattest value
|
||||
Filter based on string received, 'true': agents that can reattest, 'false': agents that can't reattest, other value will return all.
|
||||
-expiresBefore string
|
||||
Filter by expiration time (format: "2006-01-02 15:04:05 -0700 -07")
|
||||
-matchSelectorsOn string
|
||||
The match mode used when filtering by selectors. Options: exact, any, superset and subset (default "superset")
|
||||
-output value
|
||||
Desired output format (pretty, json); default: pretty.
|
||||
-selector value
|
||||
A colon-delimited type:value selector. Can be used more than once
|
||||
-socketPath string
|
||||
Path to the SPIRE Server API socket (default "/tmp/spire-server/private/api.sock")
|
||||
`
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
agentv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/agent/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/agent"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/common"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/test/clitest"
|
||||
"github.com/spiffe/spire/test/spiretest"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
|
@ -92,13 +92,10 @@ func TestBan(t *testing.T) {
|
|||
expectStderr: "Error: a SPIFFE ID is required\n",
|
||||
},
|
||||
{
|
||||
name: "wrong UDS path",
|
||||
args: []string{
|
||||
clitest.AddrArg, clitest.AddrValue,
|
||||
"-spiffeID", "spiffe://example.org/spire/agent/agent1",
|
||||
},
|
||||
name: "wrong UDS path",
|
||||
args: []string{common.AddrArg, common.AddrValue},
|
||||
expectReturnCode: 1,
|
||||
expectStderr: "Error: " + clitest.AddrError,
|
||||
expectStderr: common.AddrError,
|
||||
},
|
||||
{
|
||||
name: "server error",
|
||||
|
@ -155,13 +152,10 @@ func TestEvict(t *testing.T) {
|
|||
expectedStderr: "Error: a SPIFFE ID is required\n",
|
||||
},
|
||||
{
|
||||
name: "wrong UDS path",
|
||||
args: []string{
|
||||
clitest.AddrArg, clitest.AddrValue,
|
||||
"-spiffeID", "spiffe://example.org/spire/agent/agent1",
|
||||
},
|
||||
name: "wrong UDS path",
|
||||
args: []string{common.AddrArg, common.AddrValue},
|
||||
expectedReturnCode: 1,
|
||||
expectedStderr: "Error: " + clitest.AddrError,
|
||||
expectedStderr: common.AddrError,
|
||||
},
|
||||
{
|
||||
name: "server error",
|
||||
|
@ -227,15 +221,9 @@ func TestCount(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "wrong UDS path",
|
||||
args: []string{clitest.AddrArg, clitest.AddrValue},
|
||||
args: []string{common.AddrArg, common.AddrValue},
|
||||
expectedReturnCode: 1,
|
||||
expectedStderr: "Error: " + clitest.AddrError,
|
||||
},
|
||||
{
|
||||
name: "Count by expiresBefore: month out of range",
|
||||
args: []string{"-expiresBefore", "2001-13-05"},
|
||||
expectedReturnCode: 1,
|
||||
expectedStderr: "Error: date is not valid: parsing time \"2001-13-05\": month out of range\n",
|
||||
expectedStderr: common.AddrError,
|
||||
},
|
||||
} {
|
||||
for _, format := range availableFormats {
|
||||
|
@ -401,45 +389,6 @@ func TestList(t *testing.T) {
|
|||
expectedStdoutPretty: "Found 1 attested agent:\n\nSPIFFE ID : spiffe://example.org/spire/agent/agent1",
|
||||
expectedStdoutJSON: `{"agents":[{"id":{"trust_domain":"example.org","path":"/spire/agent/agent1"},"attestation_type":"","x509svid_serial_number":"","x509svid_expires_at":"0","selectors":[],"banned":false,"can_reattest":true}],"next_page_token":""}`,
|
||||
},
|
||||
{
|
||||
name: "by expiresBefore",
|
||||
args: []string{"-expiresBefore", "2000-01-01 15:04:05 -0700 -07"},
|
||||
expectReq: &agentv1.ListAgentsRequest{
|
||||
Filter: &agentv1.ListAgentsRequest_Filter{
|
||||
ByExpiresBefore: "2000-01-01 15:04:05 -0700 -07",
|
||||
},
|
||||
PageSize: 1000,
|
||||
},
|
||||
existentAgents: testAgents,
|
||||
expectedStdoutPretty: "Found 1 attested agent:\n\nSPIFFE ID : spiffe://example.org/spire/agent/agent1",
|
||||
expectedStdoutJSON: `{"agents":[{"id":{"trust_domain":"example.org","path":"/spire/agent/agent1"},"attestation_type":"","x509svid_serial_number":"","x509svid_expires_at":"0","selectors":[],"banned":false,"can_reattest":true}],"next_page_token":""}`,
|
||||
},
|
||||
{
|
||||
name: "by banned",
|
||||
args: []string{"-banned", "true"},
|
||||
expectReq: &agentv1.ListAgentsRequest{
|
||||
Filter: &agentv1.ListAgentsRequest_Filter{
|
||||
ByBanned: wrapperspb.Bool(true),
|
||||
},
|
||||
PageSize: 1000,
|
||||
},
|
||||
existentAgents: testAgentsWithBanned,
|
||||
expectedStdoutPretty: "Found 1 attested agent:\n\nSPIFFE ID : spiffe://example.org/spire/agent/banned",
|
||||
expectedStdoutJSON: `{"agents":[{"id":{"trust_domain":"example.org","path":"/spire/agent/banned"},"attestation_type":"","x509svid_serial_number":"","x509svid_expires_at":"0","selectors":[],"banned":true,"can_reattest":false}],"next_page_token":""}`,
|
||||
},
|
||||
{
|
||||
name: "by canReattest",
|
||||
args: []string{"-canReattest", "true"},
|
||||
expectReq: &agentv1.ListAgentsRequest{
|
||||
Filter: &agentv1.ListAgentsRequest_Filter{
|
||||
ByCanReattest: wrapperspb.Bool(true),
|
||||
},
|
||||
PageSize: 1000,
|
||||
},
|
||||
existentAgents: testAgents,
|
||||
expectedStdoutPretty: "Found 1 attested agent:\n\nSPIFFE ID : spiffe://example.org/spire/agent/agent1",
|
||||
expectedStdoutJSON: `{"agents":[{"id":{"trust_domain":"example.org","path":"/spire/agent/agent1"},"attestation_type":"","x509svid_serial_number":"","x509svid_expires_at":"0","selectors":[],"banned":false,"can_reattest":true}],"next_page_token":""}`,
|
||||
},
|
||||
{
|
||||
name: "List by selectors: Invalid matcher",
|
||||
args: []string{"-selector", "foo:bar", "-selector", "bar:baz", "-matchSelectorsOn", "NO-MATCHER"},
|
||||
|
@ -454,15 +403,9 @@ func TestList(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "wrong UDS path",
|
||||
args: []string{clitest.AddrArg, clitest.AddrValue},
|
||||
args: []string{common.AddrArg, common.AddrValue},
|
||||
expectedReturnCode: 1,
|
||||
expectedStderr: "Error: " + clitest.AddrError,
|
||||
},
|
||||
{
|
||||
name: "List by expiresBefore: month out of range",
|
||||
args: []string{"-expiresBefore", "2001-13-05"},
|
||||
expectedReturnCode: 1,
|
||||
expectedStderr: "Error: date is not valid: parsing time \"2001-13-05\": month out of range\n",
|
||||
expectedStderr: common.AddrError,
|
||||
},
|
||||
} {
|
||||
for _, format := range availableFormats {
|
||||
|
@ -746,13 +689,10 @@ func TestShow(t *testing.T) {
|
|||
expectedStderr: "Error: rpc error: code = Internal desc = internal server error\n",
|
||||
},
|
||||
{
|
||||
name: "wrong UDS path",
|
||||
args: []string{
|
||||
clitest.AddrArg, clitest.AddrValue,
|
||||
"-spiffeID", "spiffe://example.org/spire/agent/agent1",
|
||||
},
|
||||
name: "wrong UDS path",
|
||||
args: []string{common.AddrArg, common.AddrValue},
|
||||
expectedReturnCode: 1,
|
||||
expectedStderr: "Error: " + clitest.AddrError,
|
||||
expectedStderr: common.AddrError,
|
||||
},
|
||||
{
|
||||
name: "show selectors",
|
||||
|
@ -810,7 +750,7 @@ func setupTest(t *testing.T, newClient func(*commoncli.Env) cli.Command) *agentT
|
|||
stdin: stdin,
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
args: []string{clitest.AddrArg, clitest.GetAddr(addr)},
|
||||
args: []string{common.AddrArg, common.GetAddr(addr)},
|
||||
server: server,
|
||||
client: client,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package agent_test
|
||||
|
||||
|
@ -14,14 +15,6 @@ var (
|
|||
Desired output format (pretty, json); default: pretty.
|
||||
`
|
||||
listUsage = `Usage of agent list:
|
||||
-attestationType string
|
||||
Filter by attestation type, like join_token or x509pop.
|
||||
-banned value
|
||||
Filter based on string received, 'true': banned agents, 'false': not banned agents, other value will return all.
|
||||
-canReattest value
|
||||
Filter based on string received, 'true': agents that can reattest, 'false': agents that can't reattest, other value will return all.
|
||||
-expiresBefore string
|
||||
Filter by expiration time (format: "2006-01-02 15:04:05 -0700 -07")
|
||||
-matchSelectorsOn string
|
||||
The match mode used when filtering by selectors. Options: exact, any, superset and subset (default "superset")
|
||||
-namedPipeName string
|
||||
|
@ -48,22 +41,10 @@ var (
|
|||
The SPIFFE ID of the agent to evict (agent identity)
|
||||
`
|
||||
countUsage = `Usage of agent count:
|
||||
-attestationType string
|
||||
Filter by attestation type, like join_token or x509pop.
|
||||
-banned value
|
||||
Filter based on string received, 'true': banned agents, 'false': not banned agents, other value will return all.
|
||||
-canReattest value
|
||||
Filter based on string received, 'true': agents that can reattest, 'false': agents that can't reattest, other value will return all.
|
||||
-expiresBefore string
|
||||
Filter by expiration time (format: "2006-01-02 15:04:05 -0700 -07")
|
||||
-matchSelectorsOn string
|
||||
The match mode used when filtering by selectors. Options: exact, any, superset and subset (default "superset")
|
||||
-namedPipeName string
|
||||
Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api")
|
||||
-output value
|
||||
Desired output format (pretty, json); default: pretty.
|
||||
-selector value
|
||||
A colon-delimited type:value selector. Can be used more than once
|
||||
`
|
||||
showUsage = `Usage of agent show:
|
||||
-namedPipeName string
|
||||
|
|
|
@ -67,7 +67,7 @@ func (c *banCommand) AppendFlags(fs *flag.FlagSet) {
|
|||
cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, prettyPrintBanResult)
|
||||
}
|
||||
|
||||
func prettyPrintBanResult(env *commoncli.Env, _ ...any) error {
|
||||
func prettyPrintBanResult(env *commoncli.Env, _ ...interface{}) error {
|
||||
env.Println("Agent banned successfully")
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,43 +1,20 @@
|
|||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
agentv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/agent/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
"github.com/spiffe/spire/cmd/spire-server/util"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type countCommand struct {
|
||||
// Type and value are delimited by a colon (:)
|
||||
// ex. "unix:uid:1000" or "spiffe_id:spiffe://example.org/foo"
|
||||
selectors commoncli.StringsFlag
|
||||
|
||||
// Match used when filtering by selectors
|
||||
matchSelectorsOn string
|
||||
|
||||
// Filters agents to those that are banned.
|
||||
banned commoncli.BoolFlag
|
||||
|
||||
// Filters agents by those that expire before this value.
|
||||
expiresBefore string
|
||||
|
||||
// Filters agents to those matching the attestation type.
|
||||
attestationType string
|
||||
|
||||
// Filters agents that can re-attest.
|
||||
canReattest commoncli.BoolFlag
|
||||
|
||||
env *commoncli.Env
|
||||
|
||||
env *commoncli.Env
|
||||
printer cliprinter.Printer
|
||||
}
|
||||
|
||||
|
@ -62,61 +39,8 @@ func (*countCommand) Synopsis() string {
|
|||
|
||||
// Run counts attested agents
|
||||
func (c *countCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient util.ServerClient) error {
|
||||
filter := &agentv1.CountAgentsRequest_Filter{}
|
||||
if len(c.selectors) > 0 {
|
||||
matchBehavior, err := parseToSelectorMatch(c.matchSelectorsOn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
selectors := make([]*types.Selector, len(c.selectors))
|
||||
for i, sel := range c.selectors {
|
||||
selector, err := util.ParseSelector(sel)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing selector %q: %w", sel, err)
|
||||
}
|
||||
selectors[i] = selector
|
||||
}
|
||||
filter.BySelectorMatch = &types.SelectorMatch{
|
||||
Selectors: selectors,
|
||||
Match: matchBehavior,
|
||||
}
|
||||
}
|
||||
|
||||
if c.expiresBefore != "" {
|
||||
// Parse the time string into a time.Time object
|
||||
_, err := time.Parse("2006-01-02 15:04:05 -0700 -07", c.expiresBefore)
|
||||
if err != nil {
|
||||
return fmt.Errorf("date is not valid: %w", err)
|
||||
}
|
||||
filter.ByExpiresBefore = c.expiresBefore
|
||||
}
|
||||
|
||||
if c.attestationType != "" {
|
||||
filter.ByAttestationType = c.attestationType
|
||||
}
|
||||
|
||||
// 0: all, 1: can't reattest, 2: can reattest
|
||||
if c.canReattest == 1 {
|
||||
filter.ByCanReattest = wrapperspb.Bool(false)
|
||||
}
|
||||
if c.canReattest == 2 {
|
||||
filter.ByCanReattest = wrapperspb.Bool(true)
|
||||
}
|
||||
|
||||
// 0: all, 1: no-banned, 2: banned
|
||||
if c.banned == 1 {
|
||||
filter.ByBanned = wrapperspb.Bool(false)
|
||||
}
|
||||
if c.banned == 2 {
|
||||
filter.ByBanned = wrapperspb.Bool(true)
|
||||
}
|
||||
|
||||
agentClient := serverClient.NewAgentClient()
|
||||
|
||||
countResponse, err := agentClient.CountAgents(ctx, &agentv1.CountAgentsRequest{
|
||||
Filter: filter,
|
||||
})
|
||||
countResponse, err := agentClient.CountAgents(ctx, &agentv1.CountAgentsRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -125,16 +49,10 @@ func (c *countCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient u
|
|||
}
|
||||
|
||||
func (c *countCommand) AppendFlags(fs *flag.FlagSet) {
|
||||
fs.Var(&c.selectors, "selector", "A colon-delimited type:value selector. Can be used more than once")
|
||||
fs.StringVar(&c.attestationType, "attestationType", "", "Filter by attestation type, like join_token or x509pop.")
|
||||
fs.Var(&c.canReattest, "canReattest", "Filter based on string received, 'true': agents that can reattest, 'false': agents that can't reattest, other value will return all.")
|
||||
fs.Var(&c.banned, "banned", "Filter based on string received, 'true': banned agents, 'false': not banned agents, other value will return all.")
|
||||
fs.StringVar(&c.expiresBefore, "expiresBefore", "", "Filter by expiration time (format: \"2006-01-02 15:04:05 -0700 -07\")")
|
||||
fs.StringVar(&c.matchSelectorsOn, "matchSelectorsOn", "superset", "The match mode used when filtering by selectors. Options: exact, any, superset and subset")
|
||||
cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, prettyPrintCount)
|
||||
}
|
||||
|
||||
func prettyPrintCount(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintCount(env *commoncli.Env, results ...interface{}) error {
|
||||
countResp, ok := results[0].(*agentv1.CountAgentsResponse)
|
||||
if !ok {
|
||||
return errors.New("internal error: cli printer; please report this bug")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
|
||||
|
@ -12,6 +11,7 @@ import (
|
|||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"github.com/spiffe/spire/pkg/server/api"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type evictCommand struct {
|
||||
|
@ -65,7 +65,7 @@ func (c *evictCommand) AppendFlags(fs *flag.FlagSet) {
|
|||
cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, prettyPrintEvictResult)
|
||||
}
|
||||
|
||||
func prettyPrintEvictResult(env *commoncli.Env, _ ...any) error {
|
||||
func prettyPrintEvictResult(env *commoncli.Env, _ ...interface{}) error {
|
||||
env.Println("Agent evicted successfully")
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
@ -14,32 +13,17 @@ import (
|
|||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"github.com/spiffe/spire/pkg/common/idutil"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type listCommand struct {
|
||||
env *commoncli.Env
|
||||
// Type and value are delimited by a colon (:)
|
||||
// ex. "unix:uid:1000" or "spiffe_id:spiffe://example.org/foo"
|
||||
selectors commoncli.StringsFlag
|
||||
|
||||
// Match used when filtering by selectors
|
||||
// Match used when filtering agents by selectors
|
||||
matchSelectorsOn string
|
||||
|
||||
// Filters agents to those that are banned.
|
||||
banned commoncli.BoolFlag
|
||||
|
||||
// Filters agents by those that expire before this value.
|
||||
expiresBefore string
|
||||
|
||||
// Filters agents to those matching the attestation type.
|
||||
attestationType string
|
||||
|
||||
// Filters agents that can re-attest.
|
||||
canReattest commoncli.BoolFlag
|
||||
|
||||
env *commoncli.Env
|
||||
|
||||
printer cliprinter.Printer
|
||||
printer cliprinter.Printer
|
||||
}
|
||||
|
||||
// NewListCommand creates a new "list" subcommand for "agent" command.
|
||||
|
@ -84,35 +68,6 @@ func (c *listCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient ut
|
|||
}
|
||||
}
|
||||
|
||||
if c.expiresBefore != "" {
|
||||
// Parse the time string into a time.Time object
|
||||
_, err := time.Parse("2006-01-02 15:04:05 -0700 -07", c.expiresBefore)
|
||||
if err != nil {
|
||||
return fmt.Errorf("date is not valid: %w", err)
|
||||
}
|
||||
filter.ByExpiresBefore = c.expiresBefore
|
||||
}
|
||||
|
||||
if c.attestationType != "" {
|
||||
filter.ByAttestationType = c.attestationType
|
||||
}
|
||||
|
||||
// 0: all, 1: can't reattest, 2: can reattest
|
||||
if c.canReattest == 1 {
|
||||
filter.ByCanReattest = wrapperspb.Bool(false)
|
||||
}
|
||||
if c.canReattest == 2 {
|
||||
filter.ByCanReattest = wrapperspb.Bool(true)
|
||||
}
|
||||
|
||||
// 0: all, 1: no-banned, 2: banned
|
||||
if c.banned == 1 {
|
||||
filter.ByBanned = wrapperspb.Bool(false)
|
||||
}
|
||||
if c.banned == 2 {
|
||||
filter.ByBanned = wrapperspb.Bool(true)
|
||||
}
|
||||
|
||||
agentClient := serverClient.NewAgentClient()
|
||||
|
||||
pageToken := ""
|
||||
|
@ -136,16 +91,12 @@ func (c *listCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient ut
|
|||
}
|
||||
|
||||
func (c *listCommand) AppendFlags(fs *flag.FlagSet) {
|
||||
fs.Var(&c.selectors, "selector", "A colon-delimited type:value selector. Can be used more than once")
|
||||
fs.StringVar(&c.attestationType, "attestationType", "", "Filter by attestation type, like join_token or x509pop.")
|
||||
fs.Var(&c.canReattest, "canReattest", "Filter based on string received, 'true': agents that can reattest, 'false': agents that can't reattest, other value will return all.")
|
||||
fs.Var(&c.banned, "banned", "Filter based on string received, 'true': banned agents, 'false': not banned agents, other value will return all.")
|
||||
fs.StringVar(&c.expiresBefore, "expiresBefore", "", "Filter by expiration time (format: \"2006-01-02 15:04:05 -0700 -07\")")
|
||||
fs.StringVar(&c.matchSelectorsOn, "matchSelectorsOn", "superset", "The match mode used when filtering by selectors. Options: exact, any, superset and subset")
|
||||
fs.Var(&c.selectors, "selector", "A colon-delimited type:value selector. Can be used more than once")
|
||||
cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, prettyPrintAgents)
|
||||
}
|
||||
|
||||
func prettyPrintAgents(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintAgents(env *commoncli.Env, results ...interface{}) error {
|
||||
listResp, ok := results[0].(*agentv1.ListAgentsResponse)
|
||||
if !ok {
|
||||
return errors.New("internal error: cli printer; please report this bug")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"time"
|
||||
|
@ -14,6 +13,7 @@ import (
|
|||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"github.com/spiffe/spire/pkg/common/idutil"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
|
@ -95,8 +95,8 @@ type expiredAgent struct {
|
|||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (c *purgeCommand) prettyPrintPurgeResult(env *commoncli.Env, results ...any) error {
|
||||
if expAgents, ok := results[0].([]any)[0].(*expiredAgents); ok {
|
||||
func (c *purgeCommand) prettyPrintPurgeResult(env *commoncli.Env, results ...interface{}) error {
|
||||
if expAgents, ok := results[0].([]interface{})[0].(*expiredAgents); ok {
|
||||
if len(expAgents.Agents) == 0 {
|
||||
env.Println("No agents to purge.")
|
||||
return nil
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
|
||||
|
@ -13,11 +12,12 @@ import (
|
|||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"github.com/spiffe/spire/pkg/server/api"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type showCommand struct {
|
||||
env *commoncli.Env
|
||||
// SPIFFE ID of the agent being shown
|
||||
// SPIFFE ID of the agent being showed
|
||||
spiffeID string
|
||||
printer cliprinter.Printer
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ func (c *showCommand) AppendFlags(fs *flag.FlagSet) {
|
|||
cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, prettyPrintAgent)
|
||||
}
|
||||
|
||||
func prettyPrintAgent(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintAgent(env *commoncli.Env, results ...interface{}) error {
|
||||
agent, ok := results[0].(*types.Agent)
|
||||
if !ok {
|
||||
return errors.New("internal error: cli printer; please report this bug")
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
package authoritycommon
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
localauthorityv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/localauthority/v1"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
)
|
||||
|
||||
func PrettyPrintJWTAuthorityState(env *commoncli.Env, authorityState *localauthorityv1.AuthorityState) {
|
||||
prettyPrintAuthorityState(env, authorityState, false)
|
||||
}
|
||||
|
||||
func PrettyPrintX509AuthorityState(env *commoncli.Env, authorityState *localauthorityv1.AuthorityState) {
|
||||
prettyPrintAuthorityState(env, authorityState, true)
|
||||
}
|
||||
|
||||
func prettyPrintAuthorityState(env *commoncli.Env, authorityState *localauthorityv1.AuthorityState, includeUpstreamAuthority bool) {
|
||||
env.Printf(" Authority ID: %s\n", authorityState.AuthorityId)
|
||||
env.Printf(" Expires at: %s\n", time.Unix(authorityState.ExpiresAt, 0).UTC())
|
||||
if !includeUpstreamAuthority {
|
||||
return
|
||||
}
|
||||
|
||||
if authorityState.UpstreamAuthoritySubjectKeyId != "" {
|
||||
env.Printf(" Upstream authority Subject Key ID: %s\n", authorityState.UpstreamAuthoritySubjectKeyId)
|
||||
return
|
||||
}
|
||||
|
||||
env.Println(" Upstream authority ID: No upstream authority")
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
package authoritycommontest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
localauthorityv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/localauthority/v1"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/test/clitest"
|
||||
"github.com/spiffe/spire/test/spiretest"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var AvailableFormats = []string{"pretty", "json"}
|
||||
|
||||
type localAuthorityTest struct {
|
||||
Stdin *bytes.Buffer
|
||||
Stdout *bytes.Buffer
|
||||
Stderr *bytes.Buffer
|
||||
Args []string
|
||||
Server *fakeLocalAuthorityServer
|
||||
Client cli.Command
|
||||
}
|
||||
|
||||
func (s *localAuthorityTest) afterTest(t *testing.T) {
|
||||
t.Logf("TEST:%s", t.Name())
|
||||
t.Logf("STDOUT:\n%s", s.Stdout.String())
|
||||
t.Logf("STDIN:\n%s", s.Stdin.String())
|
||||
t.Logf("STDERR:\n%s", s.Stderr.String())
|
||||
}
|
||||
|
||||
func SetupTest(t *testing.T, newClient func(*commoncli.Env) cli.Command) *localAuthorityTest {
|
||||
server := &fakeLocalAuthorityServer{}
|
||||
|
||||
addr := spiretest.StartGRPCServer(t, func(s *grpc.Server) {
|
||||
localauthorityv1.RegisterLocalAuthorityServer(s, server)
|
||||
})
|
||||
|
||||
stdin := new(bytes.Buffer)
|
||||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
|
||||
client := newClient(&commoncli.Env{
|
||||
Stdin: stdin,
|
||||
Stdout: stdout,
|
||||
Stderr: stderr,
|
||||
})
|
||||
|
||||
test := &localAuthorityTest{
|
||||
Stdin: stdin,
|
||||
Stdout: stdout,
|
||||
Stderr: stderr,
|
||||
Args: []string{clitest.AddrArg, clitest.GetAddr(addr)},
|
||||
Server: server,
|
||||
Client: client,
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
test.afterTest(t)
|
||||
})
|
||||
|
||||
return test
|
||||
}
|
||||
|
||||
type fakeLocalAuthorityServer struct {
|
||||
localauthorityv1.UnsafeLocalAuthorityServer
|
||||
|
||||
ActiveJWT,
|
||||
PreparedJWT,
|
||||
OldJWT,
|
||||
ActiveX509,
|
||||
PreparedX509,
|
||||
OldX509,
|
||||
TaintedX509,
|
||||
RevokedX509,
|
||||
TaintedJWT,
|
||||
RevokedJWT *localauthorityv1.AuthorityState
|
||||
|
||||
TaintedUpstreamAuthoritySubjectKeyId,
|
||||
RevokedUpstreamAuthoritySubjectKeyId string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) GetJWTAuthorityState(context.Context, *localauthorityv1.GetJWTAuthorityStateRequest) (*localauthorityv1.GetJWTAuthorityStateResponse, error) {
|
||||
return &localauthorityv1.GetJWTAuthorityStateResponse{
|
||||
Active: s.ActiveJWT,
|
||||
Prepared: s.PreparedJWT,
|
||||
Old: s.OldJWT,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) PrepareJWTAuthority(context.Context, *localauthorityv1.PrepareJWTAuthorityRequest) (*localauthorityv1.PrepareJWTAuthorityResponse, error) {
|
||||
return &localauthorityv1.PrepareJWTAuthorityResponse{
|
||||
PreparedAuthority: s.PreparedJWT,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) ActivateJWTAuthority(context.Context, *localauthorityv1.ActivateJWTAuthorityRequest) (*localauthorityv1.ActivateJWTAuthorityResponse, error) {
|
||||
return &localauthorityv1.ActivateJWTAuthorityResponse{
|
||||
ActivatedAuthority: s.ActiveJWT,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) TaintJWTAuthority(context.Context, *localauthorityv1.TaintJWTAuthorityRequest) (*localauthorityv1.TaintJWTAuthorityResponse, error) {
|
||||
return &localauthorityv1.TaintJWTAuthorityResponse{
|
||||
TaintedAuthority: s.TaintedJWT,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) RevokeJWTAuthority(context.Context, *localauthorityv1.RevokeJWTAuthorityRequest) (*localauthorityv1.RevokeJWTAuthorityResponse, error) {
|
||||
return &localauthorityv1.RevokeJWTAuthorityResponse{
|
||||
RevokedAuthority: s.RevokedJWT,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) GetX509AuthorityState(context.Context, *localauthorityv1.GetX509AuthorityStateRequest) (*localauthorityv1.GetX509AuthorityStateResponse, error) {
|
||||
return &localauthorityv1.GetX509AuthorityStateResponse{
|
||||
Active: s.ActiveX509,
|
||||
Prepared: s.PreparedX509,
|
||||
Old: s.OldX509,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) PrepareX509Authority(context.Context, *localauthorityv1.PrepareX509AuthorityRequest) (*localauthorityv1.PrepareX509AuthorityResponse, error) {
|
||||
return &localauthorityv1.PrepareX509AuthorityResponse{
|
||||
PreparedAuthority: s.PreparedX509,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) ActivateX509Authority(context.Context, *localauthorityv1.ActivateX509AuthorityRequest) (*localauthorityv1.ActivateX509AuthorityResponse, error) {
|
||||
return &localauthorityv1.ActivateX509AuthorityResponse{
|
||||
ActivatedAuthority: s.ActiveX509,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) TaintX509Authority(context.Context, *localauthorityv1.TaintX509AuthorityRequest) (*localauthorityv1.TaintX509AuthorityResponse, error) {
|
||||
return &localauthorityv1.TaintX509AuthorityResponse{
|
||||
TaintedAuthority: s.TaintedX509,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) TaintX509UpstreamAuthority(context.Context, *localauthorityv1.TaintX509UpstreamAuthorityRequest) (*localauthorityv1.TaintX509UpstreamAuthorityResponse, error) {
|
||||
return &localauthorityv1.TaintX509UpstreamAuthorityResponse{
|
||||
UpstreamAuthoritySubjectKeyId: s.TaintedUpstreamAuthoritySubjectKeyId,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) RevokeX509Authority(context.Context, *localauthorityv1.RevokeX509AuthorityRequest) (*localauthorityv1.RevokeX509AuthorityResponse, error) {
|
||||
return &localauthorityv1.RevokeX509AuthorityResponse{
|
||||
RevokedAuthority: s.RevokedX509,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func (s *fakeLocalAuthorityServer) RevokeX509UpstreamAuthority(context.Context, *localauthorityv1.RevokeX509UpstreamAuthorityRequest) (*localauthorityv1.RevokeX509UpstreamAuthorityResponse, error) {
|
||||
return &localauthorityv1.RevokeX509UpstreamAuthorityResponse{
|
||||
UpstreamAuthoritySubjectKeyId: s.RevokedUpstreamAuthoritySubjectKeyId,
|
||||
}, s.Err
|
||||
}
|
||||
|
||||
func RequireOutputBasedOnFormat(t *testing.T, format, stdoutString string, expectedStdoutPretty, expectedStdoutJSON string) {
|
||||
switch format {
|
||||
case "pretty":
|
||||
require.Contains(t, stdoutString, expectedStdoutPretty)
|
||||
case "json":
|
||||
if expectedStdoutJSON != "" {
|
||||
require.JSONEq(t, expectedStdoutJSON, stdoutString)
|
||||
} else {
|
||||
require.Empty(t, stdoutString)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package bundle
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ func TestSetHelp(t *testing.T) {
|
|||
|
||||
func TestSetSynopsis(t *testing.T) {
|
||||
test := setupTest(t, newSetCommand)
|
||||
require.Equal(t, "Creates or updates federated bundle data", test.client.Synopsis())
|
||||
require.Equal(t, "Creates or updates bundle data", test.client.Synopsis())
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
|
@ -697,7 +697,7 @@ func TestDeleteHelp(t *testing.T) {
|
|||
|
||||
func TestDeleteSynopsis(t *testing.T) {
|
||||
test := setupTest(t, newDeleteCommand)
|
||||
require.Equal(t, "Deletes federated bundle data", test.client.Synopsis())
|
||||
require.Equal(t, "Deletes bundle data", test.client.Synopsis())
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package bundle
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package bundle
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
|
@ -16,7 +17,7 @@ import (
|
|||
"github.com/spiffe/go-spiffe/v2/spiffeid"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
"github.com/spiffe/spire/cmd/spire-server/util"
|
||||
"github.com/spiffe/spire/pkg/common/jwtutil"
|
||||
"github.com/zeebo/errs"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -77,7 +78,7 @@ func printBundle(out io.Writer, bundle *types.Bundle) error {
|
|||
|
||||
docBytes, err := b.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
|
||||
var o bytes.Buffer
|
||||
|
@ -85,8 +86,11 @@ func printBundle(out io.Writer, bundle *types.Bundle) error {
|
|||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(out, o.String())
|
||||
return err
|
||||
if _, err := fmt.Fprintln(out, o.String()); err != nil {
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// bundleFromProto converts a bundle from the given *types.Bundle to *spiffebundle.Bundle
|
||||
|
@ -99,7 +103,7 @@ func bundleFromProto(bundleProto *types.Bundle) (*spiffebundle.Bundle, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
jwtAuthorities, err := jwtutil.JWTKeysFromProto(bundleProto.JwtAuthorities)
|
||||
jwtAuthorities, err := jwtKeysFromProto(bundleProto.JwtAuthorities)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -128,6 +132,20 @@ func x509CertificatesFromProto(proto []*types.X509Certificate) ([]*x509.Certific
|
|||
return certs, nil
|
||||
}
|
||||
|
||||
// jwtKeysFromProto converts JWT keys from the given []*types.JWTKey to map[string]crypto.PublicKey.
|
||||
// The key ID of the public key is used as the key in the returned map.
|
||||
func jwtKeysFromProto(proto []*types.JWTKey) (map[string]crypto.PublicKey, error) {
|
||||
keys := make(map[string]crypto.PublicKey)
|
||||
for i, publicKey := range proto {
|
||||
jwtSigningKey, err := x509.ParsePKIXPublicKey(publicKey.PublicKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse JWT signing key %d: %w", i, err)
|
||||
}
|
||||
keys[publicKey.KeyId] = jwtSigningKey
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
func printBundleWithFormat(out io.Writer, bundle *types.Bundle, format string, header bool) error {
|
||||
if bundle == nil {
|
||||
return errors.New("no bundle provided")
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
"github.com/mitchellh/cli"
|
||||
bundlev1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/bundle/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/common"
|
||||
common_cli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/pemutil"
|
||||
"github.com/spiffe/spire/test/clitest"
|
||||
"github.com/spiffe/spire/test/spiretest"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
|
@ -203,7 +203,7 @@ func setupTest(t *testing.T, newClient func(*common_cli.Env) cli.Command) *bundl
|
|||
cert1: cert1,
|
||||
cert2: cert2,
|
||||
key1Pkix: key1Pkix,
|
||||
addr: clitest.GetAddr(addr),
|
||||
addr: common.GetAddr(addr),
|
||||
stdin: stdin,
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
|
@ -241,7 +241,7 @@ func (s *bundleTest) afterTest(t *testing.T) {
|
|||
}
|
||||
|
||||
func (s *bundleTest) args(extra ...string) []string {
|
||||
return append([]string{clitest.AddrArg, s.addr}, extra...)
|
||||
return append([]string{common.AddrArg, s.addr}, extra...)
|
||||
}
|
||||
|
||||
type fakeBundleServer struct {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package bundle
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
|
@ -11,6 +10,8 @@ import (
|
|||
bundlev1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/bundle/v1"
|
||||
"github.com/spiffe/spire/cmd/spire-server/util"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type countCommand struct {
|
||||
|
@ -52,7 +53,7 @@ func (c *countCommand) AppendFlags(fs *flag.FlagSet) {
|
|||
cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, prettyPrintCount)
|
||||
}
|
||||
|
||||
func prettyPrintCount(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintCount(env *commoncli.Env, results ...interface{}) error {
|
||||
countResp, ok := results[0].(*bundlev1.CountBundlesResponse)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
|
|
@ -44,7 +44,7 @@ func (c *deleteCommand) Name() string {
|
|||
}
|
||||
|
||||
func (c *deleteCommand) Synopsis() string {
|
||||
return "Deletes federated bundle data"
|
||||
return "Deletes bundle data"
|
||||
}
|
||||
|
||||
func (c *deleteCommand) AppendFlags(fs *flag.FlagSet) {
|
||||
|
@ -77,7 +77,7 @@ func (c *deleteCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient
|
|||
return c.printer.PrintProto(resp)
|
||||
}
|
||||
|
||||
func prettyPrintDelete(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintDelete(env *commoncli.Env, results ...interface{}) error {
|
||||
deleteResp, ok := results[0].(*bundlev1.BatchDeleteFederatedBundleResponse)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
|
|
@ -63,7 +63,7 @@ func (c *listCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient ut
|
|||
return c.printer.PrintProto(resp)
|
||||
}
|
||||
|
||||
func (c *listCommand) prettyPrintList(env *commoncli.Env, results ...any) error {
|
||||
func (c *listCommand) prettyPrintList(env *commoncli.Env, results ...interface{}) error {
|
||||
if listResp, ok := results[0].(*bundlev1.ListFederatedBundlesResponse); ok {
|
||||
for i, bundle := range listResp.Bundles {
|
||||
if i != 0 {
|
||||
|
|
|
@ -39,7 +39,7 @@ func (c *setCommand) Name() string {
|
|||
}
|
||||
|
||||
func (c *setCommand) Synopsis() string {
|
||||
return "Creates or updates federated bundle data"
|
||||
return "Creates or updates bundle data"
|
||||
}
|
||||
|
||||
func (c *setCommand) AppendFlags(fs *flag.FlagSet) {
|
||||
|
@ -80,7 +80,7 @@ func (c *setCommand) Run(ctx context.Context, env *common_cli.Env, serverClient
|
|||
return c.printer.PrintProto(resp)
|
||||
}
|
||||
|
||||
func prettyPrintSet(env *common_cli.Env, results ...any) error {
|
||||
func prettyPrintSet(env *common_cli.Env, results ...interface{}) error {
|
||||
setResp, ok := results[0].(*bundlev1.BatchSetFederatedBundleResponse)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
|
|
@ -51,7 +51,7 @@ func (c *showCommand) Run(ctx context.Context, _ *common_cli.Env, serverClient u
|
|||
return c.printer.PrintProto(resp)
|
||||
}
|
||||
|
||||
func (c *showCommand) prettyPrintBundle(env *common_cli.Env, results ...any) error {
|
||||
func (c *showCommand) prettyPrintBundle(env *common_cli.Env, results ...interface{}) error {
|
||||
showResp, ok := results[0].(*types.Bundle)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
|
|
@ -11,12 +11,8 @@ import (
|
|||
"github.com/spiffe/spire/cmd/spire-server/cli/federation"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/healthcheck"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/jwt"
|
||||
localauthority_jwt "github.com/spiffe/spire/cmd/spire-server/cli/localauthority/jwt"
|
||||
localauthority_x509 "github.com/spiffe/spire/cmd/spire-server/cli/localauthority/x509"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/logger"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/run"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/token"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/upstreamauthority"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/validate"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/x509"
|
||||
"github.com/spiffe/spire/pkg/common/log"
|
||||
|
@ -100,15 +96,6 @@ func (cc *CLI) Run(ctx context.Context, args []string) int {
|
|||
"federation update": func() (cli.Command, error) {
|
||||
return federation.NewUpdateCommand(), nil
|
||||
},
|
||||
"logger get": func() (cli.Command, error) {
|
||||
return logger.NewGetCommand(), nil
|
||||
},
|
||||
"logger set": func() (cli.Command, error) {
|
||||
return logger.NewSetCommand(), nil
|
||||
},
|
||||
"logger reset": func() (cli.Command, error) {
|
||||
return logger.NewResetCommand(), nil
|
||||
},
|
||||
"run": func() (cli.Command, error) {
|
||||
return run.NewRunCommand(ctx, cc.LogOptions, cc.AllowUnknownConfig), nil
|
||||
},
|
||||
|
@ -127,42 +114,6 @@ func (cc *CLI) Run(ctx context.Context, args []string) int {
|
|||
"validate": func() (cli.Command, error) {
|
||||
return validate.NewValidateCommand(), nil
|
||||
},
|
||||
"localauthority x509 show": func() (cli.Command, error) {
|
||||
return localauthority_x509.NewX509ShowCommand(), nil
|
||||
},
|
||||
"localauthority x509 prepare": func() (cli.Command, error) {
|
||||
return localauthority_x509.NewX509PrepareCommand(), nil
|
||||
},
|
||||
"localauthority x509 activate": func() (cli.Command, error) {
|
||||
return localauthority_x509.NewX509ActivateCommand(), nil
|
||||
},
|
||||
"localauthority x509 taint": func() (cli.Command, error) {
|
||||
return localauthority_x509.NewX509TaintCommand(), nil
|
||||
},
|
||||
"localauthority x509 revoke": func() (cli.Command, error) {
|
||||
return localauthority_x509.NewX509RevokeCommand(), nil
|
||||
},
|
||||
"localauthority jwt show": func() (cli.Command, error) {
|
||||
return localauthority_jwt.NewJWTShowCommand(), nil
|
||||
},
|
||||
"localauthority jwt prepare": func() (cli.Command, error) {
|
||||
return localauthority_jwt.NewJWTPrepareCommand(), nil
|
||||
},
|
||||
"localauthority jwt activate": func() (cli.Command, error) {
|
||||
return localauthority_jwt.NewJWTActivateCommand(), nil
|
||||
},
|
||||
"localauthority jwt taint": func() (cli.Command, error) {
|
||||
return localauthority_jwt.NewJWTTaintCommand(), nil
|
||||
},
|
||||
"localauthority jwt revoke": func() (cli.Command, error) {
|
||||
return localauthority_jwt.NewJWTRevokeCommand(), nil
|
||||
},
|
||||
"upstreamauthority taint": func() (cli.Command, error) {
|
||||
return upstreamauthority.NewTaintCommand(), nil
|
||||
},
|
||||
"upstreamauthority revoke": func() (cli.Command, error) {
|
||||
return upstreamauthority.NewRevokeCommand(), nil
|
||||
},
|
||||
}
|
||||
|
||||
exitStatus, err := c.Run()
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package clitest
|
||||
package common
|
||||
|
||||
import "net"
|
||||
|
||||
var (
|
||||
AddrArg = "-socketPath"
|
||||
AddrError = "rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing: dial unix ///does-not-exist.sock: connect: no such file or directory\"\n"
|
||||
AddrError = "Error: connection error: desc = \"transport: error while dialing: dial unix /does-not-exist.sock: connect: no such file or directory\"\n"
|
||||
AddrOutputUsage = `
|
||||
-output value
|
||||
Desired output format (pretty, json); default: pretty.
|
||||
|
@ -13,3 +16,7 @@ var (
|
|||
`
|
||||
AddrValue = "/does-not-exist.sock"
|
||||
)
|
||||
|
||||
func GetAddr(addr net.Addr) string {
|
||||
return addr.String()
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/spiffe/spire/pkg/common/namedpipe"
|
||||
)
|
||||
|
||||
var (
|
||||
AddrArg = "-namedPipeName"
|
||||
AddrError = "Error: connection error: desc = \"transport: error while dialing: open \\\\\\\\.\\\\pipe\\\\does-not-exist: The system cannot find the file specified.\"\n"
|
||||
AddrOutputUsage = `
|
||||
-namedPipeName string
|
||||
Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api")
|
||||
-output value
|
||||
Desired output format (pretty, json); default: pretty.
|
||||
`
|
||||
AddrValue = "\\does-not-exist"
|
||||
)
|
||||
|
||||
func GetAddr(addr net.Addr) string {
|
||||
return namedpipe.GetPipeName(addr.String())
|
||||
}
|
|
@ -1,45 +1,20 @@
|
|||
package entry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
|
||||
entryv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/entry/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
"github.com/spiffe/spire/cmd/spire-server/util"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type countCommand struct {
|
||||
// Type and value are delimited by a colon (:)
|
||||
// ex. "unix:uid:1000" or "spiffe_id:spiffe://example.org/foo"
|
||||
selectors StringsFlag
|
||||
|
||||
// Workload parent spiffeID
|
||||
parentID string
|
||||
|
||||
// Workload spiffeID
|
||||
spiffeID string
|
||||
|
||||
// Entry hint
|
||||
hint string
|
||||
|
||||
// List of SPIFFE IDs of trust domains the registration entry is federated with
|
||||
federatesWith StringsFlag
|
||||
|
||||
// Whether the entry is for a downstream SPIRE server
|
||||
downstream bool
|
||||
|
||||
// Match used when filtering by federates with
|
||||
matchFederatesWithOn string
|
||||
|
||||
// Match used when filtering by selectors
|
||||
matchSelectorsOn string
|
||||
|
||||
printer cliprinter.Printer
|
||||
env *commoncli.Env
|
||||
}
|
||||
|
@ -66,66 +41,7 @@ func (*countCommand) Synopsis() string {
|
|||
// Run counts attested entries
|
||||
func (c *countCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient util.ServerClient) error {
|
||||
entryClient := serverClient.NewEntryClient()
|
||||
|
||||
filter := &entryv1.CountEntriesRequest_Filter{}
|
||||
if c.parentID != "" {
|
||||
id, err := idStringToProto(c.parentID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing parent ID %q: %w", c.parentID, err)
|
||||
}
|
||||
filter.ByParentId = id
|
||||
}
|
||||
|
||||
if c.spiffeID != "" {
|
||||
id, err := idStringToProto(c.spiffeID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing SPIFFE ID %q: %w", c.spiffeID, err)
|
||||
}
|
||||
filter.BySpiffeId = id
|
||||
}
|
||||
|
||||
if len(c.selectors) != 0 {
|
||||
matchSelectorBehavior, err := parseToSelectorMatch(c.matchSelectorsOn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
selectors := make([]*types.Selector, len(c.selectors))
|
||||
for i, sel := range c.selectors {
|
||||
selector, err := util.ParseSelector(sel)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing selectors: %w", err)
|
||||
}
|
||||
selectors[i] = selector
|
||||
}
|
||||
filter.BySelectors = &types.SelectorMatch{
|
||||
Selectors: selectors,
|
||||
Match: matchSelectorBehavior,
|
||||
}
|
||||
}
|
||||
|
||||
filter.ByDownstream = wrapperspb.Bool(c.downstream)
|
||||
|
||||
if len(c.federatesWith) > 0 {
|
||||
matchFederatesWithBehavior, err := parseToFederatesWithMatch(c.matchFederatesWithOn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filter.ByFederatesWith = &types.FederatesWithMatch{
|
||||
TrustDomains: c.federatesWith,
|
||||
Match: matchFederatesWithBehavior,
|
||||
}
|
||||
}
|
||||
|
||||
if c.hint != "" {
|
||||
filter.ByHint = wrapperspb.String(c.hint)
|
||||
}
|
||||
|
||||
countResponse, err := entryClient.CountEntries(ctx, &entryv1.CountEntriesRequest{
|
||||
Filter: filter,
|
||||
})
|
||||
|
||||
countResponse, err := entryClient.CountEntries(ctx, &entryv1.CountEntriesRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -134,19 +50,10 @@ func (c *countCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient u
|
|||
}
|
||||
|
||||
func (c *countCommand) AppendFlags(fs *flag.FlagSet) {
|
||||
fs.StringVar(&c.parentID, "parentID", "", "The Parent ID of the records to count")
|
||||
fs.StringVar(&c.spiffeID, "spiffeID", "", "The SPIFFE ID of the records to count")
|
||||
fs.BoolVar(&c.downstream, "downstream", false, "A boolean value that, when set, indicates that the entry describes a downstream SPIRE server")
|
||||
fs.Var(&c.selectors, "selector", "A colon-delimited type:value selector. Can be used more than once")
|
||||
fs.Var(&c.federatesWith, "federatesWith", "SPIFFE ID of a trust domain an entry is federate with. Can be used more than once")
|
||||
fs.StringVar(&c.matchFederatesWithOn, "matchFederatesWithOn", "superset", "The match mode used when filtering by federates with. Options: exact, any, superset and subset")
|
||||
fs.StringVar(&c.matchSelectorsOn, "matchSelectorsOn", "superset", "The match mode used when filtering by selectors. Options: exact, any, superset and subset")
|
||||
fs.StringVar(&c.hint, "hint", "", "The Hint of the records to count (optional)")
|
||||
|
||||
cliprinter.AppendFlagWithCustomPretty(&c.printer, fs, c.env, c.prettyPrintCount)
|
||||
}
|
||||
|
||||
func (c *countCommand) prettyPrintCount(env *commoncli.Env, results ...any) error {
|
||||
func (c *countCommand) prettyPrintCount(env *commoncli.Env, results ...interface{}) error {
|
||||
countResp, ok := results[0].(*entryv1.CountEntriesResponse)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
|
|
@ -5,11 +5,9 @@ import (
|
|||
"testing"
|
||||
|
||||
entryv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/entry/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
func TestCountHelp(t *testing.T) {
|
||||
|
@ -33,262 +31,12 @@ func TestCount(t *testing.T) {
|
|||
for _, tt := range []struct {
|
||||
name string
|
||||
args []string
|
||||
expCountReq *entryv1.CountEntriesRequest
|
||||
fakeCountResp *entryv1.CountEntriesResponse
|
||||
serverErr error
|
||||
expOutPretty string
|
||||
expOutJSON string
|
||||
expErr string
|
||||
}{
|
||||
{
|
||||
name: "Count all entries (empty filter)",
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp4,
|
||||
expOutPretty: "4 registration entries",
|
||||
expOutJSON: `{"count":4}`,
|
||||
},
|
||||
{
|
||||
name: "Count by parentID",
|
||||
args: []string{"-parentID", "spiffe://example.org/father"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
ByParentId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/father"},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp2,
|
||||
expOutPretty: "2 registration entries",
|
||||
expOutJSON: `{"count":2}`,
|
||||
},
|
||||
{
|
||||
name: "Count by parent ID using invalid ID",
|
||||
args: []string{"-parentID", "invalid-id"},
|
||||
expErr: "Error: error parsing parent ID \"invalid-id\": scheme is missing or invalid\n",
|
||||
},
|
||||
{
|
||||
name: "Count by SPIFFE ID",
|
||||
args: []string{"-spiffeID", "spiffe://example.org/daughter"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
BySpiffeId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/daughter"},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp2,
|
||||
expOutPretty: "2 registration entries",
|
||||
expOutJSON: `{"count":2}`,
|
||||
},
|
||||
{
|
||||
name: "Count by SPIFFE ID using invalid ID",
|
||||
args: []string{"-spiffeID", "invalid-id"},
|
||||
expErr: "Error: error parsing SPIFFE ID \"invalid-id\": scheme is missing or invalid\n",
|
||||
},
|
||||
{
|
||||
name: "Count by selectors: default matcher",
|
||||
args: []string{"-selector", "foo:bar", "-selector", "bar:baz"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
BySelectors: &types.SelectorMatch{
|
||||
Selectors: []*types.Selector{
|
||||
{Type: "foo", Value: "bar"},
|
||||
{Type: "bar", Value: "baz"},
|
||||
},
|
||||
Match: types.SelectorMatch_MATCH_SUPERSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp1,
|
||||
expOutPretty: "1 registration entry",
|
||||
expOutJSON: `{"count":1}`,
|
||||
},
|
||||
{
|
||||
name: "Count by selectors: exact matcher",
|
||||
args: []string{"-selector", "foo:bar", "-selector", "bar:baz", "-matchSelectorsOn", "exact"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
BySelectors: &types.SelectorMatch{
|
||||
Selectors: []*types.Selector{
|
||||
{Type: "foo", Value: "bar"},
|
||||
{Type: "bar", Value: "baz"},
|
||||
},
|
||||
Match: types.SelectorMatch_MATCH_EXACT,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp1,
|
||||
expOutPretty: "1 registration entry",
|
||||
expOutJSON: `{"count":1}`,
|
||||
},
|
||||
{
|
||||
name: "Count by selectors: superset matcher",
|
||||
args: []string{"-selector", "foo:bar", "-selector", "bar:baz", "-matchSelectorsOn", "superset"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
BySelectors: &types.SelectorMatch{
|
||||
Selectors: []*types.Selector{
|
||||
{Type: "foo", Value: "bar"},
|
||||
{Type: "bar", Value: "baz"},
|
||||
},
|
||||
Match: types.SelectorMatch_MATCH_SUPERSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp1,
|
||||
expOutPretty: "1 registration entry",
|
||||
expOutJSON: `{"count":1}`,
|
||||
},
|
||||
{
|
||||
name: "Count by selectors: subset matcher",
|
||||
args: []string{"-selector", "foo:bar", "-selector", "bar:baz", "-matchSelectorsOn", "subset"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
BySelectors: &types.SelectorMatch{
|
||||
Selectors: []*types.Selector{
|
||||
{Type: "foo", Value: "bar"},
|
||||
{Type: "bar", Value: "baz"},
|
||||
},
|
||||
Match: types.SelectorMatch_MATCH_SUBSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp1,
|
||||
expOutPretty: "1 registration entry",
|
||||
expOutJSON: `{"count":1}`,
|
||||
},
|
||||
{
|
||||
name: "Count by selectors: Any matcher",
|
||||
args: []string{"-selector", "foo:bar", "-selector", "bar:baz", "-matchSelectorsOn", "any"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
BySelectors: &types.SelectorMatch{
|
||||
Selectors: []*types.Selector{
|
||||
{Type: "foo", Value: "bar"},
|
||||
{Type: "bar", Value: "baz"},
|
||||
},
|
||||
Match: types.SelectorMatch_MATCH_ANY,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp1,
|
||||
expOutPretty: "1 registration entry",
|
||||
expOutJSON: `{"count":1}`,
|
||||
},
|
||||
{
|
||||
name: "Count by selectors: Invalid matcher",
|
||||
args: []string{"-selector", "foo:bar", "-selector", "bar:baz", "-matchSelectorsOn", "NO-MATCHER"},
|
||||
expErr: "Error: match behavior \"NO-MATCHER\" unknown\n",
|
||||
},
|
||||
{
|
||||
name: "Count by selector using invalid selector",
|
||||
args: []string{"-selector", "invalid-selector"},
|
||||
expErr: "Error: error parsing selectors: selector \"invalid-selector\" must be formatted as type:value\n",
|
||||
},
|
||||
{
|
||||
name: "Server error",
|
||||
args: []string{"-spiffeID", "spiffe://example.org/daughter"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
BySpiffeId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/daughter"},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
serverErr: status.Error(codes.Internal, "internal server error"),
|
||||
expErr: "Error: rpc error: code = Internal desc = internal server error\n",
|
||||
},
|
||||
{
|
||||
name: "Count by Federates With: default matcher",
|
||||
args: []string{"-federatesWith", "spiffe://domain.test"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
ByFederatesWith: &types.FederatesWithMatch{
|
||||
TrustDomains: []string{"spiffe://domain.test"},
|
||||
Match: types.FederatesWithMatch_MATCH_SUPERSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp1,
|
||||
expOutPretty: "1 registration entry",
|
||||
expOutJSON: `{"count":1}`,
|
||||
},
|
||||
{
|
||||
name: "Count by Federates With: exact matcher",
|
||||
args: []string{"-federatesWith", "spiffe://domain.test", "-matchFederatesWithOn", "exact"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
ByFederatesWith: &types.FederatesWithMatch{
|
||||
TrustDomains: []string{"spiffe://domain.test"},
|
||||
Match: types.FederatesWithMatch_MATCH_EXACT,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp1,
|
||||
expOutPretty: "1 registration entry",
|
||||
expOutJSON: `{"count":1}`,
|
||||
},
|
||||
{
|
||||
name: "Count by Federates With: Any matcher",
|
||||
args: []string{"-federatesWith", "spiffe://domain.test", "-matchFederatesWithOn", "any"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
ByFederatesWith: &types.FederatesWithMatch{
|
||||
TrustDomains: []string{"spiffe://domain.test"},
|
||||
Match: types.FederatesWithMatch_MATCH_ANY,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp1,
|
||||
expOutPretty: "1 registration entry",
|
||||
expOutJSON: `{"count":1}`,
|
||||
},
|
||||
{
|
||||
name: "Count by Federates With: superset matcher",
|
||||
args: []string{"-federatesWith", "spiffe://domain.test", "-matchFederatesWithOn", "superset"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
ByFederatesWith: &types.FederatesWithMatch{
|
||||
TrustDomains: []string{"spiffe://domain.test"},
|
||||
Match: types.FederatesWithMatch_MATCH_SUPERSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp1,
|
||||
expOutPretty: "1 registration entry",
|
||||
expOutJSON: `{"count":1}`,
|
||||
},
|
||||
{
|
||||
name: "Count by Federates With: subset matcher",
|
||||
args: []string{"-federatesWith", "spiffe://domain.test", "-matchFederatesWithOn", "subset"},
|
||||
expCountReq: &entryv1.CountEntriesRequest{
|
||||
Filter: &entryv1.CountEntriesRequest_Filter{
|
||||
ByFederatesWith: &types.FederatesWithMatch{
|
||||
TrustDomains: []string{"spiffe://domain.test"},
|
||||
Match: types.FederatesWithMatch_MATCH_SUBSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeCountResp: fakeResp1,
|
||||
expOutPretty: "1 registration entry",
|
||||
expOutJSON: `{"count":1}`,
|
||||
},
|
||||
{
|
||||
name: "Count by Federates With: Invalid matcher",
|
||||
args: []string{"-federatesWith", "spiffe://domain.test", "-matchFederatesWithOn", "NO-MATCHER"},
|
||||
expErr: "Error: match behavior \"NO-MATCHER\" unknown\n",
|
||||
},
|
||||
{
|
||||
name: "4 entries",
|
||||
fakeCountResp: fakeResp4,
|
||||
|
@ -325,16 +73,13 @@ func TestCount(t *testing.T) {
|
|||
test.server.err = tt.serverErr
|
||||
test.server.countEntriesResp = tt.fakeCountResp
|
||||
|
||||
args := tt.args
|
||||
args = append(args, "-output", format)
|
||||
|
||||
rc := test.client.Run(test.args(args...))
|
||||
rc := test.client.Run(test.args(tt.args...))
|
||||
if tt.expErr != "" {
|
||||
require.Equal(t, 1, rc)
|
||||
require.Equal(t, tt.expErr, test.stderr.String())
|
||||
return
|
||||
}
|
||||
requireOutputBasedOnFormat(t, format, test.stdout.String(), tt.expOutPretty, tt.expOutJSON)
|
||||
requireOutputBasedOnFormat(t, test.stdout.String(), format, tt.expOutPretty, tt.expOutJSON)
|
||||
require.Equal(t, 0, rc)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
package entry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
entryv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/entry/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
serverutil "github.com/spiffe/spire/cmd/spire-server/util"
|
||||
"github.com/spiffe/spire/cmd/spire-server/util"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"github.com/spiffe/spire/pkg/common/idutil"
|
||||
"github.com/spiffe/spire/pkg/common/util"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// NewCreateCommand creates a new "create" subcommand for "entry" command.
|
||||
|
@ -23,7 +22,7 @@ func NewCreateCommand() cli.Command {
|
|||
}
|
||||
|
||||
func newCreateCommand(env *commoncli.Env) cli.Command {
|
||||
return serverutil.AdaptCommand(env, &createCommand{env: env})
|
||||
return util.AdaptCommand(env, &createCommand{env: env})
|
||||
}
|
||||
|
||||
type createCommand struct {
|
||||
|
@ -47,6 +46,11 @@ type createCommand struct {
|
|||
// Entry hint, used to disambiguate entries with the same SPIFFE ID
|
||||
hint string
|
||||
|
||||
// TTL for x509 and JWT SVIDs issued to this workload, unless type specific TTLs are set.
|
||||
// This field is deprecated in favor of the x509SVIDTTL and jwtSVIDTTL fields and will be
|
||||
// removed in a future release.
|
||||
ttl int
|
||||
|
||||
// TTL for x509 SVIDs issued to this workload
|
||||
x509SVIDTTL int
|
||||
|
||||
|
@ -56,13 +60,13 @@ type createCommand struct {
|
|||
// List of SPIFFE IDs of trust domains the registration entry is federated with
|
||||
federatesWith StringsFlag
|
||||
|
||||
// whether the registration entry is for an "admin" workload
|
||||
// Whether or not the registration entry is for an "admin" workload
|
||||
admin bool
|
||||
|
||||
// whether the entry is for a downstream SPIRE server
|
||||
// Whether or not the entry is for a downstream SPIRE server
|
||||
downstream bool
|
||||
|
||||
// whether the entry represents a node or group of nodes
|
||||
// Whether or not the entry represents a node or group of nodes
|
||||
node bool
|
||||
|
||||
// Expiry of entry
|
||||
|
@ -91,8 +95,9 @@ func (c *createCommand) AppendFlags(f *flag.FlagSet) {
|
|||
f.StringVar(&c.entryID, "entryID", "", "A custom ID for this registration entry (optional). If not set, a new entry ID will be generated")
|
||||
f.StringVar(&c.parentID, "parentID", "", "The SPIFFE ID of this record's parent")
|
||||
f.StringVar(&c.spiffeID, "spiffeID", "", "The SPIFFE ID that this record represents")
|
||||
f.IntVar(&c.x509SVIDTTL, "x509SVIDTTL", 0, "The lifetime, in seconds, for x509-SVIDs issued based on this registration entry.")
|
||||
f.IntVar(&c.jwtSVIDTTL, "jwtSVIDTTL", 0, "The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry.")
|
||||
f.IntVar(&c.ttl, "ttl", 0, "The lifetime, in seconds, for SVIDs issued based on this registration entry. This flag is deprecated in favor of x509SVIDTTL and jwtSVIDTTL and will be removed in a future version")
|
||||
f.IntVar(&c.x509SVIDTTL, "x509SVIDTTL", 0, "The lifetime, in seconds, for x509-SVIDs issued based on this registration entry. Overrides ttl flag")
|
||||
f.IntVar(&c.jwtSVIDTTL, "jwtSVIDTTL", 0, "The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry. Overrides ttl flag")
|
||||
f.StringVar(&c.path, "data", "", "Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin.")
|
||||
f.Var(&c.selectors, "selector", "A colon-delimited type:value selector. Can be used more than once")
|
||||
f.Var(&c.federatesWith, "federatesWith", "SPIFFE ID of a trust domain to federate with. Can be used more than once")
|
||||
|
@ -106,7 +111,7 @@ func (c *createCommand) AppendFlags(f *flag.FlagSet) {
|
|||
cliprinter.AppendFlagWithCustomPretty(&c.printer, f, c.env, prettyPrintCreate)
|
||||
}
|
||||
|
||||
func (c *createCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient serverutil.ServerClient) error {
|
||||
func (c *createCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient util.ServerClient) error {
|
||||
if err := c.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -154,6 +159,10 @@ func (c *createCommand) validate() (err error) {
|
|||
return errors.New("a SPIFFE ID is required")
|
||||
}
|
||||
|
||||
if c.ttl < 0 {
|
||||
return errors.New("a positive TTL is required")
|
||||
}
|
||||
|
||||
if c.x509SVIDTTL < 0 {
|
||||
return errors.New("a positive x509-SVID TTL is required")
|
||||
}
|
||||
|
@ -162,6 +171,10 @@ func (c *createCommand) validate() (err error) {
|
|||
return errors.New("a positive JWT-SVID TTL is required")
|
||||
}
|
||||
|
||||
if c.ttl > 0 && (c.x509SVIDTTL > 0 || c.jwtSVIDTTL > 0) {
|
||||
return errors.New("use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -177,16 +190,6 @@ func (c *createCommand) parseConfig() ([]*types.Entry, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
x509SvidTTL, err := util.CheckedCast[int32](c.x509SVIDTTL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid value for X509 SVID TTL: %w", err)
|
||||
}
|
||||
|
||||
jwtSvidTTL, err := util.CheckedCast[int32](c.jwtSVIDTTL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid value for JWT SVID TTL: %w", err)
|
||||
}
|
||||
|
||||
e := &types.Entry{
|
||||
Id: c.entryID,
|
||||
ParentId: parentID,
|
||||
|
@ -195,14 +198,26 @@ func (c *createCommand) parseConfig() ([]*types.Entry, error) {
|
|||
ExpiresAt: c.entryExpiry,
|
||||
DnsNames: c.dnsNames,
|
||||
StoreSvid: c.storeSVID,
|
||||
X509SvidTtl: x509SvidTTL,
|
||||
JwtSvidTtl: jwtSvidTTL,
|
||||
X509SvidTtl: int32(c.x509SVIDTTL),
|
||||
JwtSvidTtl: int32(c.jwtSVIDTTL),
|
||||
Hint: c.hint,
|
||||
}
|
||||
|
||||
// c.ttl is deprecated but usable if the new c.x509Svid field is not used.
|
||||
// c.ttl should not be used to set the jwtSVIDTTL value because the previous
|
||||
// behavior was to have a hard-coded 5 minute JWT TTL no matter what the value
|
||||
// of ttl was set to.
|
||||
// validate(...) ensures that either the new fields or the deprecated field is
|
||||
// used, but never a mixture.
|
||||
//
|
||||
// https://github.com/spiffe/spire/issues/2700
|
||||
if e.X509SvidTtl == 0 {
|
||||
e.X509SvidTtl = int32(c.ttl)
|
||||
}
|
||||
|
||||
selectors := []*types.Selector{}
|
||||
for _, s := range c.selectors {
|
||||
cs, err := serverutil.ParseSelector(s)
|
||||
cs, err := util.ParseSelector(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -244,7 +259,7 @@ func getParentID(config *createCommand, td string) (*types.SPIFFEID, error) {
|
|||
return idStringToProto(config.parentID)
|
||||
}
|
||||
|
||||
func prettyPrintCreate(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintCreate(env *commoncli.Env, results ...interface{}) error {
|
||||
var succeeded, failed []*entryv1.BatchCreateEntryResponse_Result
|
||||
createResp, ok := results[0].(*entryv1.BatchCreateEntryResponse)
|
||||
if !ok {
|
||||
|
@ -266,7 +281,7 @@ func prettyPrintCreate(env *commoncli.Env, results ...any) error {
|
|||
|
||||
for _, r := range failed {
|
||||
env.ErrPrintf("Failed to create the following entry (code: %s, msg: %q):\n",
|
||||
util.MustCast[codes.Code](r.Status.Code),
|
||||
codes.Code(r.Status.Code),
|
||||
r.Status.Message)
|
||||
printEntry(r.Entry, env.ErrPrintf)
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ func TestCreate(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
fakeRespOKFromCmdWithoutJwtTtl := &entryv1.BatchCreateEntryResponse{
|
||||
fakeRespOKFromCmd2 := &entryv1.BatchCreateEntryResponse{
|
||||
Results: []*entryv1.BatchCreateEntryResponse_Result{
|
||||
{
|
||||
Entry: &types.Entry{
|
||||
|
@ -186,16 +186,28 @@ func TestCreate(t *testing.T) {
|
|||
expErrJSON: "Error: selector \"unix\" must be formatted as type:value\n",
|
||||
},
|
||||
{
|
||||
name: "Negative X509SvidTtl",
|
||||
args: []string{"-selector", "unix", "-parentID", "spiffe://example.org/parent", "-spiffeID", "spiffe://example.org/workload", "-x509SVIDTTL", "-10"},
|
||||
expErrPretty: "Error: a positive x509-SVID TTL is required\n",
|
||||
expErrJSON: "Error: a positive x509-SVID TTL is required\n",
|
||||
name: "Negative TTL",
|
||||
args: []string{"-selector", "unix", "-parentID", "spiffe://example.org/parent", "-spiffeID", "spiffe://example.org/workload", "-ttl", "-10"},
|
||||
expErrPretty: "Error: a positive TTL is required\n",
|
||||
expErrJSON: "Error: a positive TTL is required\n",
|
||||
},
|
||||
{
|
||||
name: "Negative jwtSVIDTTL",
|
||||
args: []string{"-selector", "unix", "-parentID", "spiffe://example.org/parent", "-spiffeID", "spiffe://example.org/workload", "-jwtSVIDTTL", "-10"},
|
||||
expErrPretty: "Error: a positive JWT-SVID TTL is required\n",
|
||||
expErrJSON: "Error: a positive JWT-SVID TTL is required\n",
|
||||
name: "Invalid TTL and X509SvidTtl",
|
||||
args: []string{"-selector", "unix", "-parentID", "spiffe://example.org/parent", "-spiffeID", "spiffe://example.org/workload", "-ttl", "10", "-x509SVIDTTL", "20"},
|
||||
expErrPretty: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
expErrJSON: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
},
|
||||
{
|
||||
name: "Invalid TTL and JwtSvidTtl",
|
||||
args: []string{"-selector", "unix", "-parentID", "spiffe://example.org/parent", "-spiffeID", "spiffe://example.org/workload", "-ttl", "10", "-jwtSVIDTTL", "20"},
|
||||
expErrPretty: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
expErrJSON: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
},
|
||||
{
|
||||
name: "Invalid TTL and both X509SvidTtl and JwtSvidTtl",
|
||||
args: []string{"-selector", "unix", "-parentID", "spiffe://example.org/parent", "-spiffeID", "spiffe://example.org/workload", "-ttl", "10", "-x509SVIDTTL", "20", "-jwtSVIDTTL", "30"},
|
||||
expErrPretty: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
expErrJSON: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
},
|
||||
{
|
||||
name: "Federated node entries",
|
||||
|
@ -334,7 +346,7 @@ StoreSvid : true
|
|||
"-parentID", "spiffe://example.org/parent",
|
||||
"-selector", "zebra:zebra:2000",
|
||||
"-selector", "alpha:alpha:2000",
|
||||
"-x509SVIDTTL", "60",
|
||||
"-ttl", "60",
|
||||
"-federatesWith", "spiffe://domaina.test",
|
||||
"-federatesWith", "spiffe://domainb.test",
|
||||
"-admin",
|
||||
|
@ -364,7 +376,111 @@ StoreSvid : true
|
|||
},
|
||||
},
|
||||
},
|
||||
fakeResp: fakeRespOKFromCmdWithoutJwtTtl,
|
||||
fakeResp: fakeRespOKFromCmd2,
|
||||
expOutPretty: fmt.Sprintf(`Entry ID : entry-id
|
||||
SPIFFE ID : spiffe://example.org/workload
|
||||
Parent ID : spiffe://example.org/parent
|
||||
Revision : 0
|
||||
Downstream : true
|
||||
X509-SVID TTL : 60
|
||||
JWT-SVID TTL : default
|
||||
Expiration time : %s
|
||||
Selector : zebra:zebra:2000
|
||||
Selector : alpha:alpha:2000
|
||||
FederatesWith : spiffe://domaina.test
|
||||
FederatesWith : spiffe://domainb.test
|
||||
DNS name : unu1000
|
||||
DNS name : ung1000
|
||||
Admin : true
|
||||
StoreSvid : true
|
||||
|
||||
`, time.Unix(1552410266, 0).UTC()),
|
||||
expOutJSON: `{
|
||||
"results": [
|
||||
{
|
||||
"status": {
|
||||
"code": 0,
|
||||
"message": "OK"
|
||||
},
|
||||
"entry": {
|
||||
"id": "entry-id",
|
||||
"spiffe_id": {
|
||||
"trust_domain": "example.org",
|
||||
"path": "/workload"
|
||||
},
|
||||
"parent_id": {
|
||||
"trust_domain": "example.org",
|
||||
"path": "/parent"
|
||||
},
|
||||
"selectors": [
|
||||
{
|
||||
"type": "zebra",
|
||||
"value": "zebra:2000"
|
||||
},
|
||||
{
|
||||
"type": "alpha",
|
||||
"value": "alpha:2000"
|
||||
}
|
||||
],
|
||||
"x509_svid_ttl": 60,
|
||||
"federates_with": [
|
||||
"spiffe://domaina.test",
|
||||
"spiffe://domainb.test"
|
||||
],
|
||||
"hint": "",
|
||||
"admin": true,
|
||||
"created_at": "1547583197",
|
||||
"downstream": true,
|
||||
"expires_at": "1552410266",
|
||||
"dns_names": [
|
||||
"unu1000",
|
||||
"ung1000"
|
||||
],
|
||||
"revision_number": "0",
|
||||
"store_svid": true,
|
||||
"jwt_svid_ttl": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}`,
|
||||
},
|
||||
{
|
||||
name: "Create succeeds using deprecated command line arguments",
|
||||
args: []string{
|
||||
"-spiffeID", "spiffe://example.org/workload",
|
||||
"-parentID", "spiffe://example.org/parent",
|
||||
"-selector", "zebra:zebra:2000",
|
||||
"-selector", "alpha:alpha:2000",
|
||||
"-ttl", "60",
|
||||
"-federatesWith", "spiffe://domaina.test",
|
||||
"-federatesWith", "spiffe://domainb.test",
|
||||
"-admin",
|
||||
"-entryExpiry", "1552410266",
|
||||
"-dns", "unu1000",
|
||||
"-dns", "ung1000",
|
||||
"-downstream",
|
||||
"-storeSVID",
|
||||
},
|
||||
expReq: &entryv1.BatchCreateEntryRequest{
|
||||
Entries: []*types.Entry{
|
||||
{
|
||||
SpiffeId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/workload"},
|
||||
ParentId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/parent"},
|
||||
Selectors: []*types.Selector{
|
||||
{Type: "zebra", Value: "zebra:2000"},
|
||||
{Type: "alpha", Value: "alpha:2000"},
|
||||
},
|
||||
X509SvidTtl: 60,
|
||||
FederatesWith: []string{"spiffe://domaina.test", "spiffe://domainb.test"},
|
||||
Admin: true,
|
||||
ExpiresAt: 1552410266,
|
||||
DnsNames: []string{"unu1000", "ung1000"},
|
||||
Downstream: true,
|
||||
StoreSvid: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
fakeResp: fakeRespOKFromCmd2,
|
||||
expOutPretty: fmt.Sprintf(`Entry ID : entry-id
|
||||
SPIFFE ID : spiffe://example.org/workload
|
||||
Parent ID : spiffe://example.org/parent
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package entry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
|
@ -10,11 +9,12 @@ import (
|
|||
|
||||
"github.com/mitchellh/cli"
|
||||
entryv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/entry/v1"
|
||||
serverutil "github.com/spiffe/spire/cmd/spire-server/util"
|
||||
"github.com/spiffe/spire/cmd/spire-server/util"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"github.com/spiffe/spire/pkg/common/util"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// NewDeleteCommand creates a new "delete" subcommand for "entry" command.
|
||||
|
@ -23,7 +23,7 @@ func NewDeleteCommand() cli.Command {
|
|||
}
|
||||
|
||||
func newDeleteCommand(env *commoncli.Env) cli.Command {
|
||||
return serverutil.AdaptCommand(env, &deleteCommand{env: env})
|
||||
return util.AdaptCommand(env, &deleteCommand{env: env})
|
||||
}
|
||||
|
||||
type deleteCommand struct {
|
||||
|
@ -71,7 +71,7 @@ func parseEntryDeleteJSON(path string) ([]string, error) {
|
|||
return batchDeleteEntryRequest.Ids, nil
|
||||
}
|
||||
|
||||
func (c *deleteCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient serverutil.ServerClient) error {
|
||||
func (c *deleteCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient util.ServerClient) error {
|
||||
if err := c.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ func (c *deleteCommand) validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *deleteCommand) prettyPrintDelete(env *commoncli.Env, results ...any) error {
|
||||
func (c *deleteCommand) prettyPrintDelete(env *commoncli.Env, results ...interface{}) error {
|
||||
deleteResp, ok := results[0].(*entryv1.BatchDeleteEntryResponse)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
@ -136,7 +136,7 @@ func (c *deleteCommand) prettyPrintDelete(env *commoncli.Env, results ...any) er
|
|||
for _, result := range failed {
|
||||
env.ErrPrintf("Failed to delete entry with ID %s (code: %s, msg: %q)\n",
|
||||
result.Id,
|
||||
util.MustCast[codes.Code](result.Status.Code),
|
||||
codes.Code(result.Status.Code),
|
||||
result.Status.Message)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package entry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
@ -14,6 +13,8 @@ import (
|
|||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
commonutil "github.com/spiffe/spire/pkg/common/util"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
const listEntriesRequestPageSize = 500
|
||||
|
@ -47,7 +48,7 @@ type showCommand struct {
|
|||
// List of SPIFFE IDs of trust domains the registration entry is federated with
|
||||
federatesWith StringsFlag
|
||||
|
||||
// whether the entry is for a downstream SPIRE server
|
||||
// Whether or not the entry is for a downstream SPIRE server
|
||||
downstream bool
|
||||
|
||||
// Match used when filtering by federates with
|
||||
|
@ -175,8 +176,6 @@ func (c *showCommand) fetchEntries(ctx context.Context, client entryv1.EntryClie
|
|||
filter.ByHint = wrapperspb.String(c.hint)
|
||||
}
|
||||
|
||||
filter.ByDownstream = wrapperspb.Bool(c.downstream)
|
||||
|
||||
pageToken := ""
|
||||
|
||||
for {
|
||||
|
@ -247,7 +246,7 @@ func parseToFederatesWithMatch(match string) (types.FederatesWithMatch_MatchBeha
|
|||
}
|
||||
}
|
||||
|
||||
func prettyPrintShow(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintShow(env *commoncli.Env, results ...interface{}) error {
|
||||
listResp, ok := results[0].(*entryv1.ListEntriesResponse)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
func TestShowHelp(t *testing.T) {
|
||||
|
@ -62,9 +61,7 @@ func TestShow(t *testing.T) {
|
|||
name: "List all entries (empty filter)",
|
||||
expListReq: &entryv1.ListEntriesRequest{
|
||||
PageSize: listEntriesRequestPageSize,
|
||||
Filter: &entryv1.ListEntriesRequest_Filter{
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
Filter: &entryv1.ListEntriesRequest_Filter{},
|
||||
},
|
||||
fakeListResp: fakeRespAll,
|
||||
expOutPretty: fmt.Sprintf("Found 4 entries\n%s%s%s%s",
|
||||
|
@ -106,8 +103,7 @@ func TestShow(t *testing.T) {
|
|||
expListReq: &entryv1.ListEntriesRequest{
|
||||
PageSize: listEntriesRequestPageSize,
|
||||
Filter: &entryv1.ListEntriesRequest_Filter{
|
||||
ByParentId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/father"},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
ByParentId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/father"},
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespFather,
|
||||
|
@ -128,8 +124,7 @@ func TestShow(t *testing.T) {
|
|||
expListReq: &entryv1.ListEntriesRequest{
|
||||
PageSize: listEntriesRequestPageSize,
|
||||
Filter: &entryv1.ListEntriesRequest_Filter{
|
||||
BySpiffeId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/daughter"},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
BySpiffeId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/daughter"},
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespDaughter,
|
||||
|
@ -157,7 +152,6 @@ func TestShow(t *testing.T) {
|
|||
},
|
||||
Match: types.SelectorMatch_MATCH_SUPERSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespFatherDaughter,
|
||||
|
@ -179,7 +173,6 @@ func TestShow(t *testing.T) {
|
|||
},
|
||||
Match: types.SelectorMatch_MATCH_EXACT,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespFatherDaughter,
|
||||
|
@ -201,7 +194,6 @@ func TestShow(t *testing.T) {
|
|||
},
|
||||
Match: types.SelectorMatch_MATCH_SUPERSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespFatherDaughter,
|
||||
|
@ -223,7 +215,6 @@ func TestShow(t *testing.T) {
|
|||
},
|
||||
Match: types.SelectorMatch_MATCH_SUBSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespFatherDaughter,
|
||||
|
@ -245,7 +236,6 @@ func TestShow(t *testing.T) {
|
|||
},
|
||||
Match: types.SelectorMatch_MATCH_ANY,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespFatherDaughter,
|
||||
|
@ -270,8 +260,7 @@ func TestShow(t *testing.T) {
|
|||
expListReq: &entryv1.ListEntriesRequest{
|
||||
PageSize: listEntriesRequestPageSize,
|
||||
Filter: &entryv1.ListEntriesRequest_Filter{
|
||||
BySpiffeId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/daughter"},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
BySpiffeId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/daughter"},
|
||||
},
|
||||
},
|
||||
serverErr: status.Error(codes.Internal, "internal server error"),
|
||||
|
@ -287,7 +276,6 @@ func TestShow(t *testing.T) {
|
|||
TrustDomains: []string{"spiffe://domain.test"},
|
||||
Match: types.FederatesWithMatch_MATCH_SUPERSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespMotherDaughter,
|
||||
|
@ -306,7 +294,6 @@ func TestShow(t *testing.T) {
|
|||
TrustDomains: []string{"spiffe://domain.test"},
|
||||
Match: types.FederatesWithMatch_MATCH_EXACT,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespMotherDaughter,
|
||||
|
@ -325,7 +312,6 @@ func TestShow(t *testing.T) {
|
|||
TrustDomains: []string{"spiffe://domain.test"},
|
||||
Match: types.FederatesWithMatch_MATCH_ANY,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespMotherDaughter,
|
||||
|
@ -344,7 +330,6 @@ func TestShow(t *testing.T) {
|
|||
TrustDomains: []string{"spiffe://domain.test"},
|
||||
Match: types.FederatesWithMatch_MATCH_SUPERSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespMotherDaughter,
|
||||
|
@ -363,7 +348,6 @@ func TestShow(t *testing.T) {
|
|||
TrustDomains: []string{"spiffe://domain.test"},
|
||||
Match: types.FederatesWithMatch_MATCH_SUBSET,
|
||||
},
|
||||
ByDownstream: wrapperspb.Bool(false),
|
||||
},
|
||||
},
|
||||
fakeListResp: fakeRespMotherDaughter,
|
||||
|
@ -445,7 +429,7 @@ func getEntries(count int) []*types.Entry {
|
|||
}
|
||||
|
||||
e := []*types.Entry{}
|
||||
for i := range count {
|
||||
for i := 0; i < count; i++ {
|
||||
e = append(e, entries[i])
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
package entry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
entryv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/entry/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
serverutil "github.com/spiffe/spire/cmd/spire-server/util"
|
||||
"github.com/spiffe/spire/cmd/spire-server/util"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"github.com/spiffe/spire/pkg/common/util"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// NewUpdateCommand creates a new "update" subcommand for "entry" command.
|
||||
|
@ -22,7 +21,7 @@ func NewUpdateCommand() cli.Command {
|
|||
}
|
||||
|
||||
func newUpdateCommand(env *commoncli.Env) cli.Command {
|
||||
return serverutil.AdaptCommand(env, &updateCommand{env: env})
|
||||
return util.AdaptCommand(env, &updateCommand{env: env})
|
||||
}
|
||||
|
||||
type updateCommand struct {
|
||||
|
@ -43,9 +42,12 @@ type updateCommand struct {
|
|||
// Workload spiffeID
|
||||
spiffeID string
|
||||
|
||||
// whether the entry is for a downstream SPIRE server
|
||||
// Whether or not the entry is for a downstream SPIRE server
|
||||
downstream bool
|
||||
|
||||
// TTL for certificates issued to this workload
|
||||
ttl int
|
||||
|
||||
// TTL for x509 SVIDs issued to this workload
|
||||
x509SvidTTL int
|
||||
|
||||
|
@ -55,7 +57,7 @@ type updateCommand struct {
|
|||
// List of SPIFFE IDs of trust domains the registration entry is federated with
|
||||
federatesWith StringsFlag
|
||||
|
||||
// whether the registration entry is for an "admin" workload
|
||||
// Whether or not the registration entry is for an "admin" workload
|
||||
admin bool
|
||||
|
||||
// Expiry of entry
|
||||
|
@ -87,8 +89,9 @@ func (c *updateCommand) AppendFlags(f *flag.FlagSet) {
|
|||
f.StringVar(&c.entryID, "entryID", "", "The Registration Entry ID of the record to update")
|
||||
f.StringVar(&c.parentID, "parentID", "", "The SPIFFE ID of this record's parent")
|
||||
f.StringVar(&c.spiffeID, "spiffeID", "", "The SPIFFE ID that this record represents")
|
||||
f.IntVar(&c.x509SvidTTL, "x509SVIDTTL", 0, "The lifetime, in seconds, for x509-SVIDs issued based on this registration entry.")
|
||||
f.IntVar(&c.jwtSvidTTL, "jwtSVIDTTL", 0, "The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry.")
|
||||
f.IntVar(&c.ttl, "ttl", 0, "The lifetime, in seconds, for SVIDs issued based on this registration entry. This flag is deprecated in favor of x509SVIDTTL and jwtSVIDTTL and will be removed in a future version")
|
||||
f.IntVar(&c.x509SvidTTL, "x509SVIDTTL", 0, "The lifetime, in seconds, for x509-SVIDs issued based on this registration entry. Overrides ttl flag")
|
||||
f.IntVar(&c.jwtSvidTTL, "jwtSVIDTTL", 0, "The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry. Overrides ttl flag")
|
||||
f.StringVar(&c.path, "data", "", "Path to a file containing registration JSON (optional). If set to '-', read the JSON from stdin.")
|
||||
f.Var(&c.selectors, "selector", "A colon-delimited type:value selector. Can be used more than once")
|
||||
f.Var(&c.federatesWith, "federatesWith", "SPIFFE ID of a trust domain to federate with. Can be used more than once")
|
||||
|
@ -101,7 +104,7 @@ func (c *updateCommand) AppendFlags(f *flag.FlagSet) {
|
|||
cliprinter.AppendFlagWithCustomPretty(&c.printer, f, c.env, prettyPrintUpdate)
|
||||
}
|
||||
|
||||
func (c *updateCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient serverutil.ServerClient) error {
|
||||
func (c *updateCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient util.ServerClient) error {
|
||||
if err := c.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -149,6 +152,10 @@ func (c *updateCommand) validate() (err error) {
|
|||
return errors.New("a SPIFFE ID is required")
|
||||
}
|
||||
|
||||
if c.ttl < 0 {
|
||||
return errors.New("a positive TTL is required")
|
||||
}
|
||||
|
||||
if c.x509SvidTTL < 0 {
|
||||
return errors.New("a positive x509-SVID TTL is required")
|
||||
}
|
||||
|
@ -157,6 +164,10 @@ func (c *updateCommand) validate() (err error) {
|
|||
return errors.New("a positive JWT-SVID TTL is required")
|
||||
}
|
||||
|
||||
if c.ttl > 0 && (c.x509SvidTTL > 0 || c.jwtSvidTTL > 0) {
|
||||
return errors.New("use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -171,16 +182,6 @@ func (c *updateCommand) parseConfig() ([]*types.Entry, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
x509SvidTTL, err := util.CheckedCast[int32](c.x509SvidTTL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid value for X509 SVID TTL: %w", err)
|
||||
}
|
||||
|
||||
jwtSvidTTL, err := util.CheckedCast[int32](c.jwtSvidTTL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid value for JWT SVID TTL: %w", err)
|
||||
}
|
||||
|
||||
e := &types.Entry{
|
||||
Id: c.entryID,
|
||||
ParentId: parentID,
|
||||
|
@ -188,14 +189,26 @@ func (c *updateCommand) parseConfig() ([]*types.Entry, error) {
|
|||
Downstream: c.downstream,
|
||||
ExpiresAt: c.entryExpiry,
|
||||
DnsNames: c.dnsNames,
|
||||
X509SvidTtl: x509SvidTTL,
|
||||
JwtSvidTtl: jwtSvidTTL,
|
||||
X509SvidTtl: int32(c.x509SvidTTL),
|
||||
JwtSvidTtl: int32(c.jwtSvidTTL),
|
||||
Hint: c.hint,
|
||||
}
|
||||
|
||||
// c.ttl is deprecated but usable if the new c.x509Svid field is not used.
|
||||
// c.ttl should not be used to set the jwtSVIDTTL value because the previous
|
||||
// behavior was to have a hard-coded 5 minute JWT TTL no matter what the value
|
||||
// of ttl was set to.
|
||||
// validate(...) ensures that either the new fields or the deprecated field is
|
||||
// used, but never a mixture.
|
||||
//
|
||||
// https://github.com/spiffe/spire/issues/2700
|
||||
if e.X509SvidTtl == 0 {
|
||||
e.X509SvidTtl = int32(c.ttl)
|
||||
}
|
||||
|
||||
selectors := []*types.Selector{}
|
||||
for _, s := range c.selectors {
|
||||
cs, err := serverutil.ParseSelector(s)
|
||||
cs, err := util.ParseSelector(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -229,7 +242,7 @@ func updateEntries(ctx context.Context, c entryv1.EntryClient, entries []*types.
|
|||
return
|
||||
}
|
||||
|
||||
func prettyPrintUpdate(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintUpdate(env *commoncli.Env, results ...interface{}) error {
|
||||
var succeeded, failed []*entryv1.BatchUpdateEntryResponse_Result
|
||||
updateResp, ok := results[0].(*entryv1.BatchUpdateEntryResponse)
|
||||
if !ok {
|
||||
|
@ -252,7 +265,7 @@ func prettyPrintUpdate(env *commoncli.Env, results ...any) error {
|
|||
// Print entries that failed to be updated
|
||||
for _, r := range failed {
|
||||
env.ErrPrintf("Failed to update the following entry (code: %s, msg: %q):\n",
|
||||
util.MustCast[codes.Code](r.Status.Code),
|
||||
codes.Code(r.Status.Code),
|
||||
r.Status.Message)
|
||||
printEntry(r.Entry, env.ErrPrintf)
|
||||
}
|
||||
|
|
|
@ -321,6 +321,24 @@ func TestUpdate(t *testing.T) {
|
|||
JwtSvidTtl: 300,
|
||||
}
|
||||
|
||||
entry5 := &types.Entry{
|
||||
Id: "entry-id",
|
||||
SpiffeId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/workload"},
|
||||
ParentId: &types.SPIFFEID{TrustDomain: "example.org", Path: "/parent"},
|
||||
Selectors: []*types.Selector{
|
||||
{Type: "zebra", Value: "zebra:2000"},
|
||||
{Type: "alpha", Value: "alpha:2000"},
|
||||
},
|
||||
X509SvidTtl: 60,
|
||||
JwtSvidTtl: 0,
|
||||
FederatesWith: []string{"spiffe://domaina.test", "spiffe://domainb.test"},
|
||||
Admin: true,
|
||||
ExpiresAt: 1552410266,
|
||||
DnsNames: []string{"unu1000", "ung1000"},
|
||||
Downstream: true,
|
||||
Hint: "external",
|
||||
}
|
||||
|
||||
entry2Resp := proto.Clone(entry2).(*types.Entry)
|
||||
entry2Resp.CreatedAt = 1547583197
|
||||
entry3Resp := proto.Clone(entry3).(*types.Entry)
|
||||
|
@ -398,6 +416,30 @@ func TestUpdate(t *testing.T) {
|
|||
expErrPretty: "Error: selector \"unix\" must be formatted as type:value\n",
|
||||
expErrJSON: "Error: selector \"unix\" must be formatted as type:value\n",
|
||||
},
|
||||
{
|
||||
name: "Negative TTL",
|
||||
args: []string{"-entryID", "entry-id", "-selector", "unix", "-parentID", "spiffe://example.org/parent", "-spiffeID", "spiffe://example.org/workload", "-ttl", "-10"},
|
||||
expErrPretty: "Error: a positive TTL is required\n",
|
||||
expErrJSON: "Error: a positive TTL is required\n",
|
||||
},
|
||||
{
|
||||
name: "Invalid TTL and X509SvidTtl",
|
||||
args: []string{"-entryID", "entry-id", "-selector", "unix", "-parentID", "spiffe://example.org/parent", "-spiffeID", "spiffe://example.org/workload", "-ttl", "10", "-x509SVIDTTL", "20"},
|
||||
expErrPretty: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
expErrJSON: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
},
|
||||
{
|
||||
name: "Invalid TTL and JwtSvidTtl",
|
||||
args: []string{"-entryID", "entry-id", "-selector", "unix", "-parentID", "spiffe://example.org/parent", "-spiffeID", "spiffe://example.org/workload", "-ttl", "10", "-jwtSVIDTTL", "20"},
|
||||
expErrPretty: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
expErrJSON: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
},
|
||||
{
|
||||
name: "Invalid TTL and both X509SvidTtl and JwtSvidTtl",
|
||||
args: []string{"-entryID", "entry-id", "-selector", "unix", "-parentID", "spiffe://example.org/parent", "-spiffeID", "spiffe://example.org/workload", "-ttl", "10", "-x509SVIDTTL", "20", "-jwtSVIDTTL", "30"},
|
||||
expErrPretty: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
expErrJSON: "Error: use x509SVIDTTL and jwtSVIDTTL flags or the deprecated ttl flag\n",
|
||||
},
|
||||
{
|
||||
name: "Server error",
|
||||
args: []string{"-entryID", "entry-id", "-spiffeID", "spiffe://example.org/workload", "-parentID", "spiffe://example.org/parent", "-selector", "unix:uid:1"},
|
||||
|
@ -453,6 +495,58 @@ DNS name : ung1000
|
|||
Admin : true
|
||||
Hint : external
|
||||
|
||||
`, time.Unix(1552410266, 0).UTC()),
|
||||
expOutJSON: fmt.Sprintf(`{
|
||||
"results": [
|
||||
{
|
||||
"status": {
|
||||
"code": 0,
|
||||
"message": "OK"
|
||||
},
|
||||
"entry": %s
|
||||
}
|
||||
]
|
||||
}`, entry0AdminJSON),
|
||||
},
|
||||
{
|
||||
name: "Update succeeds using deprecated command line arguments",
|
||||
args: []string{
|
||||
"-entryID", "entry-id",
|
||||
"-spiffeID", "spiffe://example.org/workload",
|
||||
"-parentID", "spiffe://example.org/parent",
|
||||
"-selector", "zebra:zebra:2000",
|
||||
"-selector", "alpha:alpha:2000",
|
||||
"-ttl", "60",
|
||||
"-federatesWith", "spiffe://domaina.test",
|
||||
"-federatesWith", "spiffe://domainb.test",
|
||||
"-admin",
|
||||
"-entryExpiry", "1552410266",
|
||||
"-dns", "unu1000",
|
||||
"-dns", "ung1000",
|
||||
"-downstream",
|
||||
"-hint", "external",
|
||||
},
|
||||
expReq: &entryv1.BatchUpdateEntryRequest{
|
||||
Entries: []*types.Entry{entry5},
|
||||
},
|
||||
fakeResp: fakeRespOKFromCmd,
|
||||
expOutPretty: fmt.Sprintf(`Entry ID : entry-id
|
||||
SPIFFE ID : spiffe://example.org/workload
|
||||
Parent ID : spiffe://example.org/parent
|
||||
Revision : 0
|
||||
Downstream : true
|
||||
X509-SVID TTL : 60
|
||||
JWT-SVID TTL : 30
|
||||
Expiration time : %s
|
||||
Selector : zebra:zebra:2000
|
||||
Selector : alpha:alpha:2000
|
||||
FederatesWith : spiffe://domaina.test
|
||||
FederatesWith : spiffe://domainb.test
|
||||
DNS name : unu1000
|
||||
DNS name : ung1000
|
||||
Admin : true
|
||||
Hint : external
|
||||
|
||||
`, time.Unix(1552410266, 0).UTC()),
|
||||
expOutJSON: fmt.Sprintf(`{
|
||||
"results": [
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/spiffe/spire/proto/spire/common"
|
||||
)
|
||||
|
||||
func printEntry(e *types.Entry, printf func(string, ...any) error) {
|
||||
func printEntry(e *types.Entry, printf func(string, ...interface{}) error) {
|
||||
_ = printf("Entry ID : %s\n", printableEntryID(e.Id))
|
||||
_ = printf("SPIFFE ID : %s\n", protoToIDString(e.SpiffeId))
|
||||
_ = printf("Parent ID : %s\n", protoToIDString(e.ParentId))
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package entry
|
||||
|
||||
|
@ -21,7 +22,7 @@ const (
|
|||
-hint string
|
||||
The entry hint, used to disambiguate entries with the same SPIFFE ID
|
||||
-jwtSVIDTTL int
|
||||
The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry.
|
||||
The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry. Overrides ttl flag
|
||||
-node
|
||||
If set, this entry will be applied to matching nodes rather than workloads
|
||||
-output value
|
||||
|
@ -36,8 +37,10 @@ const (
|
|||
The SPIFFE ID that this record represents
|
||||
-storeSVID
|
||||
A boolean value that, when set, indicates that the resulting issued SVID from this entry must be stored through an SVIDStore plugin
|
||||
-ttl int
|
||||
The lifetime, in seconds, for SVIDs issued based on this registration entry. This flag is deprecated in favor of x509SVIDTTL and jwtSVIDTTL and will be removed in a future version
|
||||
-x509SVIDTTL int
|
||||
The lifetime, in seconds, for x509-SVIDs issued based on this registration entry.
|
||||
The lifetime, in seconds, for x509-SVIDs issued based on this registration entry. Overrides ttl flag
|
||||
`
|
||||
showUsage = `Usage of entry show:
|
||||
-downstream
|
||||
|
@ -81,7 +84,7 @@ const (
|
|||
-hint string
|
||||
The entry hint, used to disambiguate entries with the same SPIFFE ID
|
||||
-jwtSVIDTTL int
|
||||
The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry.
|
||||
The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry. Overrides ttl flag
|
||||
-output value
|
||||
Desired output format (pretty, json); default: pretty.
|
||||
-parentID string
|
||||
|
@ -94,8 +97,10 @@ const (
|
|||
The SPIFFE ID that this record represents
|
||||
-storeSVID
|
||||
A boolean value that, when set, indicates that the resulting issued SVID from this entry must be stored through an SVIDStore plugin
|
||||
-ttl int
|
||||
The lifetime, in seconds, for SVIDs issued based on this registration entry. This flag is deprecated in favor of x509SVIDTTL and jwtSVIDTTL and will be removed in a future version
|
||||
-x509SVIDTTL int
|
||||
The lifetime, in seconds, for x509-SVIDs issued based on this registration entry.
|
||||
The lifetime, in seconds, for x509-SVIDs issued based on this registration entry. Overrides ttl flag
|
||||
`
|
||||
deleteUsage = `Usage of entry delete:
|
||||
-entryID string
|
||||
|
@ -108,25 +113,9 @@ const (
|
|||
Path to the SPIRE Server API socket (default "/tmp/spire-server/private/api.sock")
|
||||
`
|
||||
countUsage = `Usage of entry count:
|
||||
-downstream
|
||||
A boolean value that, when set, indicates that the entry describes a downstream SPIRE server
|
||||
-federatesWith value
|
||||
SPIFFE ID of a trust domain an entry is federate with. Can be used more than once
|
||||
-hint string
|
||||
The Hint of the records to count (optional)
|
||||
-matchFederatesWithOn string
|
||||
The match mode used when filtering by federates with. Options: exact, any, superset and subset (default "superset")
|
||||
-matchSelectorsOn string
|
||||
The match mode used when filtering by selectors. Options: exact, any, superset and subset (default "superset")
|
||||
-output value
|
||||
Desired output format (pretty, json); default: pretty.
|
||||
-parentID string
|
||||
The Parent ID of the records to count
|
||||
-selector value
|
||||
A colon-delimited type:value selector. Can be used more than once
|
||||
-socketPath string
|
||||
Path to the SPIRE Server API socket (default "/tmp/spire-server/private/api.sock")
|
||||
-spiffeID string
|
||||
The SPIFFE ID of the records to count
|
||||
`
|
||||
)
|
||||
|
|
|
@ -2,7 +2,6 @@ package entry
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
@ -10,12 +9,13 @@ import (
|
|||
"github.com/mitchellh/cli"
|
||||
entryv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/entry/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/common"
|
||||
common_cli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/test/clitest"
|
||||
"github.com/spiffe/spire/test/spiretest"
|
||||
"github.com/spiffe/spire/test/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
|
@ -45,6 +45,7 @@ func TestParseEntryJSON(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
p := testCase.testDataPath
|
||||
|
||||
|
@ -154,7 +155,7 @@ func (e *entryTest) afterTest(t *testing.T) {
|
|||
}
|
||||
|
||||
func (e *entryTest) args(extra ...string) []string {
|
||||
return append([]string{clitest.AddrArg, e.addr}, extra...)
|
||||
return append([]string{common.AddrArg, e.addr}, extra...)
|
||||
}
|
||||
|
||||
type fakeEntryServer struct {
|
||||
|
@ -241,7 +242,7 @@ func setupTest(t *testing.T, newClient func(*common_cli.Env) cli.Command) *entry
|
|||
})
|
||||
|
||||
test := &entryTest{
|
||||
addr: clitest.GetAddr(addr),
|
||||
addr: common.GetAddr(addr),
|
||||
stdin: stdin,
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package entry
|
||||
|
||||
|
@ -21,7 +22,7 @@ const (
|
|||
-hint string
|
||||
The entry hint, used to disambiguate entries with the same SPIFFE ID
|
||||
-jwtSVIDTTL int
|
||||
The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry.
|
||||
The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry. Overrides ttl flag
|
||||
-namedPipeName string
|
||||
Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api")
|
||||
-node
|
||||
|
@ -36,8 +37,10 @@ const (
|
|||
The SPIFFE ID that this record represents
|
||||
-storeSVID
|
||||
A boolean value that, when set, indicates that the resulting issued SVID from this entry must be stored through an SVIDStore plugin
|
||||
-ttl int
|
||||
The lifetime, in seconds, for SVIDs issued based on this registration entry. This flag is deprecated in favor of x509SVIDTTL and jwtSVIDTTL and will be removed in a future version
|
||||
-x509SVIDTTL int
|
||||
The lifetime, in seconds, for x509-SVIDs issued based on this registration entry.
|
||||
The lifetime, in seconds, for x509-SVIDs issued based on this registration entry. Overrides ttl flag
|
||||
`
|
||||
showUsage = `Usage of entry show:
|
||||
-downstream
|
||||
|
@ -81,7 +84,7 @@ const (
|
|||
-hint string
|
||||
The entry hint, used to disambiguate entries with the same SPIFFE ID
|
||||
-jwtSVIDTTL int
|
||||
The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry.
|
||||
The lifetime, in seconds, for JWT-SVIDs issued based on this registration entry. Overrides ttl flag
|
||||
-namedPipeName string
|
||||
Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api")
|
||||
-output value
|
||||
|
@ -94,8 +97,10 @@ const (
|
|||
The SPIFFE ID that this record represents
|
||||
-storeSVID
|
||||
A boolean value that, when set, indicates that the resulting issued SVID from this entry must be stored through an SVIDStore plugin
|
||||
-ttl int
|
||||
The lifetime, in seconds, for SVIDs issued based on this registration entry. This flag is deprecated in favor of x509SVIDTTL and jwtSVIDTTL and will be removed in a future version
|
||||
-x509SVIDTTL int
|
||||
The lifetime, in seconds, for x509-SVIDs issued based on this registration entry.
|
||||
The lifetime, in seconds, for x509-SVIDs issued based on this registration entry. Overrides ttl flag
|
||||
`
|
||||
deleteUsage = `Usage of entry delete:
|
||||
-entryID string
|
||||
|
@ -108,25 +113,9 @@ const (
|
|||
Desired output format (pretty, json); default: pretty.
|
||||
`
|
||||
countUsage = `Usage of entry count:
|
||||
-downstream
|
||||
A boolean value that, when set, indicates that the entry describes a downstream SPIRE server
|
||||
-federatesWith value
|
||||
SPIFFE ID of a trust domain an entry is federate with. Can be used more than once
|
||||
-hint string
|
||||
The Hint of the records to count (optional)
|
||||
-matchFederatesWithOn string
|
||||
The match mode used when filtering by federates with. Options: exact, any, superset and subset (default "superset")
|
||||
-matchSelectorsOn string
|
||||
The match mode used when filtering by selectors. Options: exact, any, superset and subset (default "superset")
|
||||
-namedPipeName string
|
||||
Pipe name of the SPIRE Server API named pipe (default "\\spire-server\\private\\api")
|
||||
-output value
|
||||
Desired output format (pretty, json); default: pretty.
|
||||
-parentID string
|
||||
The Parent ID of the records to count
|
||||
-selector value
|
||||
A colon-delimited type:value selector. Can be used more than once
|
||||
-spiffeID string
|
||||
The SPIFFE ID of the records to count
|
||||
`
|
||||
)
|
||||
|
|
|
@ -170,7 +170,7 @@ func bundleFromRawMessage(raw json.RawMessage, bundleFormat string, endpointTrus
|
|||
return util.ParseBundle(bundle, bundleFormat, endpointTrustDomain)
|
||||
}
|
||||
|
||||
func printFederationRelationship(fr *types.FederationRelationship, printf func(format string, args ...any) error) {
|
||||
func printFederationRelationship(fr *types.FederationRelationship, printf func(format string, args ...interface{}) error) {
|
||||
_ = printf("Trust domain : %s\n", fr.TrustDomain)
|
||||
_ = printf("Bundle endpoint URL : %s\n", fr.BundleEndpointUrl)
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ import (
|
|||
"github.com/spiffe/go-spiffe/v2/spiffeid"
|
||||
trustdomainv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/trustdomain/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/common"
|
||||
common_cli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/pemutil"
|
||||
"github.com/spiffe/spire/test/clitest"
|
||||
"github.com/spiffe/spire/test/fakes/fakeserverca"
|
||||
"github.com/spiffe/spire/test/spiretest"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -124,7 +124,7 @@ func (c *cmdTest) afterTest(t *testing.T) {
|
|||
}
|
||||
|
||||
func (c *cmdTest) args(extra ...string) []string {
|
||||
return append([]string{clitest.AddrArg, c.addr}, extra...)
|
||||
return append([]string{common.AddrArg, c.addr}, extra...)
|
||||
}
|
||||
|
||||
type fakeServer struct {
|
||||
|
@ -222,7 +222,7 @@ func setupTest(t *testing.T, newClient func(*common_cli.Env) cli.Command) *cmdTe
|
|||
})
|
||||
|
||||
test := &cmdTest{
|
||||
addr: clitest.GetAddr(addr),
|
||||
addr: common.GetAddr(addr),
|
||||
stdin: stdin,
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
|
@ -241,7 +241,7 @@ func createBundle(t *testing.T, trustDomain string) (*types.Bundle, string) {
|
|||
td := spiffeid.RequireTrustDomainFromString(trustDomain)
|
||||
bundlePath := path.Join(t.TempDir(), "bundle.pem")
|
||||
ca := fakeserverca.New(t, td, &fakeserverca.Options{})
|
||||
require.NoError(t, os.WriteFile(bundlePath, pemutil.EncodeCertificates(ca.Bundle()), 0o600))
|
||||
require.NoError(t, os.WriteFile(bundlePath, pemutil.EncodeCertificates(ca.Bundle()), 0600))
|
||||
|
||||
return &types.Bundle{
|
||||
TrustDomain: td.Name(),
|
||||
|
@ -253,13 +253,13 @@ func createBundle(t *testing.T, trustDomain string) (*types.Bundle, string) {
|
|||
|
||||
func createCorruptedBundle(t *testing.T) string {
|
||||
bundlePath := path.Join(t.TempDir(), "bundle.pem")
|
||||
require.NoError(t, os.WriteFile(bundlePath, []byte("corrupted-bundle"), 0o600))
|
||||
require.NoError(t, os.WriteFile(bundlePath, []byte("corrupted-bundle"), 0600))
|
||||
return bundlePath
|
||||
}
|
||||
|
||||
func createJSONDataFile(t *testing.T, data string) string {
|
||||
jsonDataFilePath := path.Join(t.TempDir(), "bundle.pem")
|
||||
require.NoError(t, os.WriteFile(jsonDataFilePath, []byte(data), 0o600))
|
||||
require.NoError(t, os.WriteFile(jsonDataFilePath, []byte(data), 0600))
|
||||
return jsonDataFilePath
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,9 @@ import (
|
|||
"github.com/mitchellh/cli"
|
||||
trustdomainv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/trustdomain/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
serverutil "github.com/spiffe/spire/cmd/spire-server/util"
|
||||
"github.com/spiffe/spire/cmd/spire-server/util"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"github.com/spiffe/spire/pkg/common/util"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
|
@ -27,7 +26,7 @@ func NewCreateCommand() cli.Command {
|
|||
}
|
||||
|
||||
func newCreateCommand(env *commoncli.Env) cli.Command {
|
||||
return serverutil.AdaptCommand(env, &createCommand{env: env})
|
||||
return util.AdaptCommand(env, &createCommand{env: env})
|
||||
}
|
||||
|
||||
type createCommand struct {
|
||||
|
@ -53,7 +52,7 @@ func (c *createCommand) AppendFlags(f *flag.FlagSet) {
|
|||
cliprinter.AppendFlagWithCustomPretty(&c.printer, f, c.env, c.prettyPrintCreate)
|
||||
}
|
||||
|
||||
func (c *createCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient serverutil.ServerClient) error {
|
||||
func (c *createCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient util.ServerClient) error {
|
||||
federationRelationships, err := getRelationships(c.config, c.path)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -72,7 +71,7 @@ func (c *createCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient
|
|||
return c.printer.PrintProto(resp)
|
||||
}
|
||||
|
||||
func (c *createCommand) prettyPrintCreate(env *commoncli.Env, results ...any) error {
|
||||
func (c *createCommand) prettyPrintCreate(env *commoncli.Env, results ...interface{}) error {
|
||||
createResp, ok := results[0].(*trustdomainv1.BatchCreateFederationRelationshipResponse)
|
||||
if !ok || len(c.federationRelationships) < len(createResp.Results) {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
@ -102,7 +101,7 @@ func (c *createCommand) prettyPrintCreate(env *commoncli.Env, results ...any) er
|
|||
for _, r := range failed {
|
||||
env.Println()
|
||||
env.ErrPrintf("Failed to create the following federation relationship (code: %s, msg: %q):\n",
|
||||
util.MustCast[codes.Code](r.Status.Code),
|
||||
codes.Code(r.Status.Code),
|
||||
r.Status.Message)
|
||||
printFederationRelationship(r.FederationRelationship, env.ErrPrintf)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
func TestCreateHelp(t *testing.T) {
|
||||
func TestCreatetHelp(t *testing.T) {
|
||||
test := setupTest(t, newCreateCommand)
|
||||
test.client.Help()
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ func (c *deleteCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient
|
|||
return c.printer.PrintProto(resp)
|
||||
}
|
||||
|
||||
func prettyPrintDelete(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintDelete(env *commoncli.Env, results ...interface{}) error {
|
||||
if deleteResp, ok := results[0].(*trustdomain.BatchDeleteFederationRelationshipResponse); ok && len(deleteResp.Results) > 0 {
|
||||
result := deleteResp.Results[0]
|
||||
switch result.Status.Code {
|
||||
|
|
|
@ -47,7 +47,7 @@ func (c *listCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient ut
|
|||
return c.printer.PrintProto(resp)
|
||||
}
|
||||
|
||||
func prettyPrintList(env *commoncli.Env, results ...any) error {
|
||||
func prettyPrintList(env *commoncli.Env, results ...interface{}) error {
|
||||
listResp, ok := results[0].(*trustdomainv1.ListFederationRelationshipsResponse)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
|
|
@ -63,6 +63,6 @@ func (c *refreshCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient
|
|||
}
|
||||
}
|
||||
|
||||
func prettyPrintRefresh(env *commoncli.Env, _ ...any) error {
|
||||
func prettyPrintRefresh(env *commoncli.Env, _ ...interface{}) error {
|
||||
return env.Println("Bundle refreshed")
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ func (c *showCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient ut
|
|||
return c.printer.PrintProto(fr)
|
||||
}
|
||||
|
||||
func (c *showCommand) prettyPrintShow(env *commoncli.Env, results ...any) error {
|
||||
func (c *showCommand) prettyPrintShow(env *commoncli.Env, results ...interface{}) error {
|
||||
fr, ok := results[0].(*prototypes.FederationRelationship)
|
||||
if !ok {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
|
|
@ -9,10 +9,9 @@ import (
|
|||
"github.com/mitchellh/cli"
|
||||
trustdomainv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/trustdomain/v1"
|
||||
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
|
||||
serverutil "github.com/spiffe/spire/cmd/spire-server/util"
|
||||
"github.com/spiffe/spire/cmd/spire-server/util"
|
||||
commoncli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/pkg/common/cliprinter"
|
||||
"github.com/spiffe/spire/pkg/common/util"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
|
@ -22,7 +21,7 @@ func NewUpdateCommand() cli.Command {
|
|||
}
|
||||
|
||||
func newUpdateCommand(env *commoncli.Env) cli.Command {
|
||||
return serverutil.AdaptCommand(env, &updateCommand{env: env})
|
||||
return util.AdaptCommand(env, &updateCommand{env: env})
|
||||
}
|
||||
|
||||
type updateCommand struct {
|
||||
|
@ -48,7 +47,7 @@ func (c *updateCommand) AppendFlags(f *flag.FlagSet) {
|
|||
cliprinter.AppendFlagWithCustomPretty(&c.printer, f, c.env, c.prettyPrintUpdate)
|
||||
}
|
||||
|
||||
func (c *updateCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient serverutil.ServerClient) error {
|
||||
func (c *updateCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient util.ServerClient) error {
|
||||
federationRelationships, err := getRelationships(c.config, c.path)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -67,7 +66,7 @@ func (c *updateCommand) Run(ctx context.Context, _ *commoncli.Env, serverClient
|
|||
return c.printer.PrintProto(resp)
|
||||
}
|
||||
|
||||
func (c *updateCommand) prettyPrintUpdate(env *commoncli.Env, results ...any) error {
|
||||
func (c *updateCommand) prettyPrintUpdate(env *commoncli.Env, results ...interface{}) error {
|
||||
updateResp, ok := results[0].(*trustdomainv1.BatchUpdateFederationRelationshipResponse)
|
||||
if !ok || len(c.federationRelationships) < len(updateResp.Results) {
|
||||
return cliprinter.ErrInternalCustomPrettyFunc
|
||||
|
@ -98,7 +97,7 @@ func (c *updateCommand) prettyPrintUpdate(env *commoncli.Env, results ...any) er
|
|||
for _, r := range failed {
|
||||
env.Println()
|
||||
env.ErrPrintf("Failed to update the following federation relationship (code: %s, msg: %q):\n",
|
||||
util.MustCast[codes.Code](r.Status.Code),
|
||||
codes.Code(r.Status.Code),
|
||||
r.Status.Message)
|
||||
printFederationRelationship(r.FederationRelationship, env.ErrPrintf)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package federation
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package federation
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package healthcheck
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/spiffe/spire/cmd/spire-server/cli/common"
|
||||
common_cli "github.com/spiffe/spire/pkg/common/cli"
|
||||
"github.com/spiffe/spire/test/clitest"
|
||||
"github.com/spiffe/spire/test/spiretest"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"google.golang.org/grpc"
|
||||
|
@ -58,24 +58,24 @@ func (s *HealthCheckSuite) TestBadFlags() {
|
|||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestFailsIfEndpointDoesNotExist() {
|
||||
code := s.cmd.Run([]string{clitest.AddrArg, clitest.AddrValue})
|
||||
code := s.cmd.Run([]string{common.AddrArg, common.AddrValue})
|
||||
s.NotEqual(0, code, "exit code")
|
||||
s.Equal("", s.stdout.String(), "stdout")
|
||||
spiretest.AssertHasPrefix(s.T(), s.stderr.String(), "Error: server is unhealthy: unable to determine health\n")
|
||||
spiretest.AssertHasPrefix(s.T(), s.stderr.String(), common.AddrError)
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestFailsIfEndpointDoesNotExistVerbose() {
|
||||
code := s.cmd.Run([]string{clitest.AddrArg, clitest.AddrValue, "-verbose"})
|
||||
code := s.cmd.Run([]string{common.AddrArg, common.AddrValue, "-verbose"})
|
||||
s.NotEqual(0, code, "exit code")
|
||||
s.Equal("Checking server health...\n", s.stdout.String(), "stdout")
|
||||
spiretest.AssertHasPrefix(s.T(), s.stderr.String(), "Failed to check health: "+clitest.AddrError)
|
||||
s.Equal("", s.stdout.String(), "stdout")
|
||||
spiretest.AssertHasPrefix(s.T(), s.stderr.String(), common.AddrError)
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestSucceedsIfServingStatusServing() {
|
||||
addr := spiretest.StartGRPCServer(s.T(), func(srv *grpc.Server) {
|
||||
grpc_health_v1.RegisterHealthServer(srv, withStatus(grpc_health_v1.HealthCheckResponse_SERVING))
|
||||
})
|
||||
code := s.cmd.Run([]string{clitest.AddrArg, clitest.GetAddr(addr)})
|
||||
code := s.cmd.Run([]string{common.AddrArg, common.GetAddr(addr)})
|
||||
s.Equal(0, code, "exit code")
|
||||
s.Equal("Server is healthy.\n", s.stdout.String(), "stdout")
|
||||
s.Equal("", s.stderr.String(), "stderr")
|
||||
|
@ -85,7 +85,7 @@ func (s *HealthCheckSuite) TestSucceedsIfServingStatusServingVerbose() {
|
|||
addr := spiretest.StartGRPCServer(s.T(), func(srv *grpc.Server) {
|
||||
grpc_health_v1.RegisterHealthServer(srv, withStatus(grpc_health_v1.HealthCheckResponse_SERVING))
|
||||
})
|
||||
code := s.cmd.Run([]string{clitest.AddrArg, clitest.GetAddr(addr), "-verbose"})
|
||||
code := s.cmd.Run([]string{common.AddrArg, common.GetAddr(addr), "-verbose"})
|
||||
s.Equal(0, code, "exit code")
|
||||
s.Equal(`Checking server health...
|
||||
Server is healthy.
|
||||
|
@ -97,7 +97,7 @@ func (s *HealthCheckSuite) TestFailsIfServiceStatusOther() {
|
|||
addr := spiretest.StartGRPCServer(s.T(), func(srv *grpc.Server) {
|
||||
grpc_health_v1.RegisterHealthServer(srv, withStatus(grpc_health_v1.HealthCheckResponse_NOT_SERVING))
|
||||
})
|
||||
code := s.cmd.Run([]string{clitest.AddrArg, clitest.GetAddr(addr), "-verbose"})
|
||||
code := s.cmd.Run([]string{common.AddrArg, common.GetAddr(addr), "-verbose"})
|
||||
s.NotEqual(0, code, "exit code")
|
||||
s.Equal(`Checking server health...
|
||||
`, s.stdout.String(), "stdout")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package healthcheck
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue