Skip to content

Commit

Permalink
feat: Implement multi provider support (bank-vaults#59)
Browse files Browse the repository at this point in the history
* feat(multi-provider support): Implement multi-provider support, adjust tests

Signed-off-by: Bence Csati <[email protected]>

* fix(e2e): Adjust e2e tests

Signed-off-by: Bence Csati <[email protected]>

* chore(README): e2e

Signed-off-by: Bence Csati <[email protected]>

* fix(e2e): put back single-provider tests

Signed-off-by: Bence Csati <[email protected]>

* fix(env_store.go): fix remarks

Signed-off-by: Bence Csati <[email protected]>

* chore: minor fixes

Signed-off-by: Bence Csati <[email protected]>

* chore: naming

Signed-off-by: Bence Csati <[email protected]>

---------

Signed-off-by: Bence Csati <[email protected]>
Signed-off-by: Bence Csati <[email protected]>
  • Loading branch information
csatib02 committed Feb 15, 2024
1 parent 457bce6 commit c414d9e
Show file tree
Hide file tree
Showing 14 changed files with 485 additions and 210 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Run the test suite:

```shell
make test
make test-e2e
```

Run linters:
Expand Down
2 changes: 0 additions & 2 deletions common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ type Config struct {
LogServer string `json:"log_server"`
Daemon bool `json:"daemon"`
Delay time.Duration `json:"delay"`
Provider string `json:"provider"`
}

func LoadConfig() (*Config, error) {
Expand All @@ -46,6 +45,5 @@ func LoadConfig() (*Config, error) {
LogServer: os.Getenv(LogServerEnv),
Daemon: cast.ToBool(os.Getenv(DaemonEnv)),
Delay: cast.ToDuration(os.Getenv(DelayEnv)),
Provider: os.Getenv(ProviderEnv),
}, nil
}
8 changes: 1 addition & 7 deletions common/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,12 @@ func TestConfig(t *testing.T) {
JSONLogEnv: "true",
LogServerEnv: "",
DaemonEnv: "true",
ProviderEnv: "vault",
},
wantConfig: &Config{
LogLevel: "debug",
JSONLog: true,
LogServer: "",
Daemon: true,
Provider: "vault",
},
},
}
Expand All @@ -52,16 +50,12 @@ func TestConfig(t *testing.T) {
for envKey, envVal := range ttp.env {
os.Setenv(envKey, envVal)
}
defer os.Clearenv()

config, err := LoadConfig()
assert.Nil(t, err, "Unexpected error")

assert.Equal(t, ttp.wantConfig, config, "Unexpected config")

// unset envs for the next test
for envKey := range ttp.env {
os.Unsetenv(envKey)
}
})
}
}
34 changes: 22 additions & 12 deletions e2e/file-provider.bats
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,40 @@ 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"
setup_file_provider() {
add_secret_file

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

export FILE_SECRET="file:$TMPFILE_SECRET"
}

add_secret_file() {
TMPFILE_SECRET=$(mktemp)
printf "secret-value" > "$TMPFILE_SECRET"
}

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

@test "secret successfully loaded" {
run_output=$(./secret-init env | grep Secret)
assert_output_contains() {
local expected=$1
local output=$2

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

@test "secret successfully loaded from file" {
setup_file_provider

run_output=$(./secret-init env | grep FILE_SECRET)
assert_success
expected_output="Secret=secret-value"

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

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

run go build
assert_success
}

setup_file_provider() {
add_secret_file

export FILE_MOUNT_PATH="/"

export FILE_SECRET="file:$TMPFILE_SECRET"
}

add_secret_file() {
TMPFILE_SECRET=$(mktemp)
printf "secret-value" > "$TMPFILE_SECRET"
}

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

export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN_FILE="$TMPFILE_TOKEN"

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

start_vault
}

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
}

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
}

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
}

teardown() {
stop_vault

rm -f "$TMPFILE_SECRET"
rm -f "$TMPFILE_TOKEN"
rm -f secret-init
}

stop_vault() {
remove_secrets_from_vault
docker compose down
}

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" {
setup_file_provider

setup_vault_provider
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\|FILE_SECRET')
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"
assert_output_contains "FILE_SECRET=secret-value" "$run_output"
}

@test "secrets successfully loaded using vault:login as token" {
setup_file_provider

setup_vault_provider
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\|FILE_SECRET')
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"
assert_output_contains "FILE_SECRET=secret-value" "$run_output"
}

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

setup_vault_provider
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\|FILE_SECRET')
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"
assert_output_contains "FILE_SECRET=secret-value" "$run_output"

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

@test "secrets successfully loaded 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

setup_file_provider

setup_vault_provider
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\|FILE_SECRET')
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"
assert_output_contains "FILE_SECRET=secret-value" "$run_output"
}
47 changes: 24 additions & 23 deletions e2e/vault-provider.bats
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,24 @@ setup() {
bats_load_library bats-support
bats_load_library bats-assert

start_vault

setup_pod

run go build
assert_success
}

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

export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN_FILE="$TMPFILE_TOKEN"

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

start_vault
}

start_vault() {
docker compose up -d

Expand All @@ -26,19 +36,6 @@ start_vault() {
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"
Expand All @@ -53,10 +50,15 @@ add_secrets_to_vault() {
docker exec "$vault_container_name" vault kv put secret/test/aws AWS_ACCESS_KEY_ID=secretId AWS_SECRET_ACCESS_KEY=s3cr3t
}

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
}

teardown() {
stop_vault

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

Expand All @@ -65,11 +67,6 @@ stop_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
Expand All @@ -89,6 +86,7 @@ check_process_status() {


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

Expand All @@ -101,6 +99,7 @@ check_process_status() {
}

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

Expand All @@ -113,6 +112,7 @@ check_process_status() {
}

@test "secrets successfully loaded from vault using vault:login as token and daemon mode enabled" {
setup_vault_provider
set_vault_token "vault:login"
set_daemon_mode
add_secrets_to_vault
Expand All @@ -135,6 +135,7 @@ check_process_status() {
unset AWS_SECRET_ACCESS_KEY
unset AWS_ACCESS_KEY_ID

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

0 comments on commit c414d9e

Please sign in to comment.