chore: clean up vault process
This commit is contained in:
parent
fc904df7f0
commit
93f37bc9b6
2
main.go
2
main.go
|
|
@ -89,7 +89,7 @@ func runInitRepo(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
|
||||
func runCreateDockerSecret(cmd *cobra.Command, args []string) {
|
||||
if err := createDockerRegistrySecret(); err != nil {
|
||||
if err := createAndStoreSecrets(); err != nil {
|
||||
fmt.Printf("[ERROR] Failed to create Docker registry secret: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
|||
470
vault.go
470
vault.go
|
|
@ -13,6 +13,22 @@ import (
|
|||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
// --- Constants for Vault and Kubernetes ---
|
||||
const (
|
||||
vaultNamespace = "vault"
|
||||
vaultPodLabelSelector = "app.kubernetes.io/name=vault"
|
||||
vaultRootTokenSecretName = "vault-unseal-keys"
|
||||
vaultRootTokenSecretKey = "vault-root"
|
||||
ghcrSecretPath = "secret/ghcr-auth"
|
||||
orgManagementSecretPath = "secret/org-management-pat"
|
||||
dockerConfigJSONKey = ".dockerconfigjson"
|
||||
orgManagementPATKey = "ORG_MANAGEMENT_PAT"
|
||||
ghcrRegistry = "ghcr.io"
|
||||
defaultVaultAddress = "https://127.0.0.1:8200"
|
||||
)
|
||||
|
||||
// --- Structs for Docker Config ---
|
||||
|
||||
// DockerConfig represents the structure of a Docker config.json
|
||||
type DockerConfig struct {
|
||||
Auths map[string]DockerAuth `json:"auths"`
|
||||
|
|
@ -25,327 +41,245 @@ type DockerAuth struct {
|
|||
Auth string `json:"auth"`
|
||||
}
|
||||
|
||||
// VaultSecret represents the structure for storing in Vault
|
||||
type VaultSecret struct {
|
||||
DockerConfigJSON string `json:".dockerconfigjson"`
|
||||
// --- VaultManager to Encapsulate Logic ---
|
||||
|
||||
// VaultManager handles all interactions with Kubernetes and Vault.
|
||||
type VaultManager struct {
|
||||
podName string
|
||||
rootToken string
|
||||
}
|
||||
|
||||
// OrgManagementSecret represents the organization management PAT secret
|
||||
type OrgManagementSecret struct {
|
||||
OrgManagementPAT string `json:"ORG_MANAGEMENT_PAT"`
|
||||
}
|
||||
// NewVaultManager creates and initializes a new VaultManager.
|
||||
func NewVaultManager() (*VaultManager, error) {
|
||||
vm := &VaultManager{}
|
||||
|
||||
// createDockerRegistrySecret creates a Docker registry secret in Vault
|
||||
func createDockerRegistrySecret() error {
|
||||
// Check dependencies
|
||||
fmt.Println("[INFO] Checking dependencies (kubectl and vault)...")
|
||||
fmt.Println("[INFO] Checking dependencies (kubectl)...")
|
||||
if !commandExists("kubectl") {
|
||||
return fmt.Errorf("'kubectl' must be installed and in your PATH")
|
||||
return nil, fmt.Errorf("'kubectl' must be installed and in your PATH")
|
||||
}
|
||||
|
||||
// Check kubectl context
|
||||
fmt.Println("[INFO] Checking Kubernetes context...")
|
||||
if err := runCommandQuiet("kubectl", "get", "nodes"); err != nil {
|
||||
return fmt.Errorf("unable to connect to Kubernetes cluster. Please check your kubectl configuration")
|
||||
}
|
||||
|
||||
// Check if vault namespace exists
|
||||
fmt.Println("[INFO] Checking if 'vault' namespace exists...")
|
||||
if err := runCommandQuiet("kubectl", "get", "namespace", "vault"); err != nil {
|
||||
fmt.Println("[WARNING] 'vault' namespace does not exist. Please ensure Vault is properly installed in your cluster.")
|
||||
return fmt.Errorf("vault namespace not found")
|
||||
}
|
||||
|
||||
// Get user input
|
||||
username, token, orgToken, err := getUserInput()
|
||||
fmt.Println("[INFO] Finding Vault pod...")
|
||||
podName, err := vm.getVaultPodName()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get user input: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
vm.podName = podName
|
||||
fmt.Printf("[INFO] Using Vault pod: %s\n", vm.podName)
|
||||
|
||||
// Create Docker config
|
||||
dockerConfig, err := createDockerConfig(username, token)
|
||||
fmt.Println("[INFO] Retrieving Vault root token...")
|
||||
rootToken, err := vm.getVaultRootToken()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create Docker config: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
vm.rootToken = rootToken
|
||||
fmt.Println("[SUCCESS] Found Vault root token.")
|
||||
|
||||
fmt.Println("[INFO] Verifying Vault connection and token...")
|
||||
if err := vm.verifyVaultToken(); err != nil {
|
||||
return nil, fmt.Errorf("failed to validate Vault token: %w", err)
|
||||
}
|
||||
fmt.Println("[SUCCESS] Vault token is valid.")
|
||||
|
||||
return vm, nil
|
||||
}
|
||||
|
||||
// Store Docker registry secret in Vault
|
||||
fmt.Println("[INFO] Storing Docker registry secret in Vault...")
|
||||
if err := storeInVault(dockerConfig); err != nil {
|
||||
return fmt.Errorf("failed to store Docker registry secret in Vault: %v", err)
|
||||
// getVaultPodName finds a running Vault pod in the cluster.
|
||||
func (vm *VaultManager) getVaultPodName() (string, error) {
|
||||
// Use `runCommandQuiet` to check for the existence of common pod names.
|
||||
commonNames := []string{"vault-0", "vault-1", "vault-2"}
|
||||
for _, name := range commonNames {
|
||||
if err := runCommandQuiet("kubectl", "get", "pod", name, "-n", vaultNamespace); err == nil {
|
||||
return name, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Store organization management PAT in Vault
|
||||
fmt.Println("[INFO] Storing organization management PAT in Vault...")
|
||||
if err := storeOrgManagementPAT(orgToken); err != nil {
|
||||
return fmt.Errorf("failed to store organization management PAT in Vault: %v", err)
|
||||
// For getting the name via label, we MUST capture the command's output,
|
||||
// so we use exec.Command().Output() directly.
|
||||
cmd := exec.Command("kubectl", "get", "pods", "-n", vaultNamespace, "-l", vaultPodLabelSelector, "-o", "jsonpath={.items[0].metadata.name}")
|
||||
output, err := cmd.Output()
|
||||
if err == nil && len(output) > 0 {
|
||||
return string(output), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("could not find any running Vault pods in the '%s' namespace", vaultNamespace)
|
||||
}
|
||||
|
||||
// getVaultRootToken retrieves the Vault root token from the Kubernetes secret.
|
||||
func (vm *VaultManager) getVaultRootToken() (string, error) {
|
||||
// We need to capture the secret data from stdout, so we must use exec.Command().Output().
|
||||
// The utility functions in utils.go do not support this.
|
||||
cmd := exec.Command("kubectl", "get", "secret", vaultRootTokenSecretName, "-n", vaultNamespace, "-o", fmt.Sprintf("jsonpath={.data.%s}", vaultRootTokenSecretKey))
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get '%s' secret from '%s' namespace: %w", vaultRootTokenSecretName, vaultNamespace, err)
|
||||
}
|
||||
|
||||
if len(output) == 0 {
|
||||
return "", fmt.Errorf("key '%s' not found in secret '%s'", vaultRootTokenSecretKey, vaultRootTokenSecretName)
|
||||
}
|
||||
|
||||
decoded, err := base64.StdEncoding.DecodeString(string(output))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decode base64 root token: %w", err)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(decoded)), nil
|
||||
}
|
||||
|
||||
// runVaultCommand executes a command inside the Vault pod using the `runCommand` utility.
|
||||
func (vm *VaultManager) runVaultCommand(command string) error {
|
||||
envSetup := fmt.Sprintf("export VAULT_SKIP_VERIFY=true && export VAULT_ADDR='%s' && export VAULT_TOKEN='%s'", defaultVaultAddress, vm.rootToken)
|
||||
fullCmd := fmt.Sprintf("%s && %s", envSetup, command)
|
||||
|
||||
// Use the runCommand utility to show command output to the user.
|
||||
return runCommand("kubectl", "exec", "-n", vaultNamespace, vm.podName, "--", "sh", "-c", fullCmd)
|
||||
}
|
||||
|
||||
// verifyVaultToken checks if the root token is valid.
|
||||
func (vm *VaultManager) verifyVaultToken() error {
|
||||
return vm.runVaultCommand("vault token lookup")
|
||||
}
|
||||
|
||||
// StoreSecret stores a key-value secret at the specified path in Vault.
|
||||
func (vm *VaultManager) StoreSecret(path string, data map[string]string) error {
|
||||
fmt.Printf("[INFO] Storing secret in Vault at path: %s...\n", path)
|
||||
|
||||
var kvPairs []string
|
||||
for key, value := range data {
|
||||
// Escape single quotes for shell command robustness.
|
||||
escapedValue := strings.ReplaceAll(value, "'", "'\"'\"'")
|
||||
kvPairs = append(kvPairs, fmt.Sprintf("%s='%s'", key, escapedValue))
|
||||
}
|
||||
|
||||
vaultCmd := fmt.Sprintf("vault kv put %s %s", path, strings.Join(kvPairs, " "))
|
||||
if err := vm.runVaultCommand(vaultCmd); err != nil {
|
||||
return fmt.Errorf("failed to store secret in Vault: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("[INFO] Verifying secret storage...")
|
||||
verifyCmd := fmt.Sprintf("vault kv get %s", path)
|
||||
if err := vm.runVaultCommand(verifyCmd); err != nil {
|
||||
fmt.Printf("[WARNING] Could not verify secret storage at '%s', but it may have been created successfully.\n", path)
|
||||
} else {
|
||||
fmt.Printf("[SUCCESS] Secret at '%s' stored and verified in Vault!\n", path)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getUserInput prompts the user for their GitHub username, registry token, and organization management token
|
||||
func getUserInput() (string, string, string, error) {
|
||||
// --- Main Workflow Function ---
|
||||
func createAndStoreSecrets() error {
|
||||
// 1. Get User Input
|
||||
username, registryToken, orgToken, err := getUserInput()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. Initialize Vault Manager
|
||||
// This handles kubectl checks, pod discovery, and token retrieval.
|
||||
vm, err := NewVaultManager()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize Vault manager: %w", err)
|
||||
}
|
||||
|
||||
// 3. Create and Store Docker Registry Secret
|
||||
dockerConfigJSON, err := createDockerConfig(username, registryToken)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create Docker config: %w", err)
|
||||
}
|
||||
|
||||
dockerSecretData := map[string]string{dockerConfigJSONKey: dockerConfigJSON}
|
||||
if err := vm.StoreSecret(ghcrSecretPath, dockerSecretData); err != nil {
|
||||
return fmt.Errorf("failed to store Docker registry secret: %w", err)
|
||||
}
|
||||
|
||||
// 4. Create and Store Organization Management PAT
|
||||
orgSecretData := map[string]string{orgManagementPATKey: orgToken}
|
||||
if err := vm.StoreSecret(orgManagementSecretPath, orgSecretData); err != nil {
|
||||
return fmt.Errorf("failed to store organization management PAT: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// --- User Input and Helper Functions ---
|
||||
func getUserInput() (username, registryToken, orgToken string, err error) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
// Get username
|
||||
fmt.Print("Enter your GitHub username: ")
|
||||
username, err := reader.ReadString('\n')
|
||||
username, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
return
|
||||
}
|
||||
username = strings.TrimSpace(username)
|
||||
|
||||
if username == "" {
|
||||
return "", "", "", fmt.Errorf("username cannot be empty")
|
||||
err = fmt.Errorf("username cannot be empty")
|
||||
return
|
||||
}
|
||||
|
||||
// Get registry token (hidden input)
|
||||
fmt.Print("Enter your GitHub personal access token for container registry: ")
|
||||
tokenBytes, err := term.ReadPassword(int(syscall.Stdin))
|
||||
registryToken, err = promptForToken(reader, "Enter your GitHub personal access token for container registry")
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
return
|
||||
}
|
||||
|
||||
orgToken, err = promptForToken(reader, "Enter your GitHub personal access token for organization management")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// promptForToken provides a generic way to ask for a token with validation.
|
||||
func promptForToken(reader *bufio.Reader, prompt string) (string, error) {
|
||||
fmt.Printf("%s: ", prompt)
|
||||
tokenBytes, err := term.ReadPassword(int(syscall.Stdin))
|
||||
fmt.Println()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fmt.Println() // Print newline after hidden input
|
||||
|
||||
token := string(tokenBytes)
|
||||
if token == "" {
|
||||
return "", "", "", fmt.Errorf("registry token cannot be empty")
|
||||
return "", fmt.Errorf("token cannot be empty")
|
||||
}
|
||||
|
||||
// Validate registry token format
|
||||
if !strings.HasPrefix(token, "ghp_") && !strings.HasPrefix(token, "gho_") &&
|
||||
!strings.HasPrefix(token, "ghu_") && !strings.HasPrefix(token, "ghs_") &&
|
||||
!strings.HasPrefix(token, "ghr_") {
|
||||
fmt.Println("[WARNING] The registry token doesn't appear to be a GitHub personal access token (should start with ghp_, gho_, ghu_, ghs_, or ghr_)")
|
||||
validPrefixes := []string{"ghp_", "gho_", "ghu_", "ghs_", "ghr_", "github_pat_"}
|
||||
hasValidPrefix := false
|
||||
for _, prefix := range validPrefixes {
|
||||
if strings.HasPrefix(token, prefix) {
|
||||
hasValidPrefix = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasValidPrefix {
|
||||
fmt.Printf("[WARNING] The token does not appear to be a valid GitHub personal access token (should start with one of %v)\n", validPrefixes)
|
||||
fmt.Print("Do you want to continue anyway? (y/N): ")
|
||||
|
||||
confirm, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
confirm = strings.TrimSpace(strings.ToLower(confirm))
|
||||
|
||||
if confirm != "y" && confirm != "yes" {
|
||||
return "", "", "", fmt.Errorf("operation cancelled by user")
|
||||
confirm, _ := reader.ReadString('\n')
|
||||
if strings.TrimSpace(strings.ToLower(confirm)) != "y" {
|
||||
return "", fmt.Errorf("operation cancelled by user")
|
||||
}
|
||||
}
|
||||
|
||||
// Get organization management token (hidden input)
|
||||
fmt.Print("Enter your GitHub personal access token for organization management: ")
|
||||
orgTokenBytes, err := term.ReadPassword(int(syscall.Stdin))
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
fmt.Println() // Print newline after hidden input
|
||||
|
||||
orgToken := string(orgTokenBytes)
|
||||
if orgToken == "" {
|
||||
return "", "", "", fmt.Errorf("organization management token cannot be empty")
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// Validate organization management token format
|
||||
if !strings.HasPrefix(orgToken, "ghp_") && !strings.HasPrefix(orgToken, "gho_") &&
|
||||
!strings.HasPrefix(orgToken, "ghu_") && !strings.HasPrefix(orgToken, "ghs_") &&
|
||||
!strings.HasPrefix(orgToken, "ghr_") && !strings.HasPrefix(orgToken, "github_pat_") {
|
||||
fmt.Println("[WARNING] The organization management token doesn't appear to be a GitHub personal access token (should start with ghp_, gho_, ghu_, ghs_, or ghr_)")
|
||||
fmt.Print("Do you want to continue anyway? (y/N): ")
|
||||
|
||||
confirm, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
confirm = strings.TrimSpace(strings.ToLower(confirm))
|
||||
|
||||
if confirm != "y" && confirm != "yes" {
|
||||
return "", "", "", fmt.Errorf("operation cancelled by user")
|
||||
}
|
||||
}
|
||||
|
||||
return username, token, orgToken, nil
|
||||
}
|
||||
|
||||
// createDockerConfig creates a Docker config JSON structure
|
||||
// createDockerConfig creates a Docker config JSON string.
|
||||
func createDockerConfig(username, token string) (string, error) {
|
||||
// Create base64 encoded auth string
|
||||
auth := base64.StdEncoding.EncodeToString([]byte(username + ":" + token))
|
||||
|
||||
// Create Docker config structure
|
||||
config := DockerConfig{
|
||||
Auths: map[string]DockerAuth{
|
||||
"ghcr.io": {
|
||||
ghcrRegistry: {
|
||||
Username: username,
|
||||
Password: token,
|
||||
Auth: auth,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Marshal to JSON
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", fmt.Errorf("failed to marshal docker config: %w", err)
|
||||
}
|
||||
|
||||
return string(configJSON), nil
|
||||
}
|
||||
|
||||
// storeInVault stores the Docker config in Vault KV v2
|
||||
func storeInVault(dockerConfigJSON string) error {
|
||||
fmt.Println("[INFO] Setting up Vault connection...")
|
||||
|
||||
// Get the vault pod name
|
||||
fmt.Println("[INFO] Finding Vault pod...")
|
||||
vaultPod, err := getVaultPodName()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find Vault pod: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("[INFO] Using Vault pod: %s\n", vaultPod)
|
||||
|
||||
// Get the root token
|
||||
fmt.Println("[INFO] Retrieving Vault root token...")
|
||||
rootToken, err := getVaultRootToken()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get Vault root token: %v", err)
|
||||
}
|
||||
|
||||
// Set environment and authenticate
|
||||
fmt.Println("[INFO] Setting up Vault environment...")
|
||||
envSetupCmd := fmt.Sprintf("export VAULT_SKIP_VERIFY=true && export VAULT_ADDR='https://127.0.0.1:8200' && export VAULT_TOKEN='%s'", rootToken)
|
||||
|
||||
// Test authentication
|
||||
authTestCmd := fmt.Sprintf("%s && vault token lookup", envSetupCmd)
|
||||
if err := runCommand("kubectl", "exec", "-n", "vault", vaultPod, "--", "sh", "-c", authTestCmd); err != nil {
|
||||
return fmt.Errorf("failed to validate Vault token: %v", err)
|
||||
}
|
||||
fmt.Println("[SUCCESS] Vault token is valid")
|
||||
|
||||
// Store the secret using kubectl exec to vault pod
|
||||
fmt.Println("[INFO] Storing Docker registry secret in Vault KV store...")
|
||||
|
||||
// Use kubectl exec to run vault command inside the pod with proper env vars and token
|
||||
vaultCmd := fmt.Sprintf("%s && vault kv put secret/ghcr-auth .dockerconfigjson='%s'", envSetupCmd, dockerConfigJSON)
|
||||
|
||||
if err := runCommand("kubectl", "exec", "-n", "vault", vaultPod, "--", "sh", "-c", vaultCmd); err != nil {
|
||||
return fmt.Errorf("failed to store Docker registry secret in Vault: %v", err)
|
||||
}
|
||||
|
||||
// Verify the secret was stored
|
||||
fmt.Println("[INFO] Verifying Docker registry secret storage...")
|
||||
verifyCmd := fmt.Sprintf("%s && vault kv get secret/ghcr-auth", envSetupCmd)
|
||||
if err := runCommand("kubectl", "exec", "-n", "vault", vaultPod, "--", "sh", "-c", verifyCmd); err != nil {
|
||||
fmt.Println("[WARNING] Could not verify Docker registry secret storage, but it may have been created successfully")
|
||||
fmt.Printf("[INFO] You can manually verify with: kubectl exec -n vault %s -- sh -c \"%s\"\n", vaultPod, verifyCmd)
|
||||
} else {
|
||||
fmt.Println("[SUCCESS] Docker registry secret stored and verified in Vault!")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// storeOrgManagementPAT stores the organization management PAT in Vault KV v2
|
||||
func storeOrgManagementPAT(token string) error {
|
||||
// Get the vault pod name
|
||||
vaultPod, err := getVaultPodName()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find Vault pod: %v", err)
|
||||
}
|
||||
|
||||
// Get the root token
|
||||
rootToken, err := getVaultRootToken()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get Vault root token: %v", err)
|
||||
}
|
||||
|
||||
// Set environment and authenticate
|
||||
envSetupCmd := fmt.Sprintf("export VAULT_SKIP_VERIFY=true && export VAULT_ADDR='https://127.0.0.1:8200' && export VAULT_TOKEN='%s'", rootToken)
|
||||
|
||||
// Store the organization management PAT
|
||||
fmt.Println("[INFO] Storing organization management PAT in Vault KV store...")
|
||||
|
||||
// Escape single quotes in token for shell command
|
||||
escapedToken := strings.ReplaceAll(token, "'", "'\"'\"'")
|
||||
|
||||
// Use kubectl exec to run vault command inside the pod
|
||||
vaultCmd := fmt.Sprintf("%s && vault kv put secret/org-management-pat ORG_MANAGEMENT_PAT='%s'", envSetupCmd, escapedToken)
|
||||
|
||||
if err := runCommand("kubectl", "exec", "-n", "vault", vaultPod, "--", "sh", "-c", vaultCmd); err != nil {
|
||||
return fmt.Errorf("failed to store organization management PAT in Vault: %v", err)
|
||||
}
|
||||
|
||||
// Verify the secret was stored
|
||||
fmt.Println("[INFO] Verifying organization management PAT storage...")
|
||||
verifyCmd := fmt.Sprintf("%s && vault kv get secret/org-management-pat", envSetupCmd)
|
||||
if err := runCommand("kubectl", "exec", "-n", "vault", vaultPod, "--", "sh", "-c", verifyCmd); err != nil {
|
||||
fmt.Println("[WARNING] Could not verify organization management PAT storage, but it may have been created successfully")
|
||||
fmt.Printf("[INFO] You can manually verify with: kubectl exec -n vault %s -- sh -c \"%s\"\n", vaultPod, verifyCmd)
|
||||
} else {
|
||||
fmt.Println("[SUCCESS] Organization management PAT stored and verified in Vault!")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getVaultPodName gets the name of a running Vault pod
|
||||
func getVaultPodName() (string, error) {
|
||||
// Try to get vault-0 first (common StatefulSet naming)
|
||||
if err := runCommandQuiet("kubectl", "get", "pod", "vault-0", "-n", "vault"); err == nil {
|
||||
return "vault-0", nil
|
||||
}
|
||||
|
||||
// Try other common Vault pod names
|
||||
commonNames := []string{"vault-0", "vault-1", "vault-2"}
|
||||
for _, name := range commonNames {
|
||||
if err := runCommandQuiet("kubectl", "get", "pod", name, "-n", "vault"); err == nil {
|
||||
return name, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find any vault pod using labels
|
||||
cmd := exec.Command("kubectl", "get", "pods", "-n", "vault", "-l", "app.kubernetes.io/name=vault", "-o", "jsonpath={.items[0].metadata.name}")
|
||||
output, err := cmd.Output()
|
||||
if err == nil && len(output) > 0 {
|
||||
return string(output), nil
|
||||
}
|
||||
|
||||
// Last resort: try to find any running pod in vault namespace
|
||||
cmd = exec.Command("kubectl", "get", "pods", "-n", "vault", "--field-selector=status.phase=Running", "-o", "jsonpath={.items[0].metadata.name}")
|
||||
output, err = cmd.Output()
|
||||
if err == nil && len(output) > 0 {
|
||||
return string(output), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("could not find any running Vault pods in the 'vault' namespace. Please ensure Vault is properly deployed and running")
|
||||
}
|
||||
|
||||
// getVaultRootToken retrieves the Vault root token from Kubernetes secrets
|
||||
func getVaultRootToken() (string, error) {
|
||||
fmt.Println("[INFO] Looking for Vault root token in vault-unseal-keys secret...")
|
||||
|
||||
// Primary location: secret/vault-unseal-keys key vault-root in vault namespace
|
||||
cmd := exec.Command("kubectl", "get", "secret", "vault-unseal-keys", "-n", "vault", "-o", "jsonpath={.data.vault-root}")
|
||||
output, err := cmd.Output()
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get vault-unseal-keys secret from vault namespace: %v. Please ensure Vault is properly initialized", err)
|
||||
}
|
||||
|
||||
if len(output) == 0 {
|
||||
return "", fmt.Errorf("vault-root key not found in vault-unseal-keys secret")
|
||||
}
|
||||
|
||||
// The token is base64 encoded in the Kubernetes secret, decode it
|
||||
decoded, err := base64.StdEncoding.DecodeString(string(output))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decode base64 root token: %v", err)
|
||||
}
|
||||
|
||||
if len(decoded) == 0 {
|
||||
return "", fmt.Errorf("decoded root token is empty")
|
||||
}
|
||||
|
||||
token := strings.TrimSpace(string(decoded))
|
||||
fmt.Println("[SUCCESS] Found Vault root token")
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue