mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-14 11:03:09 +02:00
a1988f6808
* Add GH issue creation + SARIF * Code cleanup * Fix fmt, add debug * Code enhancements * Fix * Added debug info * Rework UA log scan * Fix code * read UA version * Fix nil reference * Extraction * Credentials * Issue creation * Error handling * Fix issue creation * query escape * Query escape 2 * Revert * Test avoid update * HTTP client * Add support for custom TLS certs * Fix code * Fix code 2 * Fix code 3 * Disable cert check * Fix auth * Remove implicit trust * Skip verification * Fix * Fix client * Fix HTTP auth * Fix trusted certs * Trim version * Code * Add token * Added token handling to client * Fix token * Cleanup * Fix token * Token rework * Fix code * Kick out oauth client * Kick out oauth client * Transport wrapping * Token * Simplification * Refactor * Variation * Check * Fix * Debug * Switch client * Variation * Debug * Switch to cert check * Add debug * Parse self * Cleanup * Update resources/metadata/whitesourceExecuteScan.yaml * Add debug * Expose subjects * Patch * Debug * Debug2 * Debug3 * Fix logging response body * Cleanup * Cleanup * Fix request body logging * Cleanup import * Fix import cycle * Cleanup * Fix fmt * Fix NopCloser reference * Regenerate * Reintroduce * Fix test * Fix tests * Correction * Fix error * Code fix * Fix tests * Add tests * Fix code climate issues * Code climate * Code climate again * Code climate again * Fix fmt * Fix fmt 2 Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com>
326 lines
9.4 KiB
Go
326 lines
9.4 KiB
Go
//go:build integration
|
|
// +build integration
|
|
|
|
// can be execute with go test -tags=integration ./integration/...
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/SAP/jenkins-library/pkg/vault"
|
|
"github.com/hashicorp/vault/api"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/testcontainers/testcontainers-go"
|
|
"github.com/testcontainers/testcontainers-go/wait"
|
|
)
|
|
|
|
type SecretData = map[string]interface{}
|
|
|
|
func TestGetVaultSecret(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := context.Background()
|
|
const testToken = "vault-token"
|
|
|
|
req := testcontainers.GenericContainerRequest{
|
|
ContainerRequest: testcontainers.ContainerRequest{
|
|
AlwaysPullImage: true,
|
|
Image: "vault:1.4.3",
|
|
ExposedPorts: []string{"8200/tcp"},
|
|
Env: map[string]string{"VAULT_DEV_ROOT_TOKEN_ID": testToken},
|
|
WaitingFor: wait.ForLog("Vault server started!").WithStartupTimeout(20 * time.Second)},
|
|
|
|
Started: true,
|
|
}
|
|
|
|
vaultContainer, err := testcontainers.GenericContainer(ctx, req)
|
|
assert.NoError(t, err)
|
|
defer vaultContainer.Terminate(ctx)
|
|
|
|
ip, err := vaultContainer.Host(ctx)
|
|
assert.NoError(t, err)
|
|
port, err := vaultContainer.MappedPort(ctx, "8200")
|
|
host := fmt.Sprintf("http://%s:%s", ip, port.Port())
|
|
config := &vault.Config{Config: &api.Config{Address: host}}
|
|
// setup vault for testing
|
|
secretData := SecretData{
|
|
"key1": "value1",
|
|
"key2": "value2",
|
|
}
|
|
setupVault(t, config, testToken, secretData)
|
|
|
|
client, err := vault.NewClient(config, testToken)
|
|
assert.NoError(t, err)
|
|
secret, err := client.GetKvSecret("secret/test")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "value1", secret["key1"])
|
|
assert.Equal(t, "value2", secret["key2"])
|
|
|
|
secret, err = client.GetKvSecret("kv/test")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "value1", secret["key1"])
|
|
assert.Equal(t, "value2", secret["key2"])
|
|
|
|
}
|
|
|
|
func TestWriteVaultSecret(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := context.Background()
|
|
const testToken = "vault-token"
|
|
|
|
req := testcontainers.GenericContainerRequest{
|
|
ContainerRequest: testcontainers.ContainerRequest{
|
|
AlwaysPullImage: true,
|
|
Image: "vault:1.4.3",
|
|
ExposedPorts: []string{"8200/tcp"},
|
|
Env: map[string]string{"VAULT_DEV_ROOT_TOKEN_ID": testToken},
|
|
WaitingFor: wait.ForLog("Vault server started!").WithStartupTimeout(20 * time.Second)},
|
|
|
|
Started: true,
|
|
}
|
|
|
|
vaultContainer, err := testcontainers.GenericContainer(ctx, req)
|
|
assert.NoError(t, err)
|
|
defer vaultContainer.Terminate(ctx)
|
|
|
|
ip, err := vaultContainer.Host(ctx)
|
|
assert.NoError(t, err)
|
|
port, err := vaultContainer.MappedPort(ctx, "8200")
|
|
host := fmt.Sprintf("http://%s:%s", ip, port.Port())
|
|
config := &vault.Config{Config: &api.Config{Address: host}}
|
|
// setup vault for testing
|
|
secretData := map[string]string{
|
|
"key1": "value1",
|
|
"key2": "value2",
|
|
}
|
|
|
|
client, err := vault.NewClient(config, testToken)
|
|
assert.NoError(t, err)
|
|
|
|
err = client.WriteKvSecret("secret/test", secretData)
|
|
assert.NoError(t, err)
|
|
|
|
secret, err := client.GetKvSecret("secret/test")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "value1", secret["key1"])
|
|
assert.Equal(t, "value2", secret["key2"])
|
|
|
|
// enabling KV engine 1
|
|
vaultClient, err := api.NewClient(config.Config)
|
|
assert.NoError(t, err)
|
|
vaultClient.SetToken(testToken)
|
|
_, err = vaultClient.Logical().Write("sys/mounts/kv", SecretData{
|
|
"path": "kv",
|
|
"type": "kv",
|
|
"options": SecretData{
|
|
"version": "1",
|
|
},
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
err = client.WriteKvSecret("secret/test1", secretData)
|
|
assert.NoError(t, err)
|
|
|
|
secret, err = client.GetKvSecret("secret/test1")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "value1", secret["key1"])
|
|
assert.Equal(t, "value2", secret["key2"])
|
|
}
|
|
|
|
func TestVaultAppRole(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := context.Background()
|
|
const testToken = "vault-token"
|
|
const appRolePath = "auth/approle/role/test"
|
|
const appRoleName = "test"
|
|
|
|
req := testcontainers.GenericContainerRequest{
|
|
ContainerRequest: testcontainers.ContainerRequest{
|
|
AlwaysPullImage: true,
|
|
Image: "vault:1.4.3",
|
|
ExposedPorts: []string{"8200/tcp"},
|
|
Env: map[string]string{"VAULT_DEV_ROOT_TOKEN_ID": testToken},
|
|
WaitingFor: wait.ForLog("Vault server started!").WithStartupTimeout(20 * time.Second)},
|
|
|
|
Started: true,
|
|
}
|
|
|
|
vaultContainer, err := testcontainers.GenericContainer(ctx, req)
|
|
assert.NoError(t, err)
|
|
defer vaultContainer.Terminate(ctx)
|
|
|
|
ip, err := vaultContainer.Host(ctx)
|
|
assert.NoError(t, err)
|
|
port, err := vaultContainer.MappedPort(ctx, "8200")
|
|
host := fmt.Sprintf("http://%s:%s", ip, port.Port())
|
|
config := &vault.Config{Config: &api.Config{Address: host}}
|
|
|
|
secretIDMetadata := map[string]interface{}{
|
|
"field1": "value1",
|
|
}
|
|
|
|
roleID, secretID := setupVaultAppRole(t, config, testToken, appRolePath, secretIDMetadata)
|
|
|
|
t.Run("Test Vault AppRole login", func(t *testing.T) {
|
|
client, err := vault.NewClientWithAppRole(config, roleID, secretID)
|
|
assert.NoError(t, err)
|
|
secret, err := client.GetSecret("auth/token/lookup-self")
|
|
meta := secret.Data["meta"].(SecretData)
|
|
assert.Equal(t, meta["field1"], "value1")
|
|
assert.Equal(t, meta["role_name"], "test")
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
t.Run("Test Vault AppRoleTTL Fetch", func(t *testing.T) {
|
|
client, err := vault.NewClient(config, testToken)
|
|
assert.NoError(t, err)
|
|
ttl, err := client.GetAppRoleSecretIDTtl(secretID, appRoleName)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, time.Duration(90*24*time.Hour), ttl.Round(time.Hour))
|
|
})
|
|
|
|
t.Run("Test Vault AppRole Rotation", func(t *testing.T) {
|
|
client, err := vault.NewClient(config, testToken)
|
|
assert.NoError(t, err)
|
|
newSecretID, err := client.GenerateNewAppRoleSecret(secretID, appRoleName)
|
|
assert.NoError(t, err)
|
|
assert.NotEmpty(t, newSecretID)
|
|
assert.NotEqual(t, secretID, newSecretID)
|
|
|
|
// verify metadata is not broken
|
|
client, err = vault.NewClientWithAppRole(config, roleID, newSecretID)
|
|
assert.NoError(t, err)
|
|
secret, err := client.GetSecret("auth/token/lookup-self")
|
|
meta := secret.Data["meta"].(SecretData)
|
|
assert.Equal(t, meta["field1"], "value1")
|
|
assert.Equal(t, meta["role_name"], "test")
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
t.Run("Test Fetching RoleName from vault", func(t *testing.T) {
|
|
client, err := vault.NewClientWithAppRole(config, roleID, secretID)
|
|
assert.NoError(t, err)
|
|
fetchedRoleName, err := client.GetAppRoleName()
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, appRoleName, fetchedRoleName)
|
|
})
|
|
}
|
|
|
|
func TestTokenRevocation(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := context.Background()
|
|
const testToken = "vault-token"
|
|
const appRolePath = "auth/approle/role/test"
|
|
const appRoleName = "test"
|
|
|
|
req := testcontainers.GenericContainerRequest{
|
|
ContainerRequest: testcontainers.ContainerRequest{
|
|
AlwaysPullImage: true,
|
|
Image: "vault:1.4.3",
|
|
ExposedPorts: []string{"8200/tcp"},
|
|
Env: map[string]string{"VAULT_DEV_ROOT_TOKEN_ID": testToken},
|
|
WaitingFor: wait.ForLog("Vault server started!").WithStartupTimeout(20 * time.Second)},
|
|
|
|
Started: true,
|
|
}
|
|
|
|
vaultContainer, err := testcontainers.GenericContainer(ctx, req)
|
|
assert.NoError(t, err)
|
|
defer vaultContainer.Terminate(ctx)
|
|
|
|
ip, err := vaultContainer.Host(ctx)
|
|
assert.NoError(t, err)
|
|
port, err := vaultContainer.MappedPort(ctx, "8200")
|
|
host := fmt.Sprintf("http://%s:%s", ip, port.Port())
|
|
config := &vault.Config{Config: &api.Config{Address: host}}
|
|
|
|
secretIDMetadata := map[string]interface{}{
|
|
"field1": "value1",
|
|
}
|
|
|
|
roleID, secretID := setupVaultAppRole(t, config, testToken, appRolePath, secretIDMetadata)
|
|
|
|
t.Run("Test Revocation works", func(t *testing.T) {
|
|
client, err := vault.NewClientWithAppRole(config, roleID, secretID)
|
|
assert.NoError(t, err)
|
|
secret, err := client.GetSecret("auth/token/lookup-self")
|
|
meta := secret.Data["meta"].(SecretData)
|
|
assert.Equal(t, meta["field1"], "value1")
|
|
assert.Equal(t, meta["role_name"], "test")
|
|
assert.NoError(t, err)
|
|
|
|
err = client.RevokeToken()
|
|
assert.NoError(t, err)
|
|
|
|
_, err = client.GetSecret("auth/token/lookup-self")
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func setupVaultAppRole(t *testing.T, config *vault.Config, token, appRolePath string, metadata map[string]interface{}) (string, string) {
|
|
t.Helper()
|
|
client, err := api.NewClient(config.Config)
|
|
assert.NoError(t, err)
|
|
client.SetToken(token)
|
|
lClient := client.Logical()
|
|
|
|
_, err = lClient.Write("sys/auth/approle", SecretData{
|
|
"type": "approle",
|
|
"config": map[string]interface{}{
|
|
"default_lease_ttl": "7776000s",
|
|
"max_lease_ttl": "7776000s",
|
|
},
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = lClient.Write("auth/approle/role/test", SecretData{
|
|
"secret_id_ttl": 7776000,
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
metadataJson, err := json.Marshal(metadata)
|
|
assert.NoError(t, err)
|
|
|
|
res, err := lClient.Write("auth/approle/role/test/secret-id", SecretData{
|
|
"metadata": string(metadataJson),
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
secretID := res.Data["secret_id"]
|
|
|
|
res, err = lClient.Read("auth/approle/role/test/role-id")
|
|
assert.NoError(t, err)
|
|
roleID := res.Data["role_id"]
|
|
|
|
return roleID.(string), secretID.(string)
|
|
}
|
|
|
|
func setupVault(t *testing.T, config *vault.Config, token string, secret SecretData) {
|
|
t.Helper()
|
|
client, err := api.NewClient(config.Config)
|
|
assert.NoError(t, err)
|
|
client.SetToken(token)
|
|
|
|
_, err = client.Logical().Write("secret/data/test", SecretData{"data": secret})
|
|
assert.NoError(t, err)
|
|
|
|
// enabling KV engine 1
|
|
_, err = client.Logical().Write("sys/mounts/kv", SecretData{
|
|
"path": "kv",
|
|
"type": "kv",
|
|
"options": SecretData{
|
|
"version": "1",
|
|
},
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = client.Logical().Write("kv/test", secret)
|
|
assert.NoError(t, err)
|
|
|
|
}
|