-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstore_kolla_passwords.go
127 lines (112 loc) · 4 KB
/
store_kolla_passwords.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main
import (
"fmt"
"log"
"os"
"github.com/hashicorp/vault/api"
"gopkg.in/yaml.v2"
"io/ioutil"
)
const (
passwordsFile = "etc/kolla/passwords.yml" // Path to the passwords.yml file
vaultAddress = "http://127.0.0.1:8200" // Address of the Vault server
basePath = "secret/data/kolla" // Base Vault path, includes the 'data' section
defaultPath = "default" // Default subdirectory to use in Vault path
)
func main() {
// Determine the Vault subdirectory from the environment variable or use the default
vaultSubDir := getEnv("VAULT_PATH", defaultPath)
vaultPath := fmt.Sprintf("%s/%s", basePath, vaultSubDir)
vaultToken := os.Getenv("VAULT_TOKEN")
// Ensure VAULT_TOKEN is set, or exit
if vaultToken == "" {
log.Println("VAULT_TOKEN is not set. Exiting.")
return
}
// Initialize the Vault client
client, err := initializeVaultClient(vaultAddress, vaultToken)
if err != nil {
log.Fatalf("Failed to create Vault client: %v", err)
}
// Load the passwords.yml file into memory
data, err := ioutil.ReadFile(passwordsFile)
if err != nil {
log.Fatalf("Failed to read passwords.yml: %v", err)
}
// Parse the YAML content into a map
passwords := make(map[string]interface{})
err = yaml.Unmarshal(data, &passwords)
if err != nil {
log.Fatalf("Failed to parse YAML: %v", err)
}
// Store the parsed passwords in Vault
if err := storePasswordsInVault(client, vaultPath, passwords); err != nil {
log.Fatalf("Failed to store passwords: %v", err)
}
log.Println("All passwords have been stored in Vault.")
}
// getEnv retrieves the value of an environment variable or returns a fallback value if not set
func getEnv(key, fallback string) string {
if value := os.Getenv(key); value != "" {
fmt.Printf("Using Vault path '%s/%s'.\n", basePath, value)
return value
}
fmt.Printf("VAULT_PATH is not set. Using default path '%s/%s'.\n", basePath, fallback)
return fallback
}
// initializeVaultClient creates a new Vault client and sets the authentication token
func initializeVaultClient(address, token string) (*api.Client, error) {
client, err := api.NewClient(&api.Config{Address: address})
if err != nil {
return nil, err
}
client.SetToken(token)
return client, nil
}
// storePasswordsInVault stores the passwords recursively in Vault
func storePasswordsInVault(client *api.Client, vaultPath string, data map[string]interface{}) error {
// Delegate the storage process to storeNestedMap to handle both simple and nested values
return storeNestedMap(client, vaultPath, data)
}
// storeNestedMap recursively processes and stores nested structures in Vault
func storeNestedMap(client *api.Client, path string, data map[string]interface{}) error {
for key, value := range data {
switch v := value.(type) {
case map[interface{}]interface{}:
// Convert map[interface{}]interface{} to map[string]interface{} for compatibility with Vault
nestedMap := make(map[string]interface{})
for k, val := range v {
strKey := fmt.Sprintf("%v", k)
nestedMap[strKey] = val
}
// Recursively store nested maps
if err := storeNestedMap(client, fmt.Sprintf("%s/%s", path, key), nestedMap); err != nil {
return err
}
case string:
// Store simple string values as secrets in Vault
if err := storeSecret(client, path, key, v); err != nil {
return err
}
case nil:
// Handle nil values (currently skipping them)
log.Printf("Skipping nil value for key %s", key)
default:
// Skip unsupported types
log.Printf("Skipping unsupported type for key %s: %T", key, v)
}
}
return nil
}
// storeSecret stores a single key-value pair in Vault at the specified path
func storeSecret(client *api.Client, vaultPath, key, value string) error {
// Write the secret to Vault in the appropriate path
_, err := client.Logical().Write(
fmt.Sprintf("%s/%s", vaultPath, key),
map[string]interface{}{"data": map[string]interface{}{"value": value}},
)
if err != nil {
log.Printf("Error storing secret %s at path %s/%s: %v", key, vaultPath, key, err)
}
return err
}