constellation/internal/constellation/apply.go
Daniel Weiße b7425db72a
constellation-lib: add Helm wrapper (#2680)
* Add Helm wrapper to constellation-lib
* Move helm package to constellation-lib

---------

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
2023-12-06 10:01:39 +01:00

116 lines
3.5 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package constellation
import (
"context"
"fmt"
"github.com/edgelesssys/constellation/v2/internal/atls"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/constellation/helm"
"github.com/edgelesssys/constellation/v2/internal/constellation/kubecmd"
"github.com/edgelesssys/constellation/v2/internal/crypto"
"github.com/edgelesssys/constellation/v2/internal/grpc/dialer"
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
"github.com/edgelesssys/constellation/v2/internal/license"
)
// An Applier handles applying a specific configuration to a Constellation cluster
// with existing Infrastructure.
// In Particular, this involves Initialization and Upgrading of the cluster.
type Applier struct {
log debugLog
licenseChecker licenseChecker
spinner spinnerInterf
// newDialer creates a new aTLS gRPC dialer.
newDialer func(validator atls.Validator) *dialer.Dialer
kubecmdClient kubecmdClient
helmClient helmApplier
}
type licenseChecker interface {
CheckLicense(context.Context, cloudprovider.Provider, string) (license.QuotaCheckResponse, error)
}
type debugLog interface {
Debugf(format string, args ...any)
}
// NewApplier creates a new Applier.
func NewApplier(
log debugLog,
spinner spinnerInterf,
newDialer func(validator atls.Validator) *dialer.Dialer,
) *Applier {
return &Applier{
log: log,
spinner: spinner,
licenseChecker: license.NewChecker(license.NewClient()),
newDialer: newDialer,
}
}
// SetKubeConfig sets the config file to use for creating Kubernetes clients.
func (a *Applier) SetKubeConfig(kubeConfig []byte) error {
kubecmdClient, err := kubecmd.New(kubeConfig, a.log)
if err != nil {
return err
}
helmClient, err := helm.NewClient(kubeConfig, a.log)
if err != nil {
return err
}
a.kubecmdClient = kubecmdClient
a.helmClient = helmClient
return nil
}
// CheckLicense checks the given Constellation license with the license server
// and returns the allowed quota for the license.
func (a *Applier) CheckLicense(ctx context.Context, csp cloudprovider.Provider, licenseID string) (int, error) {
a.log.Debugf("Contacting license server for license '%s'", licenseID)
quotaResp, err := a.licenseChecker.CheckLicense(ctx, csp, licenseID)
if err != nil {
return 0, fmt.Errorf("checking license: %w", err)
}
a.log.Debugf("Got response from license server for license '%s'", licenseID)
return quotaResp.Quota, nil
}
// GenerateMasterSecret generates a new master secret.
func (a *Applier) GenerateMasterSecret() (uri.MasterSecret, error) {
a.log.Debugf("Generating master secret")
key, err := crypto.GenerateRandomBytes(crypto.MasterSecretLengthDefault)
if err != nil {
return uri.MasterSecret{}, err
}
salt, err := crypto.GenerateRandomBytes(crypto.RNGLengthDefault)
if err != nil {
return uri.MasterSecret{}, err
}
secret := uri.MasterSecret{
Key: key,
Salt: salt,
}
a.log.Debugf("Generated master secret key and salt values")
return secret, nil
}
// GenerateMeasurementSalt generates a new measurement salt.
func (a *Applier) GenerateMeasurementSalt() ([]byte, error) {
a.log.Debugf("Generating measurement salt")
measurementSalt, err := crypto.GenerateRandomBytes(crypto.RNGLengthDefault)
if err != nil {
return nil, fmt.Errorf("generating measurement salt: %w", err)
}
a.log.Debugf("Generated measurement salt")
return measurementSalt, nil
}