From ffa05ae43cd38f4033fa639f09a5568a8b7deb99 Mon Sep 17 00:00:00 2001
From: Michal Baumgartner <michal.baumgartner@ataccama.com>
Date: Sun, 15 Dec 2024 21:13:52 +0100
Subject: [PATCH] Fix authentication configuration options

(cherry picked from commit 3be92deff6f190a9213a6e1ee0762c2eb9d85017)
---
 Makefile                   |  6 +++++-
 cluster/test/setup-auth.sh | 38 ++++++++++++++++++++++++++++++++++++++
 cluster/test/setup.sh      | 23 +++++++++++++++++++++++
 internal/clients/vault.go  | 17 ++++++++++++-----
 4 files changed, 78 insertions(+), 6 deletions(-)
 create mode 100755 cluster/test/setup-auth.sh

diff --git a/Makefile b/Makefile
index af8cd7b..efda481 100644
--- a/Makefile
+++ b/Makefile
@@ -170,7 +170,11 @@ vault.uninstall:
 	@$(KUBECTL) delete secret vault-auto-unseal-keys --ignore-not-found
 	@$(OK) uninstalled vault
 
-.PHONY: uptest e2e cobertura submodules fallthrough run crds.clean vault.uninstall
+vault.token:
+	@$(KUBECTL) get secret -n vault vault-creds --template='{{ .data.credentials | base64decode }}' | jq -r '.token'
+
+.PHONY: uptest e2e cobertura submodules fallthrough run crds.clean 
+.PHONY: vault.uninstall vault.token
 
 # ====================================================================================
 # Special Targets
diff --git a/cluster/test/setup-auth.sh b/cluster/test/setup-auth.sh
new file mode 100755
index 0000000..c17c34c
--- /dev/null
+++ b/cluster/test/setup-auth.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+set -euo pipefail
+
+VAULT_TOKEN=$(make vault.token)
+export VAULT_TOKEN
+
+# requires Vault to be port-forwarded
+VAULT_ADDR="http://127.0.0.1:8200"
+export VAULT_ADDR
+
+if vault auth list | grep -q "approle"; then
+    echo "Approle auth method already enabled"
+else
+    echo "Enabling approle auth method"
+    vault auth enable approle
+fi
+
+echo "Creating development admin policy"
+curl \
+  --request POST \
+  --header "X-Vault-Token: $VAULT_TOKEN" \
+  --data '{"policy": "path \"*\" { capabilities = [\"create\", \"read\", \"update\", \"delete\", \"list\", \"sudo\"] }"}' \
+  "$VAULT_ADDR/v1/sys/policy/dev-admin"
+
+echo "Creating AppRole role my-role"
+vault write auth/approle/role/my-role \
+    token_type=batch \
+    token_max_ttl=10m \
+    bind_secret_id=false \
+    secret_id_bound_cidrs="0.0.0.0/0" \
+    token_bound_cidrs="0.0.0.0/0" \
+    token_policies="dev-admin"
+
+vault write auth/approle/role/my-role/role-id \
+    role_id=my-role
+
+echo "Authentication set up!"
diff --git a/cluster/test/setup.sh b/cluster/test/setup.sh
index 7cf476d..3a292b8 100755
--- a/cluster/test/setup.sh
+++ b/cluster/test/setup.sh
@@ -96,6 +96,13 @@ metadata:
 type: Opaque
 stringData:
   credentials: '{"token": "$VAULT_ROOT_TOKEN"}'
+  appRoleCredentials: |
+    {
+      "auth_login": {
+        "path": "auth/approle/login",
+        "parameters": {"role_id": "my-role"}
+      }
+    }
 EOF
 
 echo_info "Applying providerconfig"
@@ -116,3 +123,19 @@ spec:
       name: vault-creds
       key: credentials
 EOF
+cat <<EOF | ${KUBECTL} apply -f -
+apiVersion: vault.upbound.io/v1beta1
+kind: ProviderConfig
+metadata:
+  name: vault-provider-config-approle
+spec:
+  address: http://$VAULT_0_POD_IP:8200
+  skip_child_token: true
+  skip_tls_verify: true
+  credentials:
+    source: Secret
+    secretRef:
+      namespace: vault
+      name: vault-creds
+      key: appRoleCredentials
+EOF
diff --git a/internal/clients/vault.go b/internal/clients/vault.go
index 5029e98..1c412d5 100644
--- a/internal/clients/vault.go
+++ b/internal/clients/vault.go
@@ -125,17 +125,24 @@ func TerraformSetupBuilder(tfProvider *schema.Provider) terraform.SetupFn {
 
 		// Set credentials in Terraform
 		// provider configuration
-		credsKeys := [...]string{keyToken, keyTokenName, keyCaCertFile,
-			keyCaCertDir, keyAuthLoginUserpass, keyAuthLoginAWS,
+		credsKeys := [...]string{keyToken, keyTokenName, keyCaCertFile, keyCaCertDir}
+		for _, key := range credsKeys {
+			if v, ok := creds[key]; ok {
+				ps.Configuration[key] = v
+			}
+		}
+		// structured auth methods need to be wrapped in a single element array
+		// see: https://registry.terraform.io/providers/hashicorp/vault/latest/docs#vault-authentication-configuration-options
+		authKeys := [...]string{keyAuthLoginUserpass, keyAuthLoginAWS,
 			keyAuthLoginCert, keyAuthLoginGCP, keyAuthLoginKerberos,
 			keyAuthLoginRadius, keyAuthLoginOCI, keyAuthLoginOIDC,
 			keyAuthLoginJWT, keyAuthLoginAzure, keyAuthLogin, keyClientAuth}
-
-		for _, key := range credsKeys {
+		for _, key := range authKeys {
 			if v, ok := creds[key]; ok {
-				ps.Configuration[key] = v
+				ps.Configuration[key] = []interface{}{v}
 			}
 		}
+
 		return ps, errors.Wrap(
 			configureNoForkVaultClient(ctx, &ps, *tfProvider),
 			"failed to configure the no-fork Vault client",