mirror of
https://github.com/khuedoan/homelab.git
synced 2025-02-07 01:28:42 +07:00
141 lines
3.7 KiB
Go
141 lines
3.7 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"math"
|
||
|
"os"
|
||
|
|
||
|
"github.com/sethvargo/go-password/password"
|
||
|
"gopkg.in/yaml.v2"
|
||
|
v1 "k8s.io/api/core/v1"
|
||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||
|
"k8s.io/client-go/kubernetes"
|
||
|
"k8s.io/client-go/tools/clientcmd"
|
||
|
)
|
||
|
|
||
|
const namespace = "global-secrets"
|
||
|
|
||
|
type RandomSecret struct {
|
||
|
Name string
|
||
|
Data []struct {
|
||
|
Key string
|
||
|
Length int
|
||
|
Special bool
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func getClient() (*kubernetes.Clientset, error) {
|
||
|
rules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||
|
overrides := &clientcmd.ConfigOverrides{}
|
||
|
|
||
|
config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig()
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("Error building client config: %v", err)
|
||
|
}
|
||
|
|
||
|
return kubernetes.NewForConfig(config)
|
||
|
}
|
||
|
|
||
|
func generateRandomPassword(length int, special bool) (string, error) {
|
||
|
numDigits := int(math.Ceil(float64(length) * 0.2))
|
||
|
numSymbols := 0
|
||
|
|
||
|
if special {
|
||
|
numSymbols = int(math.Ceil(float64(length) * 0.2))
|
||
|
}
|
||
|
|
||
|
return password.Generate(length, numDigits, numSymbols, false, true)
|
||
|
}
|
||
|
|
||
|
func readConfigFile(filename string) ([]RandomSecret, error) {
|
||
|
data, err := os.ReadFile(filename)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("Unable to read config file: %v", err)
|
||
|
}
|
||
|
|
||
|
var randomSecrets []RandomSecret
|
||
|
err = yaml.Unmarshal(data, &randomSecrets)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("Error parsing config file: %v", err)
|
||
|
}
|
||
|
|
||
|
return randomSecrets, nil
|
||
|
}
|
||
|
|
||
|
func createOrUpdateSecret(client *kubernetes.Clientset, name string, randomSecret RandomSecret) error {
|
||
|
secret, err := client.CoreV1().Secrets(namespace).Get(context.Background(), name, metav1.GetOptions{})
|
||
|
|
||
|
if err != nil {
|
||
|
// Secret not found, create a new one
|
||
|
secretData := map[string][]byte{}
|
||
|
|
||
|
for _, randomPassword := range randomSecret.Data {
|
||
|
password, err := generateRandomPassword(randomPassword.Length, randomPassword.Special)
|
||
|
if err != nil {
|
||
|
log.Printf("Error generating password for key '%s': %v", randomPassword.Key, err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
secretData[randomPassword.Key] = []byte(password)
|
||
|
}
|
||
|
|
||
|
newSecret := &v1.Secret{
|
||
|
ObjectMeta: metav1.ObjectMeta{
|
||
|
Name: name,
|
||
|
Namespace: namespace,
|
||
|
},
|
||
|
Data: secretData,
|
||
|
}
|
||
|
|
||
|
_, err := client.CoreV1().Secrets(namespace).Create(context.Background(), newSecret, metav1.CreateOptions{})
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("Unable to create secret: %v", err)
|
||
|
}
|
||
|
log.Printf("Secret '%s' created successfully.", name)
|
||
|
} else {
|
||
|
// Secret exists, check for new keys
|
||
|
for _, randomKey := range randomSecret.Data {
|
||
|
if _, exists := secret.Data[randomKey.Key]; !exists {
|
||
|
// New key found, generate new password
|
||
|
log.Printf("New key '%s' found in config for secret '%s', generating new password", randomKey.Key, name)
|
||
|
password, err := generateRandomPassword(randomKey.Length, randomKey.Special)
|
||
|
if err != nil {
|
||
|
log.Printf("Error generating password for key '%s': %v", randomKey.Key, err)
|
||
|
continue
|
||
|
}
|
||
|
secret.Data[randomKey.Key] = []byte(password)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update the secret
|
||
|
_, err := client.CoreV1().Secrets(namespace).Update(context.Background(), secret, metav1.UpdateOptions{})
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("Unable to update secret: %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
configFilename := "./config.yaml"
|
||
|
randomSecrets, err := readConfigFile(configFilename)
|
||
|
if err != nil {
|
||
|
log.Fatalf("Error reading config file: %v", err)
|
||
|
}
|
||
|
|
||
|
client, err := getClient()
|
||
|
if err != nil {
|
||
|
log.Fatalf("Unable to create Kubernetes client: %v", err)
|
||
|
}
|
||
|
|
||
|
for _, randomSecret := range randomSecrets {
|
||
|
err := createOrUpdateSecret(client, randomSecret.Name, randomSecret)
|
||
|
if err != nil {
|
||
|
log.Printf("Error processing secret %s: %v", randomSecret.Name, err)
|
||
|
}
|
||
|
}
|
||
|
}
|