mirror of
https://github.com/hanzoai/deploy.git
synced 2026-10-07 08:44:50 +00:00
go.mod still declared `module github.com/hanzoai/deploy` after the repo was renamed. A Go module path is not cosmetic — it is the resolvable location. So `go get github.com/hanzoai/cd` could not work, and anything importing this module had to spell a name that no longer exists at that address. The build log of v3.6.0 is where it surfaced: the compiler was still emitting github.com/hanzoai/deploy/cmd/cd/commands. 3541 import paths across 690 .go, 19 .proto, 4 .yaml, 3 .sh, 2 .mod, Procfile and Makefile. Plus the 62 ghcr.io/hanzoai/deploy image references, moved to ghcr.io/hanzoai/cd to match hanzo.yml's build target — a distinct string from the module path, replaced separately so neither could clobber the other. go mod tidy clean, CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ./... clean. Co-authored-by: Hanzo Dev <[email protected]>
142 lines
4.5 KiB
Go
142 lines
4.5 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/hanzoai/cd/common"
|
|
appsv1 "github.com/hanzoai/cd/pkg/apis/application/v1alpha1"
|
|
"github.com/hanzoai/cd/util/sourceintegrity"
|
|
)
|
|
|
|
// Validates a single GnuPG key and returns the key's ID
|
|
func validatePGPKey(keyData string) (*appsv1.GnuPGPublicKey, error) {
|
|
f, err := os.CreateTemp("", "gpg-public-key")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error creating temp file for GPG key: %w", err)
|
|
}
|
|
defer os.Remove(f.Name())
|
|
|
|
err = os.WriteFile(f.Name(), []byte(keyData), 0o600)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error writing GPG key to temp file: %w", err)
|
|
}
|
|
defer func() {
|
|
err = f.Close()
|
|
if err != nil {
|
|
log.Errorf("error closing file %q: %v", f.Name(), err)
|
|
}
|
|
}()
|
|
|
|
parsed, err := sourceintegrity.ValidatePGPKeys(f.Name())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error validating PGP key: %w", err)
|
|
}
|
|
|
|
// Each key/value pair in the config map must exactly contain one public key, with the (short) GPG key ID as key
|
|
if len(parsed) != 1 {
|
|
return nil, errors.New("more than one key found in input data")
|
|
}
|
|
|
|
var retKey *appsv1.GnuPGPublicKey
|
|
// Is there a better way to get the first element from a map without knowing its key?
|
|
for _, k := range parsed {
|
|
retKey = k
|
|
break
|
|
}
|
|
if retKey != nil {
|
|
retKey.KeyData = keyData
|
|
return retKey, nil
|
|
}
|
|
return nil, errors.New("could not find the GPG key")
|
|
}
|
|
|
|
// ListConfiguredGPGPublicKeys returns a list of all configured GPG public keys from the ConfigMap
|
|
func (db *db) ListConfiguredGPGPublicKeys(_ context.Context) (map[string]*appsv1.GnuPGPublicKey, error) {
|
|
log.Debugf("Loading PGP public keys from config map")
|
|
result := make(map[string]*appsv1.GnuPGPublicKey)
|
|
keysCM, err := db.settingsMgr.GetConfigMapByName(common.ArgoCDGPGKeysConfigMapName)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting GPG keys configmap: %w", err)
|
|
}
|
|
|
|
// We have to verify all PGP keys in the ConfigMap to be valid keys before. To do so,
|
|
// we write each single one out to a temporary file and validate them through gpg.
|
|
// This is not optimal, but the executil from argo-pkg does not support writing to
|
|
// stdin of the forked process. So for now, we must live with that.
|
|
for k, p := range keysCM.Data {
|
|
expectedKeyID, err := sourceintegrity.KeyID(k)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error validating key ID %q in GPG keys configmap: %w", k, err)
|
|
}
|
|
parsedKey, err := validatePGPKey(p)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing GPG key for entry %q: %w", expectedKeyID, err)
|
|
}
|
|
if expectedKeyID != parsedKey.KeyID {
|
|
return nil, fmt.Errorf("key parsed for entry with key ID '%s' had different key ID '%s'", expectedKeyID, parsedKey.KeyID)
|
|
}
|
|
result[parsedKey.KeyID] = parsedKey
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// AddGPGPublicKey adds one or more public keys to the configuration
|
|
func (db *db) AddGPGPublicKey(ctx context.Context, keyData string) (map[string]*appsv1.GnuPGPublicKey, []string, error) {
|
|
result := make(map[string]*appsv1.GnuPGPublicKey)
|
|
skipped := make([]string, 0)
|
|
|
|
keys, err := sourceintegrity.ValidatePGPKeysFromString(keyData)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("error validating PGP keys from input: %w", err)
|
|
}
|
|
|
|
keysCM, err := db.settingsMgr.GetConfigMapByName(common.ArgoCDGPGKeysConfigMapName)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("error getting GPG keys configmap: %w", err)
|
|
}
|
|
|
|
for kid, key := range keys {
|
|
if _, ok := keysCM.Data[kid]; ok {
|
|
skipped = append(skipped, kid)
|
|
log.Debugf("Not adding incoming key with kid=%s because it is configured already", kid)
|
|
} else {
|
|
result[kid] = key
|
|
keysCM.Data[kid] = key.KeyData
|
|
log.Debugf("Adding incoming key with kid=%s to database", kid)
|
|
}
|
|
}
|
|
|
|
err = db.settingsMgr.SaveGPGPublicKeyData(ctx, keysCM.Data)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("error saving GPG public key data: %w", err)
|
|
}
|
|
|
|
return result, skipped, nil
|
|
}
|
|
|
|
// DeleteGPGPublicKey deletes a GPG public key from the configuration
|
|
func (db *db) DeleteGPGPublicKey(ctx context.Context, keyID string) error {
|
|
keysCM, err := db.settingsMgr.GetConfigMapByName(common.ArgoCDGPGKeysConfigMapName)
|
|
if err != nil {
|
|
return fmt.Errorf("error getting GPG keys configmap: %w", err)
|
|
}
|
|
|
|
if _, ok := keysCM.Data[keyID]; !ok {
|
|
return fmt.Errorf("no such key configured: %s", keyID)
|
|
}
|
|
|
|
delete(keysCM.Data, keyID)
|
|
|
|
err = db.settingsMgr.SaveGPGPublicKeyData(ctx, keysCM.Data)
|
|
if err != nil {
|
|
return fmt.Errorf("error saving GPG public key data: %w", err)
|
|
}
|
|
return nil
|
|
}
|