package edgeencrypt import ( "context" "crypto/rsa" "fmt" "cloud.google.com/go/kms/apiv1/kmspb" "github.com/golang-jwt/jwt" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) const ( EncryptionName = "sparrow" EncryptionJWTSecret = "encryption-jwt-signing-secret" //nolint:gosec EncryptionSecret = "%s-encryption-key" //nolint:gosec EncryptionBearerToken = "%s-encryption-bearer-token" //nolint:gosec EncryptionJWTSecretManager = "sparrow-jwt-signing-key" //nolint:gosec EncryptionSecretManager = "channel-%s-encryption-key" //nolint:gosec EncryptionTokenSecretManager = "channel-%s-encryption-bearer-token" //nolint:gosec DecryptionName = "magpie" DecryptionJWTSecret = "decryption-signing-secret" //nolint:gosec DecryptionJWTSecretManager = "decryption-signing-secret" //nolint:gosec DecryptionTokenSecretManager = "decryption-bearer-token" //nolint:gosec VersionKey = "version" PEMKey = "pem" DefaultSigningCryptoKeyPurpose = kmspb.CryptoKey_ASYMMETRIC_SIGN DefaultSigningCryptoKeyAlgorithm = kmspb.CryptoKeyVersion_RSA_SIGN_PSS_2048_SHA256 DefaultCryptoKeyPurpose = kmspb.CryptoKey_ASYMMETRIC_DECRYPT DefaultCryptoKeyAlgorithm = kmspb.CryptoKeyVersion_RSA_DECRYPT_OAEP_2048_SHA256 ) type PublicKey struct { Version string `json:"version"` // 1,2 PEM string `json:"pem"` // actual public key } func NewPublicKey(pem, version string) (*PublicKey, error) { p := &PublicKey{ Version: version, PEM: pem, } if err := p.Valid(); err != nil { return nil, err } return p, nil } func (p *PublicKey) Valid() error { if p.Version == "" { return fmt.Errorf("version is required") } if p.PEM == "" { return fmt.Errorf("pem is required") } return nil } func (p *PublicKey) ToSecret(ns, name string) (*v1.Secret, error) { if err := p.Valid(); err != nil { return nil, err } return &v1.Secret{ TypeMeta: metav1.TypeMeta{ Kind: "Secret", APIVersion: v1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: ns, }, Data: map[string][]byte{ VersionKey: []byte(p.Version), PEMKey: []byte(p.PEM), }, }, nil } func (p *PublicKey) FromSecret(secret *v1.Secret) error { p.Version = string(secret.Data[VersionKey]) p.PEM = string(secret.Data[PEMKey]) return p.Valid() } func (p *PublicKey) ToRSAPublicKey() (*rsa.PublicKey, error) { return jwt.ParseRSAPublicKeyFromPEM([]byte(p.PEM)) } // Save put the pem values int0 the secret func (p *PublicKey) Save(ctx context.Context, cl client.Client, ns, name string) error { secret, err := p.ToSecret(ns, name) if err != nil { return err } return cl.Create(ctx, secret) } // GetPublicKey grabs the pem values from the secret func GetPublicKey(ctx context.Context, cl client.Client, ns, name string) (*PublicKey, error) { secret := &v1.Secret{} if err := cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: name}, secret); err != nil { return nil, fmt.Errorf("failed to get public key [%s/%s] Secret: %w", ns, name, err) } p := &PublicKey{} if err := p.FromSecret(secret); err != nil { return nil, fmt.Errorf("failed to parse public key [%s/%s] secret: %w", ns, name, err) } return p, nil }