Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add e2e tests #51

Merged
merged 9 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ jobs:
vault:
image: hashicorp/vault:${{ matrix.vault_version }}
env:
SKIP_SETCAP: true
SKIP_SETCAP: "true"
VAULT_ADDR: http://127.0.0.1:8200
VAULT_TOKEN: 227e1cce-6bf7-30bb-2d2a-acc854318caf
VAULT_DEV_ROOT_TOKEN_ID: 227e1cce-6bf7-30bb-2d2a-acc854318caf
ports:
- 8200:8200
Expand Down Expand Up @@ -215,3 +217,52 @@ jobs:

- name: Dependency Review
uses: actions/dependency-review-action@4901385134134e04cec5fbe5ddfe3b2c5bd5d976 # v4.0.0

e2e-test:
name: E2E test
runs-on: ubuntu-latest
strategy:
matrix:
vault_version: ["1.11.12", "1.12.8", "1.13.4", "1.14.1"]

services:
vault:
image: hashicorp/vault:${{ matrix.vault_version }}
env:
SKIP_SETCAP: "true"
VAULT_ADDR: http://127.0.0.1:8200
VAULT_TOKEN: 227e1cce-6bf7-30bb-2d2a-acc854318caf
VAULT_DEV_ROOT_TOKEN_ID: 227e1cce-6bf7-30bb-2d2a-acc854318caf
ports:
- 8200:8200

steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Set up Nix
uses: cachix/install-nix-action@7ac1ec25491415c381d9b62f0657c7a028df52a7 # v24
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}

- name: Set up magic Nix cache
uses: DeterminateSystems/magic-nix-cache-action@8a218f9e264e9c3803c9a1ee1c30d8e4ab55be63 # v2

- name: Set up Go cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ github.job }}-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ github.job }}-${{ runner.os }}-go-

- name: Prepare Nix shell
run: nix develop --impure .#ci

- name: Test
run: nix develop --impure .#ci -c make test-e2e
env:
VAULT_VERSION: ${{ matrix.vault_version }}
69 changes: 57 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,21 @@ export PATH := $(abspath bin/):${PATH}
# Dependency versions
GOLANGCI_VERSION = 1.53.3
LICENSEI_VERSION = 0.8.0
GORELEASER_VERSION = 1.18.2
COSIGN_VERSION = 2.2.2
GORELEASER_VERSION = 1.23.0
BATS_VERSION = 1.2.1

##@ General

# Targets commented with ## will be visible in "make help" info.
# Comments marked with ##@ will be used as categories for a group of targets.

.PHONY: help
.DEFAULT_GOAL := help
help: ## Display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

##@ Development

.PHONY: up
up: ## Start development environment
Expand All @@ -19,6 +33,8 @@ stop: ## Stop development environment
down: ## Destroy development environment
docker compose down -v

##@ Build

.PHONY: build
build: ## Build binary
@mkdir -p build
Expand All @@ -34,7 +50,9 @@ container-image: ## Build container image

.PHONY: binary-snapshot
binary-snapshot: ## Build binary snapshot
goreleaser release --rm-dist --skip-publish --snapshot
VERSION=v${GORELEASER_VERSION} goreleaser release --clean --skip=publish --snapshot

##@ Checks

.PHONY: check
check: test lint ## Run checks (tests and linters)
Expand All @@ -43,6 +61,11 @@ check: test lint ## Run checks (tests and linters)
test: ## Run tests
go test -race -v ./...

.PHONY: test-e2e
test-e2e: ## Run e2e tests
@export BATS_LIB_PATH=${PWD}/bin/bats-core/libexec/bats-core/lib && \
bats e2e
csatib02 marked this conversation as resolved.
Show resolved Hide resolved

.PHONY: lint
lint: lint-go lint-docker lint-yaml
lint: ## Run linters
Expand All @@ -68,7 +91,9 @@ license-check: ## Run license check
licensei check
licensei header

deps: bin/golangci-lint bin/licensei bin/goreleaser
##@ Dependencies

deps: bin/golangci-lint bin/licensei bin/cosign bin/goreleaser bin/bats
deps: ## Install dependencies

bin/golangci-lint:
Expand All @@ -79,14 +104,34 @@ bin/licensei:
@mkdir -p bin
curl -sfL https://raw.githubusercontent.com/goph/licensei/master/install.sh | bash -s -- v${LICENSEI_VERSION}

bin/goreleaser:
bin/cosign:
@mkdir -p bin
@mkdir -p tmpgoreleaser
curl -sfL https://goreleaser.com/static/run | VERSION=v${GORELEASER_VERSION} TMPDIR=${PWD}/tmpgoreleaser bash -s -- --version
mv tmpgoreleaser/goreleaser bin/
@rm -rf tmpgoreleaser
@OS=$$(uname -s); \
case $$OS in \
"Linux") \
curl -sSfL https://github.com/sigstore/cosign/releases/download/v${COSIGN_VERSION}/cosign-linux-amd64 -o bin/cosign; \
;; \
"Darwin") \
curl -sSfL https://github.com/sigstore/cosign/releases/download/v${COSIGN_VERSION}/cosign-darwin-arm64 -o bin/cosign; \
;; \
*) \
echo "Unsupported OS: $$OS"; \
exit 1; \
;; \
esac
@chmod +x bin/cosign

.PHONY: help
.DEFAULT_GOAL := help
help:
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-10s\033[0m %s\n", $$1, $$2}'
bin/goreleaser:
@mkdir -p bin
curl -sfL https://goreleaser.com/static/run -o bin/goreleaser
@chmod +x bin/goreleaser

bin/bats:
@mkdir -p bin/bats-core
@mkdir -p tmpbats
git clone https://github.com/bats-core/bats-core.git tmpbats
bash tmpbats/install.sh bin/bats-core
@ln -sF ${PWD}/bin/bats-core/bin/bats ${PWD}/bin
@rm -rf tmpbats
git clone https://github.com/bats-core/bats-support.git bin/bats-core/libexec/bats-core/lib/bats-support
git clone https://github.com/bats-core/bats-assert.git bin/bats-core/libexec/bats-core/lib/bats-assert
5 changes: 4 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ version: "3.9"

services:
vault:
container_name: vault
image: hashicorp/vault:1.14.1
ports:
- 127.0.0.1:8200:8200
environment:
SKIP_SETCAP: true
SKIP_SETCAP: "true"
VAULT_ADDR: http://127.0.0.1:8200
VAULT_TOKEN: 227e1cce-6bf7-30bb-2d2a-acc854318caf
VAULT_DEV_ROOT_TOKEN_ID: 227e1cce-6bf7-30bb-2d2a-acc854318caf
31 changes: 31 additions & 0 deletions e2e/file-provider.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
setup() {
bats_load_library bats-support
bats_load_library bats-assert

setup_pod

run go build
assert_success
}

setup_pod() {
TMPFILE=$(mktemp)
printf "secret-value" > "$TMPFILE"

export SECRET_INIT_PROVIDER="file"
export FILE_MOUNT_PATH="/"
export Secret="file:$TMPFILE"
}

teardown() {
rm -f "$TMPFILE"
rm -f secret-init
}

@test "secret successfully loaded" {
run_output=$(./secret-init env | grep Secret)
assert_success
expected_output="Secret=secret-value"

assert_equal "$run_output" "$expected_output"
}
148 changes: 148 additions & 0 deletions e2e/vault-provider.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
vault_container_name="vault"

setup() {
bats_load_library bats-support
bats_load_library bats-assert

start_vault

setup_pod

run go build
assert_success
}

start_vault() {
docker compose up -d

# wait for Vault to be ready
max_attempts=${MAX_ATTEMPTS:-10}

for ((attempts = 0; attempts < max_attempts; attempts++)); do
if docker compose exec -T "$vault_container_name" vault status > /dev/null 2>&1; then
break
fi
sleep 1
done
}

setup_pod() {
TMPFILE=$(mktemp)
printf "227e1cce-6bf7-30bb-2d2a-acc854318caf" > "$TMPFILE"

export SECRET_INIT_PROVIDER="vault"
export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN_FILE="$TMPFILE"

export MYSQL_PASSWORD=vault:secret/data/test/mysql#MYSQL_PASSWORD
export AWS_SECRET_ACCESS_KEY=vault:secret/data/test/aws#AWS_SECRET_ACCESS_KEY
export AWS_ACCESS_KEY_ID=vault:secret/data/test/aws#AWS_ACCESS_KEY_ID
}

set_vault_token() {
local token=$1
export VAULT_TOKEN="$token"
}

set_daemon_mode() {
export SECRET_INIT_DAEMON="true"
}

add_secrets_to_vault() {
docker exec "$vault_container_name" vault kv put secret/test/mysql MYSQL_PASSWORD=3xtr3ms3cr3t
docker exec "$vault_container_name" vault kv put secret/test/aws AWS_ACCESS_KEY_ID=secretId AWS_SECRET_ACCESS_KEY=s3cr3t
}

teardown() {
stop_vault

rm -f "$TMPFILE"
rm -f secret-init
}

stop_vault() {
remove_secrets_from_vault
docker compose down
}

remove_secrets_from_vault() {
docker exec "$vault_container_name" vault kv delete secret/test/mysql
docker exec "$vault_container_name" vault kv delete secret/test/aws
}

assert_output_contains() {
local expected=$1
local output=$2

echo "$output" | grep -qF "$expected" || fail "Expected line not found: $expected"
}

check_process_status() {
local process_name="$1"

if pgrep -f "$process_name" > /dev/null; then
echo "Process is running"
else
echo "Process is not running"
fi
}


@test "secrets successfully loaded from vault" {
set_vault_token 227e1cce-6bf7-30bb-2d2a-acc854318caf
add_secrets_to_vault

run_output=$(./secret-init env | grep 'MYSQL_PASSWORD\|AWS_SECRET_ACCESS_KEY\|AWS_ACCESS_KEY_ID')
assert_success

assert_output_contains "MYSQL_PASSWORD=3xtr3ms3cr3t" "$run_output"
assert_output_contains "AWS_SECRET_ACCESS_KEY=s3cr3t" "$run_output"
assert_output_contains "AWS_ACCESS_KEY_ID=secretId" "$run_output"
}

@test "secrets successfully loaded from vault using vault:login as token" {
set_vault_token "vault:login"
add_secrets_to_vault

run_output=$(./secret-init env | grep 'MYSQL_PASSWORD\|AWS_SECRET_ACCESS_KEY\|AWS_ACCESS_KEY_ID')
assert_success

assert_output_contains "MYSQL_PASSWORD=3xtr3ms3cr3t" "$run_output"
assert_output_contains "AWS_SECRET_ACCESS_KEY=s3cr3t" "$run_output"
assert_output_contains "AWS_ACCESS_KEY_ID=secretId" "$run_output"
}

@test "secrets successfully loaded from vault using vault:login as token and daemon mode enabled" {
set_vault_token "vault:login"
set_daemon_mode
add_secrets_to_vault

run_output=$(./secret-init env | grep 'MYSQL_PASSWORD\|AWS_SECRET_ACCESS_KEY\|AWS_ACCESS_KEY_ID')
assert_success

assert_output_contains "MYSQL_PASSWORD=3xtr3ms3cr3t" "$run_output"
assert_output_contains "AWS_SECRET_ACCESS_KEY=s3cr3t" "$run_output"
assert_output_contains "AWS_ACCESS_KEY_ID=secretId" "$run_output"

# Check if the process is still running in the background
check_process_status "secret-init env"
assert_success
}

@test "secrets successfully loaded from vault using VAULT_FROM_PATH" {
# unset env vars to ensure secret-init will utilize VAULT_FROM_PATH
unset MYSQL_PASSWORD
unset AWS_SECRET_ACCESS_KEY
unset AWS_ACCESS_KEY_ID

set_vault_token 227e1cce-6bf7-30bb-2d2a-acc854318caf
add_secrets_to_vault
export VAULT_FROM_PATH="secret/data/test/mysql,secret/data/test/aws"

run_output=$(./secret-init env | grep 'MYSQL_PASSWORD\|AWS_SECRET_ACCESS_KEY\|AWS_ACCESS_KEY_ID')
assert_success

assert_output_contains "MYSQL_PASSWORD=3xtr3ms3cr3t" "$run_output"
assert_output_contains "AWS_SECRET_ACCESS_KEY=s3cr3t" "$run_output"
assert_output_contains "AWS_ACCESS_KEY_ID=secretId" "$run_output"
}
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
gnumake

# golangci-lint
(bats.withLibraries (p: [ p.bats-support p.bats-assert ]))
goreleaser

# TODO: remove once https://github.com/NixOS/nixpkgs/pull/254878 hits unstable
Expand Down
5 changes: 2 additions & 3 deletions provider/vault/vault_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,8 @@ func TestNewProvider(t *testing.T) {
func setupTestLogger() {
originalLogger = slog.Default()

// Redirect logs to avoid polluting the test output
handler := slog.NewTextHandler(io.Discard, nil)
testLogger := slog.New(handler)
// Discard logs to avoid polluting the test output
testLogger := slog.New(slog.NewTextHandler(io.Discard, nil))
slog.SetDefault(testLogger)
}

Expand Down
Loading