add ability to store/create encrypted vcenter password
Some checks are pending
CI / Lint (push) Waiting to run
CI / Test (push) Waiting to run
CI / End-to-End (push) Waiting to run
CI / Publish Docker (push) Blocked by required conditions
continuous-integration/drone/push Build is passing

This commit is contained in:
2024-09-27 17:02:02 +10:00
parent 5a00f4a8c7
commit 3501967c9e
13 changed files with 235 additions and 772 deletions

View File

@@ -0,0 +1,80 @@
package secrets
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"io"
"log/slog"
)
type Secrets struct {
Logger *slog.Logger
EncryptionKey []byte
}
func New(logger *slog.Logger, key []byte) *Secrets {
return &Secrets{
Logger: logger,
EncryptionKey: key,
}
}
// Encrypt function that encrypts data using AES256-GCM and returns base64 encoded ciphertext
func (s *Secrets) Encrypt(plainText []byte) (string, error) {
block, err := aes.NewCipher(s.EncryptionKey)
if err != nil {
return "", err
}
// Create a new GCM cipher
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
// Create a nonce
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return "", err
}
// Encrypt the plaintext using AES256-GCM
cipherText := gcm.Seal(nonce, nonce, plainText, nil)
// Return the base64 encoded ciphertext
return base64.StdEncoding.EncodeToString(cipherText), nil
}
// Decrypt function that decrypts base64 encoded AES256-GCM ciphertext
func (s *Secrets) Decrypt(base64CipherText string) ([]byte, error) {
// Decode the base64 ciphertext
cipherText, err := base64.StdEncoding.DecodeString(base64CipherText)
if err != nil {
return nil, err
}
block, err := aes.NewCipher(s.EncryptionKey)
if err != nil {
return nil, err
}
// Create a new GCM cipher
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
// Extract the nonce from the ciphertext
nonceSize := gcm.NonceSize()
nonce, cipherText := cipherText[:nonceSize], cipherText[nonceSize:]
// Decrypt the ciphertext
plainText, err := gcm.Open(nil, nonce, cipherText, nil)
if err != nil {
return nil, err
}
return plainText, nil
}

View File

@@ -11,17 +11,6 @@ import (
// SettingsYML struct holds various runtime data that is too cumbersome to specify via command line, eg replacement properties
type SettingsYML struct {
Settings struct {
/*
Replacements []struct {
Key string `yaml:"Key"`
Value string `yaml:"Value"`
} `yaml:"replacements"`
Omapi struct {
KeyName string `yaml:"key_name"`
KeySecret string `yaml:"key_secret"`
} `yaml:"omapi"`
*/
TenantsToFilter []string `yaml:"tenants_to_filter"`
NodeChargeClusters []string `yaml:"node_charge_clusters"`
SrmActiveActiveVms []string `yaml:"srm_activeactive_vms"`

View File

@@ -5,21 +5,12 @@ import (
"database/sql"
"log/slog"
"time"
"vctp/db"
"vctp/db/queries"
"vctp/internal/settings"
"vctp/internal/vcenter"
"github.com/vmware/govmomi/vim25/types"
)
// Handler handles requests.
type CronTask struct {
Logger *slog.Logger
Database db.Database
Settings settings.SettingsYML
}
// use gocron to check events in the Events table
func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error {
var (
@@ -42,6 +33,8 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error {
if err != nil {
logger.Error("Unable to query for unprocessed events", "error", err)
return nil // TODO - what to do with this error?
} else {
logger.Debug("Successfully queried for unprocessed events", "count", len(events))
}
for _, evt := range events {
@@ -51,7 +44,7 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error {
// to avoid doing unnecessary login/logout of vcenter
c.Logger.Debug("connecting to vcenter")
vc := vcenter.New(c.Logger)
vc := vcenter.New(c.Logger, c.VcCreds)
vc.Login(evt.Source)
//datacenter = evt.DatacenterName.String

16
internal/tasks/tasks.go Normal file
View File

@@ -0,0 +1,16 @@
package tasks
import (
"log/slog"
"vctp/db"
"vctp/internal/settings"
"vctp/internal/vcenter"
)
// CronTask stores runtime information to be used by tasks
type CronTask struct {
Logger *slog.Logger
Database db.Database
Settings settings.SettingsYML
VcCreds *vcenter.VcenterLogin
}

View File

@@ -19,9 +19,15 @@ import (
)
type Vcenter struct {
Logger *slog.Logger
ctx context.Context
client *govmomi.Client
Logger *slog.Logger
ctx context.Context
client *govmomi.Client
credentials *VcenterLogin
}
type VcenterLogin struct {
Username string
Password string
}
type VmProperties struct {
@@ -30,23 +36,25 @@ type VmProperties struct {
}
// New creates a new Vcenter with the given logger
func New(logger *slog.Logger) *Vcenter {
func New(logger *slog.Logger, creds *VcenterLogin) *Vcenter {
//ctx, cancel := context.WithCancel(context.Background())
//defer cancel()
return &Vcenter{
Logger: logger,
ctx: context.Background(),
Logger: logger,
ctx: context.Background(),
credentials: creds,
}
}
func (v *Vcenter) Login(vUrl string) error {
var insecure bool
// TODO - fix this
insecureString := os.Getenv("VCENTER_INSECURE")
username := os.Getenv("VCENTER_USERNAME")
password := os.Getenv("VCENTER_PASSWORD")
//username := os.Getenv("VCENTER_USERNAME")
//password := os.Getenv("VCENTER_PASSWORD")
// Connect to vCenter
u, err := soap.ParseURL(vUrl)
@@ -54,7 +62,7 @@ func (v *Vcenter) Login(vUrl string) error {
log.Fatalf("Error parsing vCenter URL: %s", err)
}
u.User = url.UserPassword(username, password)
u.User = url.UserPassword(v.credentials.Username, v.credentials.Password)
/*
c, err := govmomi.NewClient(ctx, u, insecure)
@@ -77,7 +85,7 @@ func (v *Vcenter) Login(vUrl string) error {
v.client = c
v.Logger.Debug("successfully connected to vCenter", "url", vUrl, "username", username)
v.Logger.Debug("successfully connected to vCenter", "url", vUrl, "username", v.credentials.Username)
return nil
}