mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-05-30 11:34:26 -04:00
deps: convert zap to slog (#2825)
This commit is contained in:
parent
3765cb0762
commit
54cce77bab
182 changed files with 1474 additions and 1509 deletions
|
@ -44,7 +44,6 @@ go_library(
|
||||||
"//internal/versions/components",
|
"//internal/versions/components",
|
||||||
"@com_github_spf13_afero//:afero",
|
"@com_github_spf13_afero//:afero",
|
||||||
"@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm/v1beta3",
|
"@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm/v1beta3",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,13 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes"
|
"github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes"
|
||||||
"github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes/k8sapi"
|
"github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes/k8sapi"
|
||||||
|
@ -45,13 +46,12 @@ func main() {
|
||||||
gRPCDebug := flag.Bool("debug", false, "Enable gRPC debug logging")
|
gRPCDebug := flag.Bool("debug", false, "Enable gRPC debug logging")
|
||||||
verbosity := flag.Int("v", 0, logger.CmdLineVerbosityDescription)
|
verbosity := flag.Int("v", 0, logger.CmdLineVerbosityDescription)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
log := logger.New(logger.JSONLog, logger.VerbosityFromInt(*verbosity)).Named("bootstrapper")
|
log := logger.NewJSONLogger(logger.VerbosityFromInt(*verbosity)).WithGroup("bootstrapper")
|
||||||
defer log.Sync()
|
|
||||||
|
|
||||||
if *gRPCDebug {
|
if *gRPCDebug {
|
||||||
log.Named("gRPC").ReplaceGRPCLogger()
|
logger.ReplaceGRPCLogger(log.WithGroup("gRPC"))
|
||||||
} else {
|
} else {
|
||||||
log.Named("gRPC").WithIncreasedLevel(zap.WarnLevel).ReplaceGRPCLogger()
|
logger.ReplaceGRPCLogger(slog.New(logger.NewLevelHandler(slog.LevelWarn, log.Handler())).WithGroup("gRPC"))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
@ -66,18 +66,21 @@ func main() {
|
||||||
|
|
||||||
attestVariant, err := variant.FromString(os.Getenv(constants.AttestationVariant))
|
attestVariant, err := variant.FromString(os.Getenv(constants.AttestationVariant))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to parse attestation variant")
|
log.With(slog.Any("error", err)).Error("Failed to parse attestation variant")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
issuer, err := choose.Issuer(attestVariant, log)
|
issuer, err := choose.Issuer(attestVariant, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to select issuer")
|
log.With(slog.Any("error", err)).Error("Failed to select issuer")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch cloudprovider.FromString(os.Getenv(constellationCSP)) {
|
switch cloudprovider.FromString(os.Getenv(constellationCSP)) {
|
||||||
case cloudprovider.AWS:
|
case cloudprovider.AWS:
|
||||||
metadata, err := awscloud.New(ctx)
|
metadata, err := awscloud.New(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to set up AWS metadata API")
|
log.With(slog.Any("error", err)).Error("Failed to set up AWS metadata API")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
metadataAPI = metadata
|
metadataAPI = metadata
|
||||||
|
|
||||||
|
@ -91,7 +94,8 @@ func main() {
|
||||||
case cloudprovider.GCP:
|
case cloudprovider.GCP:
|
||||||
metadata, err := gcpcloud.New(ctx)
|
metadata, err := gcpcloud.New(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to create GCP metadata client")
|
log.With(slog.Any("error", err)).Error("Failed to create GCP metadata client")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer metadata.Close()
|
defer metadata.Close()
|
||||||
|
|
||||||
|
@ -106,11 +110,13 @@ func main() {
|
||||||
case cloudprovider.Azure:
|
case cloudprovider.Azure:
|
||||||
metadata, err := azurecloud.New(ctx)
|
metadata, err := azurecloud.New(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to create Azure metadata client")
|
log.With(slog.Any("error", err)).Error("Failed to create Azure metadata client")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := metadata.PrepareControlPlaneNode(ctx, log); err != nil {
|
if err := metadata.PrepareControlPlaneNode(ctx, log); err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to prepare Azure control plane node")
|
log.With(slog.Any("error", err)).Error("Failed to prepare Azure control plane node")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
metadataAPI = metadata
|
metadataAPI = metadata
|
||||||
|
@ -138,13 +144,14 @@ func main() {
|
||||||
return tdx.Open()
|
return tdx.Open()
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
log.Fatalf("Unsupported attestation variant: %s", attestVariant)
|
log.Error(fmt.Sprintf("Unsupported attestation variant: %s", attestVariant))
|
||||||
}
|
}
|
||||||
fs = afero.NewOsFs()
|
fs = afero.NewOsFs()
|
||||||
case cloudprovider.OpenStack:
|
case cloudprovider.OpenStack:
|
||||||
metadata, err := openstackcloud.New(ctx)
|
metadata, err := openstackcloud.New(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to create OpenStack metadata client")
|
log.With(slog.Any("error", err)).Error("Failed to create OpenStack metadata client")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
clusterInitJoiner = kubernetes.New(
|
clusterInitJoiner = kubernetes.New(
|
||||||
"openstack", k8sapi.NewKubernetesUtil(), &k8sapi.KubdeadmConfiguration{}, kubectl.NewUninitialized(),
|
"openstack", k8sapi.NewKubernetesUtil(), &k8sapi.KubdeadmConfiguration{}, kubectl.NewUninitialized(),
|
||||||
|
|
|
@ -8,7 +8,10 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/bootstrapper/internal/clean"
|
"github.com/edgelesssys/constellation/v2/bootstrapper/internal/clean"
|
||||||
"github.com/edgelesssys/constellation/v2/bootstrapper/internal/diskencryption"
|
"github.com/edgelesssys/constellation/v2/bootstrapper/internal/diskencryption"
|
||||||
|
@ -21,31 +24,31 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/grpc/dialer"
|
"github.com/edgelesssys/constellation/v2/internal/grpc/dialer"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func run(issuer atls.Issuer, openDevice vtpm.TPMOpenFunc, fileHandler file.Handler,
|
func run(issuer atls.Issuer, openDevice vtpm.TPMOpenFunc, fileHandler file.Handler,
|
||||||
kube clusterInitJoiner, metadata metadataAPI,
|
kube clusterInitJoiner, metadata metadataAPI,
|
||||||
bindIP, bindPort string, log *logger.Logger,
|
bindIP, bindPort string, log *slog.Logger,
|
||||||
) {
|
) {
|
||||||
log.With(zap.String("version", constants.BinaryVersion().String())).Infof("Starting bootstrapper")
|
log.With(slog.String("version", constants.BinaryVersion().String())).Info("Starting bootstrapper")
|
||||||
|
|
||||||
uuid, err := getDiskUUID()
|
uuid, err := getDiskUUID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Errorf("Failed to get disk UUID")
|
log.With(slog.Any("error", err)).Error("Failed to get disk UUID")
|
||||||
} else {
|
} else {
|
||||||
log.Infof("Disk UUID: %s", uuid)
|
log.Info(fmt.Sprintf("Disk UUID: %s", uuid))
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeBootstrapped, err := initialize.IsNodeBootstrapped(openDevice)
|
nodeBootstrapped, err := initialize.IsNodeBootstrapped(openDevice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to check if node was previously bootstrapped")
|
log.With(slog.Any("error", err)).Error("Failed to check if node was previously bootstrapped")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if nodeBootstrapped {
|
if nodeBootstrapped {
|
||||||
if err := kube.StartKubelet(); err != nil {
|
if err := kube.StartKubelet(); err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to restart kubelet")
|
log.With(slog.Any("error", err)).Error("Failed to restart kubelet")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -53,7 +56,8 @@ func run(issuer atls.Issuer, openDevice vtpm.TPMOpenFunc, fileHandler file.Handl
|
||||||
nodeLock := nodelock.New(openDevice)
|
nodeLock := nodelock.New(openDevice)
|
||||||
initServer, err := initserver.New(context.Background(), nodeLock, kube, issuer, fileHandler, metadata, log)
|
initServer, err := initserver.New(context.Background(), nodeLock, kube, issuer, fileHandler, metadata, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to create init server")
|
log.With(slog.Any("error", err)).Error("Failed to create init server")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
dialer := dialer.New(issuer, nil, &net.Dialer{})
|
dialer := dialer.New(issuer, nil, &net.Dialer{})
|
||||||
|
@ -66,10 +70,11 @@ func run(issuer atls.Issuer, openDevice vtpm.TPMOpenFunc, fileHandler file.Handl
|
||||||
joinClient.Start(cleaner)
|
joinClient.Start(cleaner)
|
||||||
|
|
||||||
if err := initServer.Serve(bindIP, bindPort, cleaner); err != nil {
|
if err := initServer.Serve(bindIP, bindPort, cleaner); err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to serve init server")
|
log.With(slog.Any("error", err)).Error("Failed to serve init server")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("bootstrapper done")
|
log.Info("bootstrapper done")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDiskUUID() (string, error) {
|
func getDiskUUID() (string, error) {
|
||||||
|
|
|
@ -8,9 +8,9 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions/components"
|
"github.com/edgelesssys/constellation/v2/internal/versions/components"
|
||||||
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
|
@ -22,13 +22,13 @@ type clusterFake struct{}
|
||||||
// InitCluster fakes bootstrapping a new cluster with the current node being the master, returning the arguments required to join the cluster.
|
// InitCluster fakes bootstrapping a new cluster with the current node being the master, returning the arguments required to join the cluster.
|
||||||
func (c *clusterFake) InitCluster(
|
func (c *clusterFake) InitCluster(
|
||||||
context.Context, string, string,
|
context.Context, string, string,
|
||||||
bool, components.Components, []string, string, *logger.Logger,
|
bool, components.Components, []string, string, *slog.Logger,
|
||||||
) ([]byte, error) {
|
) ([]byte, error) {
|
||||||
return []byte{}, nil
|
return []byte{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// JoinCluster will fake joining the current node to an existing cluster.
|
// JoinCluster will fake joining the current node to an existing cluster.
|
||||||
func (c *clusterFake) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, components.Components, *logger.Logger) error {
|
func (c *clusterFake) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, components.Components, *slog.Logger) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ go_library(
|
||||||
"@org_golang_google_grpc//keepalive",
|
"@org_golang_google_grpc//keepalive",
|
||||||
"@org_golang_google_grpc//status",
|
"@org_golang_google_grpc//status",
|
||||||
"@org_golang_x_crypto//bcrypt",
|
"@org_golang_x_crypto//bcrypt",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -43,7 +44,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/nodestate"
|
"github.com/edgelesssys/constellation/v2/internal/nodestate"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions/components"
|
"github.com/edgelesssys/constellation/v2/internal/versions/components"
|
||||||
"go.uber.org/zap"
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
|
@ -68,7 +68,7 @@ type Server struct {
|
||||||
|
|
||||||
kmsURI string
|
kmsURI string
|
||||||
|
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
|
|
||||||
journaldCollector journaldCollection
|
journaldCollector journaldCollection
|
||||||
|
|
||||||
|
@ -76,8 +76,8 @@ type Server struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new initialization server.
|
// New creates a new initialization server.
|
||||||
func New(ctx context.Context, lock locker, kube ClusterInitializer, issuer atls.Issuer, fh file.Handler, metadata MetadataAPI, log *logger.Logger) (*Server, error) {
|
func New(ctx context.Context, lock locker, kube ClusterInitializer, issuer atls.Issuer, fh file.Handler, metadata MetadataAPI, log *slog.Logger) (*Server, error) {
|
||||||
log = log.Named("initServer")
|
log = log.WithGroup("initServer")
|
||||||
|
|
||||||
initSecretHash, err := metadata.InitSecretHash(ctx)
|
initSecretHash, err := metadata.InitSecretHash(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -106,7 +106,7 @@ func New(ctx context.Context, lock locker, kube ClusterInitializer, issuer atls.
|
||||||
grpcServer := grpc.NewServer(
|
grpcServer := grpc.NewServer(
|
||||||
grpc.Creds(atlscredentials.New(issuer, nil)),
|
grpc.Creds(atlscredentials.New(issuer, nil)),
|
||||||
grpc.KeepaliveParams(keepalive.ServerParameters{Time: 15 * time.Second}),
|
grpc.KeepaliveParams(keepalive.ServerParameters{Time: 15 * time.Second}),
|
||||||
log.Named("gRPC").GetServerUnaryInterceptor(),
|
logger.GetServerUnaryInterceptor(log.WithGroup("gRPC")),
|
||||||
)
|
)
|
||||||
initproto.RegisterAPIServer(grpcServer, server)
|
initproto.RegisterAPIServer(grpcServer, server)
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ func (s *Server) Serve(ip, port string, cleaner cleaner) error {
|
||||||
return fmt.Errorf("failed to listen: %w", err)
|
return fmt.Errorf("failed to listen: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.log.Infof("Starting")
|
s.log.Info("Starting")
|
||||||
return s.grpcServer.Serve(lis)
|
return s.grpcServer.Serve(lis)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,8 +132,8 @@ func (s *Server) Init(req *initproto.InitRequest, stream initproto.API_InitServe
|
||||||
s.shutdownLock.RLock()
|
s.shutdownLock.RLock()
|
||||||
defer s.shutdownLock.RUnlock()
|
defer s.shutdownLock.RUnlock()
|
||||||
|
|
||||||
log := s.log.With(zap.String("peer", grpclog.PeerAddrFromContext(stream.Context())))
|
log := s.log.With(slog.String("peer", grpclog.PeerAddrFromContext(stream.Context())))
|
||||||
log.Infof("Init called")
|
log.Info("Init called")
|
||||||
|
|
||||||
s.kmsURI = req.KmsUri
|
s.kmsURI = req.KmsUri
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ func (s *Server) Init(req *initproto.InitRequest, stream initproto.API_InitServe
|
||||||
// init does not make sense, so we just stop.
|
// init does not make sense, so we just stop.
|
||||||
//
|
//
|
||||||
// The server stops itself after the current call is done.
|
// The server stops itself after the current call is done.
|
||||||
log.Warnf("Node is already in a join process")
|
log.Warn("Node is already in a join process")
|
||||||
|
|
||||||
err = status.Error(codes.FailedPrecondition, "node is already being activated")
|
err = status.Error(codes.FailedPrecondition, "node is already being activated")
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ func (s *Server) Init(req *initproto.InitRequest, stream initproto.API_InitServe
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Init succeeded")
|
log.Info("Init succeeded")
|
||||||
|
|
||||||
successMessage := &initproto.InitResponse_InitSuccess{
|
successMessage := &initproto.InitResponse_InitSuccess{
|
||||||
InitSuccess: &initproto.InitSuccessResponse{
|
InitSuccess: &initproto.InitSuccessResponse{
|
||||||
|
@ -287,14 +287,14 @@ func (s *Server) sendLogsWithMessage(stream initproto.API_InitServer, message er
|
||||||
|
|
||||||
// Stop stops the initialization server gracefully.
|
// Stop stops the initialization server gracefully.
|
||||||
func (s *Server) Stop() {
|
func (s *Server) Stop() {
|
||||||
s.log.Infof("Stopping")
|
s.log.Info("Stopping")
|
||||||
|
|
||||||
// Make sure to only stop the server if no Init calls are running
|
// Make sure to only stop the server if no Init calls are running
|
||||||
s.shutdownLock.Lock()
|
s.shutdownLock.Lock()
|
||||||
defer s.shutdownLock.Unlock()
|
defer s.shutdownLock.Unlock()
|
||||||
s.grpcServer.GracefulStop()
|
s.grpcServer.GracefulStop()
|
||||||
|
|
||||||
s.log.Infof("Stopped")
|
s.log.Info("Stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) setupDisk(ctx context.Context, cloudKms kms.CloudKMS) error {
|
func (s *Server) setupDisk(ctx context.Context, cloudKms kms.CloudKMS) error {
|
||||||
|
@ -342,7 +342,7 @@ type ClusterInitializer interface {
|
||||||
kubernetesComponents components.Components,
|
kubernetesComponents components.Components,
|
||||||
apiServerCertSANs []string,
|
apiServerCertSANs []string,
|
||||||
serviceCIDR string,
|
serviceCIDR string,
|
||||||
log *logger.Logger,
|
log *slog.Logger,
|
||||||
) ([]byte, error)
|
) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -408,7 +409,7 @@ type stubClusterInitializer struct {
|
||||||
|
|
||||||
func (i *stubClusterInitializer) InitCluster(
|
func (i *stubClusterInitializer) InitCluster(
|
||||||
context.Context, string, string,
|
context.Context, string, string,
|
||||||
bool, components.Components, []string, string, *logger.Logger,
|
bool, components.Components, []string, string, *slog.Logger,
|
||||||
) ([]byte, error) {
|
) ([]byte, error) {
|
||||||
return i.initClusterKubeconfig, i.initClusterErr
|
return i.initClusterKubeconfig, i.initClusterErr
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ go_library(
|
||||||
"//internal/cloud/metadata",
|
"//internal/cloud/metadata",
|
||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/file",
|
"//internal/file",
|
||||||
"//internal/logger",
|
|
||||||
"//internal/nodestate",
|
"//internal/nodestate",
|
||||||
"//internal/role",
|
"//internal/role",
|
||||||
"//internal/versions/components",
|
"//internal/versions/components",
|
||||||
|
@ -23,7 +22,6 @@ go_library(
|
||||||
"@io_k8s_kubernetes//cmd/kubeadm/app/constants",
|
"@io_k8s_kubernetes//cmd/kubeadm/app/constants",
|
||||||
"@io_k8s_utils//clock",
|
"@io_k8s_utils//clock",
|
||||||
"@org_golang_google_grpc//:go_default_library",
|
"@org_golang_google_grpc//:go_default_library",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -33,13 +34,11 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/nodestate"
|
"github.com/edgelesssys/constellation/v2/internal/nodestate"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions/components"
|
"github.com/edgelesssys/constellation/v2/internal/versions/components"
|
||||||
"github.com/edgelesssys/constellation/v2/joinservice/joinproto"
|
"github.com/edgelesssys/constellation/v2/joinservice/joinproto"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"go.uber.org/zap"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
kubeconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
|
@ -73,7 +72,7 @@ type JoinClient struct {
|
||||||
cleaner cleaner
|
cleaner cleaner
|
||||||
metadataAPI MetadataAPI
|
metadataAPI MetadataAPI
|
||||||
|
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
|
|
||||||
mux sync.Mutex
|
mux sync.Mutex
|
||||||
stopC chan struct{}
|
stopC chan struct{}
|
||||||
|
@ -81,7 +80,7 @@ type JoinClient struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new JoinClient.
|
// New creates a new JoinClient.
|
||||||
func New(lock locker, dial grpcDialer, joiner ClusterJoiner, meta MetadataAPI, log *logger.Logger) *JoinClient {
|
func New(lock locker, dial grpcDialer, joiner ClusterJoiner, meta MetadataAPI, log *slog.Logger) *JoinClient {
|
||||||
return &JoinClient{
|
return &JoinClient{
|
||||||
nodeLock: lock,
|
nodeLock: lock,
|
||||||
disk: diskencryption.New(),
|
disk: diskencryption.New(),
|
||||||
|
@ -93,7 +92,7 @@ func New(lock locker, dial grpcDialer, joiner ClusterJoiner, meta MetadataAPI, l
|
||||||
dialer: dial,
|
dialer: dial,
|
||||||
joiner: joiner,
|
joiner: joiner,
|
||||||
metadataAPI: meta,
|
metadataAPI: meta,
|
||||||
log: log.Named("join-client"),
|
log: log.WithGroup("join-client"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +109,7 @@ func (c *JoinClient) Start(cleaner cleaner) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Infof("Starting")
|
c.log.Info("Starting")
|
||||||
c.stopC = make(chan struct{}, 1)
|
c.stopC = make(chan struct{}, 1)
|
||||||
c.stopDone = make(chan struct{}, 1)
|
c.stopDone = make(chan struct{}, 1)
|
||||||
c.cleaner = cleaner
|
c.cleaner = cleaner
|
||||||
|
@ -119,11 +118,11 @@ func (c *JoinClient) Start(cleaner cleaner) {
|
||||||
go func() {
|
go func() {
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
defer func() { c.stopDone <- struct{}{} }()
|
defer func() { c.stopDone <- struct{}{} }()
|
||||||
defer c.log.Infof("Client stopped")
|
defer c.log.Info("Client stopped")
|
||||||
|
|
||||||
diskUUID, err := c.getDiskUUID()
|
diskUUID, err := c.getDiskUUID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.With(zap.Error(err)).Errorf("Failed to get disk UUID")
|
c.log.With(slog.Any("error", err)).Error("Failed to get disk UUID")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.diskUUID = diskUUID
|
c.diskUUID = diskUUID
|
||||||
|
@ -131,12 +130,12 @@ func (c *JoinClient) Start(cleaner cleaner) {
|
||||||
for {
|
for {
|
||||||
err := c.getNodeMetadata()
|
err := c.getNodeMetadata()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.log.With(zap.String("role", c.role.String()), zap.String("name", c.nodeName)).Infof("Received own instance metadata")
|
c.log.With(slog.String("role", c.role.String()), slog.String("name", c.nodeName)).Info("Received own instance metadata")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c.log.With(zap.Error(err)).Errorf("Failed to retrieve instance metadata")
|
c.log.With(slog.Any("error", err)).Error("Failed to retrieve instance metadata")
|
||||||
|
|
||||||
c.log.With(zap.Duration("interval", c.interval)).Infof("Sleeping")
|
c.log.With(slog.Duration("interval", c.interval)).Info("Sleeping")
|
||||||
select {
|
select {
|
||||||
case <-c.stopC:
|
case <-c.stopC:
|
||||||
return
|
return
|
||||||
|
@ -147,15 +146,15 @@ func (c *JoinClient) Start(cleaner cleaner) {
|
||||||
for {
|
for {
|
||||||
err := c.tryJoinWithAvailableServices()
|
err := c.tryJoinWithAvailableServices()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.log.Infof("Joined successfully. Client is shutting down")
|
c.log.Info("Joined successfully. Client is shutting down")
|
||||||
return
|
return
|
||||||
} else if isUnrecoverable(err) {
|
} else if isUnrecoverable(err) {
|
||||||
c.log.With(zap.Error(err)).Errorf("Unrecoverable error occurred")
|
c.log.With(slog.Any("error", err)).Error("Unrecoverable error occurred")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.log.With(zap.Error(err)).Warnf("Join failed for all available endpoints")
|
c.log.With(slog.Any("error", err)).Warn("Join failed for all available endpoints")
|
||||||
|
|
||||||
c.log.With(zap.Duration("interval", c.interval)).Infof("Sleeping")
|
c.log.With(slog.Duration("interval", c.interval)).Info("Sleeping")
|
||||||
select {
|
select {
|
||||||
case <-c.stopC:
|
case <-c.stopC:
|
||||||
return
|
return
|
||||||
|
@ -174,7 +173,7 @@ func (c *JoinClient) Stop() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Infof("Stopping")
|
c.log.Info("Stopping")
|
||||||
|
|
||||||
c.stopC <- struct{}{}
|
c.stopC <- struct{}{}
|
||||||
<-c.stopDone
|
<-c.stopDone
|
||||||
|
@ -182,7 +181,7 @@ func (c *JoinClient) Stop() {
|
||||||
c.stopC = nil
|
c.stopC = nil
|
||||||
c.stopDone = nil
|
c.stopDone = nil
|
||||||
|
|
||||||
c.log.Infof("Stopped")
|
c.log.Info("Stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *JoinClient) tryJoinWithAvailableServices() error {
|
func (c *JoinClient) tryJoinWithAvailableServices() error {
|
||||||
|
@ -231,7 +230,7 @@ func (c *JoinClient) join(serviceEndpoint string) error {
|
||||||
|
|
||||||
conn, err := c.dialer.Dial(ctx, serviceEndpoint)
|
conn, err := c.dialer.Dial(ctx, serviceEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.With(zap.String("endpoint", serviceEndpoint), zap.Error(err)).Errorf("Join service unreachable")
|
c.log.With(slog.String("endpoint", serviceEndpoint), slog.Any("error", err)).Error("Join service unreachable")
|
||||||
return fmt.Errorf("dialing join service endpoint: %w", err)
|
return fmt.Errorf("dialing join service endpoint: %w", err)
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
@ -244,7 +243,7 @@ func (c *JoinClient) join(serviceEndpoint string) error {
|
||||||
}
|
}
|
||||||
ticket, err := protoClient.IssueJoinTicket(ctx, req)
|
ticket, err := protoClient.IssueJoinTicket(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.With(zap.String("endpoint", serviceEndpoint), zap.Error(err)).Errorf("Issuing join ticket failed")
|
c.log.With(slog.String("endpoint", serviceEndpoint), slog.Any("error", err)).Error("Issuing join ticket failed")
|
||||||
return fmt.Errorf("issuing join ticket: %w", err)
|
return fmt.Errorf("issuing join ticket: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +268,7 @@ func (c *JoinClient) startNodeAndJoin(ticket *joinproto.IssueJoinTicketResponse,
|
||||||
|
|
||||||
nodeLockAcquired, err := c.nodeLock.TryLockOnce(clusterID)
|
nodeLockAcquired, err := c.nodeLock.TryLockOnce(clusterID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.With(zap.Error(err)).Errorf("Acquiring node lock failed")
|
c.log.With(slog.Any("error", err)).Error("Acquiring node lock failed")
|
||||||
return fmt.Errorf("acquiring node lock: %w", err)
|
return fmt.Errorf("acquiring node lock: %w", err)
|
||||||
}
|
}
|
||||||
if !nodeLockAcquired {
|
if !nodeLockAcquired {
|
||||||
|
@ -322,12 +321,12 @@ func (c *JoinClient) getNodeMetadata() error {
|
||||||
ctx, cancel := c.timeoutCtx()
|
ctx, cancel := c.timeoutCtx()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
c.log.Debugf("Requesting node metadata from metadata API")
|
c.log.Debug("Requesting node metadata from metadata API")
|
||||||
inst, err := c.metadataAPI.Self(ctx)
|
inst, err := c.metadataAPI.Self(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.log.With(zap.Any("instance", inst)).Debugf("Received node metadata")
|
c.log.With(slog.Any("instance", inst)).Debug("Received node metadata")
|
||||||
|
|
||||||
if inst.Name == "" {
|
if inst.Name == "" {
|
||||||
return errors.New("got instance metadata with empty name")
|
return errors.New("got instance metadata with empty name")
|
||||||
|
@ -371,7 +370,7 @@ func (c *JoinClient) getDiskUUID() (string, error) {
|
||||||
func (c *JoinClient) getControlPlaneIPs(ctx context.Context) ([]string, error) {
|
func (c *JoinClient) getControlPlaneIPs(ctx context.Context) ([]string, error) {
|
||||||
instances, err := c.metadataAPI.List(ctx)
|
instances, err := c.metadataAPI.List(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.With(zap.Error(err)).Errorf("Failed to list instances from metadata API")
|
c.log.With(slog.Any("error", err)).Error("Failed to list instances from metadata API")
|
||||||
return nil, fmt.Errorf("listing instances from metadata API: %w", err)
|
return nil, fmt.Errorf("listing instances from metadata API: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +381,7 @@ func (c *JoinClient) getControlPlaneIPs(ctx context.Context) ([]string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.With(zap.Strings("IPs", ips)).Infof("Received control plane endpoints")
|
c.log.With(slog.Any("IPs", ips)).Info("Received control plane endpoints")
|
||||||
return ips, nil
|
return ips, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +422,7 @@ type ClusterJoiner interface {
|
||||||
args *kubeadm.BootstrapTokenDiscovery,
|
args *kubeadm.BootstrapTokenDiscovery,
|
||||||
peerRole role.Role,
|
peerRole role.Role,
|
||||||
k8sComponents components.Components,
|
k8sComponents components.Components,
|
||||||
log *logger.Logger,
|
log *slog.Logger,
|
||||||
) error
|
) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ package joinclient
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -401,7 +402,7 @@ type stubClusterJoiner struct {
|
||||||
joinClusterErr error
|
joinClusterErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *stubClusterJoiner) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, components.Components, *logger.Logger) error {
|
func (j *stubClusterJoiner) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, components.Components, *slog.Logger) error {
|
||||||
j.joinClusterCalled = true
|
j.joinClusterCalled = true
|
||||||
return j.joinClusterErr
|
return j.joinClusterErr
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,11 @@ go_library(
|
||||||
"//internal/cloud/metadata",
|
"//internal/cloud/metadata",
|
||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/kubernetes",
|
"//internal/kubernetes",
|
||||||
"//internal/logger",
|
|
||||||
"//internal/role",
|
"//internal/role",
|
||||||
"//internal/versions/components",
|
"//internal/versions/components",
|
||||||
"@io_k8s_api//core/v1:core",
|
"@io_k8s_api//core/v1:core",
|
||||||
"@io_k8s_apimachinery//pkg/apis/meta/v1:meta",
|
"@io_k8s_apimachinery//pkg/apis/meta/v1:meta",
|
||||||
"@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm/v1beta3",
|
"@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm/v1beta3",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ go_library(
|
||||||
"//internal/file",
|
"//internal/file",
|
||||||
"//internal/installer",
|
"//internal/installer",
|
||||||
"//internal/kubernetes",
|
"//internal/kubernetes",
|
||||||
"//internal/logger",
|
|
||||||
"//internal/versions/components",
|
"//internal/versions/components",
|
||||||
"@com_github_coreos_go_systemd_v22//dbus",
|
"@com_github_coreos_go_systemd_v22//dbus",
|
||||||
"@com_github_spf13_afero//:afero",
|
"@com_github_spf13_afero//:afero",
|
||||||
|
@ -29,7 +28,6 @@ go_library(
|
||||||
"@io_k8s_kubelet//config/v1beta1",
|
"@io_k8s_kubelet//config/v1beta1",
|
||||||
"@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm/v1beta3",
|
"@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm/v1beta3",
|
||||||
"@io_k8s_kubernetes//cmd/kubeadm/app/constants",
|
"@io_k8s_kubernetes//cmd/kubeadm/app/constants",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -30,9 +31,7 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/crypto"
|
"github.com/edgelesssys/constellation/v2/internal/crypto"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/installer"
|
"github.com/edgelesssys/constellation/v2/internal/installer"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -87,7 +86,7 @@ func (k *KubernetesUtil) InstallComponents(ctx context.Context, kubernetesCompon
|
||||||
// InitCluster instruments kubeadm to initialize the K8s cluster.
|
// InitCluster instruments kubeadm to initialize the K8s cluster.
|
||||||
// On success an admin kubeconfig file is returned.
|
// On success an admin kubeconfig file is returned.
|
||||||
func (k *KubernetesUtil) InitCluster(
|
func (k *KubernetesUtil) InitCluster(
|
||||||
ctx context.Context, initConfig []byte, nodeName, clusterName string, ips []net.IP, conformanceMode bool, log *logger.Logger,
|
ctx context.Context, initConfig []byte, nodeName, clusterName string, ips []net.IP, conformanceMode bool, log *slog.Logger,
|
||||||
) ([]byte, error) {
|
) ([]byte, error) {
|
||||||
// TODO(3u13r): audit policy should be user input
|
// TODO(3u13r): audit policy should be user input
|
||||||
auditPolicy, err := resources.NewDefaultAuditPolicy().Marshal()
|
auditPolicy, err := resources.NewDefaultAuditPolicy().Marshal()
|
||||||
|
@ -108,7 +107,7 @@ func (k *KubernetesUtil) InitCluster(
|
||||||
}
|
}
|
||||||
|
|
||||||
// preflight
|
// preflight
|
||||||
log.Infof("Running kubeadm preflight checks")
|
log.Info("Running kubeadm preflight checks")
|
||||||
cmd := exec.CommandContext(ctx, constants.KubeadmPath, "init", "phase", "preflight", "-v=5", "--config", initConfigFile.Name())
|
cmd := exec.CommandContext(ctx, constants.KubeadmPath, "init", "phase", "preflight", "-v=5", "--config", initConfigFile.Name())
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -120,7 +119,7 @@ func (k *KubernetesUtil) InitCluster(
|
||||||
}
|
}
|
||||||
|
|
||||||
// create CA certs
|
// create CA certs
|
||||||
log.Infof("Creating Kubernetes control-plane certificates and keys")
|
log.Info("Creating Kubernetes control-plane certificates and keys")
|
||||||
cmd = exec.CommandContext(ctx, constants.KubeadmPath, "init", "phase", "certs", "all", "-v=5", "--config", initConfigFile.Name())
|
cmd = exec.CommandContext(ctx, constants.KubeadmPath, "init", "phase", "certs", "all", "-v=5", "--config", initConfigFile.Name())
|
||||||
out, err = cmd.CombinedOutput()
|
out, err = cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -132,19 +131,19 @@ func (k *KubernetesUtil) InitCluster(
|
||||||
}
|
}
|
||||||
|
|
||||||
// create kubelet key and CA signed certificate for the node
|
// create kubelet key and CA signed certificate for the node
|
||||||
log.Infof("Creating signed kubelet certificate")
|
log.Info("Creating signed kubelet certificate")
|
||||||
if err := k.createSignedKubeletCert(nodeName, ips); err != nil {
|
if err := k.createSignedKubeletCert(nodeName, ips); err != nil {
|
||||||
return nil, fmt.Errorf("creating signed kubelete certificate: %w", err)
|
return nil, fmt.Errorf("creating signed kubelete certificate: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create static pods directory for all nodes (the Kubelets on the worker nodes also expect the path to exist)
|
// Create static pods directory for all nodes (the Kubelets on the worker nodes also expect the path to exist)
|
||||||
log.Infof("Creating static Pod directory /etc/kubernetes/manifests")
|
log.Info("Creating static Pod directory /etc/kubernetes/manifests")
|
||||||
if err := os.MkdirAll("/etc/kubernetes/manifests", os.ModePerm); err != nil {
|
if err := os.MkdirAll("/etc/kubernetes/manifests", os.ModePerm); err != nil {
|
||||||
return nil, fmt.Errorf("creating static pods directory: %w", err)
|
return nil, fmt.Errorf("creating static pods directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize the cluster
|
// initialize the cluster
|
||||||
log.Infof("Initializing the cluster using kubeadm init")
|
log.Info("Initializing the cluster using kubeadm init")
|
||||||
skipPhases := "--skip-phases=preflight,certs"
|
skipPhases := "--skip-phases=preflight,certs"
|
||||||
if !conformanceMode {
|
if !conformanceMode {
|
||||||
skipPhases += ",addon/kube-proxy"
|
skipPhases += ",addon/kube-proxy"
|
||||||
|
@ -159,11 +158,11 @@ func (k *KubernetesUtil) InitCluster(
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("kubeadm init: %w", err)
|
return nil, fmt.Errorf("kubeadm init: %w", err)
|
||||||
}
|
}
|
||||||
log.With(zap.String("output", string(out))).Infof("kubeadm init succeeded")
|
log.With(slog.String("output", string(out))).Info("kubeadm init succeeded")
|
||||||
|
|
||||||
userName := clusterName + "-admin"
|
userName := clusterName + "-admin"
|
||||||
|
|
||||||
log.With(zap.String("userName", userName)).Infof("Creating admin kubeconfig file")
|
log.With(slog.String("userName", userName)).Info("Creating admin kubeconfig file")
|
||||||
cmd = exec.CommandContext(
|
cmd = exec.CommandContext(
|
||||||
ctx, constants.KubeadmPath, "kubeconfig", "user",
|
ctx, constants.KubeadmPath, "kubeconfig", "user",
|
||||||
"--client-name", userName, "--config", initConfigFile.Name(), "--org", user.SystemPrivilegedGroup,
|
"--client-name", userName, "--config", initConfigFile.Name(), "--org", user.SystemPrivilegedGroup,
|
||||||
|
@ -176,12 +175,12 @@ func (k *KubernetesUtil) InitCluster(
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("kubeadm kubeconfig user: %w", err)
|
return nil, fmt.Errorf("kubeadm kubeconfig user: %w", err)
|
||||||
}
|
}
|
||||||
log.Infof("kubeadm kubeconfig user succeeded")
|
log.Info("kubeadm kubeconfig user succeeded")
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// JoinCluster joins existing Kubernetes cluster using kubeadm join.
|
// JoinCluster joins existing Kubernetes cluster using kubeadm join.
|
||||||
func (k *KubernetesUtil) JoinCluster(ctx context.Context, joinConfig []byte, log *logger.Logger) error {
|
func (k *KubernetesUtil) JoinCluster(ctx context.Context, joinConfig []byte, log *slog.Logger) error {
|
||||||
// TODO(3u13r): audit policy should be user input
|
// TODO(3u13r): audit policy should be user input
|
||||||
auditPolicy, err := resources.NewDefaultAuditPolicy().Marshal()
|
auditPolicy, err := resources.NewDefaultAuditPolicy().Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -201,7 +200,7 @@ func (k *KubernetesUtil) JoinCluster(ctx context.Context, joinConfig []byte, log
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create static pods directory for all nodes (the Kubelets on the worker nodes also expect the path to exist)
|
// Create static pods directory for all nodes (the Kubelets on the worker nodes also expect the path to exist)
|
||||||
log.Infof("Creating static Pod directory /etc/kubernetes/manifests")
|
log.Info("Creating static Pod directory /etc/kubernetes/manifests")
|
||||||
if err := os.MkdirAll("/etc/kubernetes/manifests", os.ModePerm); err != nil {
|
if err := os.MkdirAll("/etc/kubernetes/manifests", os.ModePerm); err != nil {
|
||||||
return fmt.Errorf("creating static pods directory: %w", err)
|
return fmt.Errorf("creating static pods directory: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -216,7 +215,7 @@ func (k *KubernetesUtil) JoinCluster(ctx context.Context, joinConfig []byte, log
|
||||||
}
|
}
|
||||||
return fmt.Errorf("kubeadm join: %w", err)
|
return fmt.Errorf("kubeadm join: %w", err)
|
||||||
}
|
}
|
||||||
log.With(zap.String("output", string(out))).Infof("kubeadm join succeeded")
|
log.With(slog.String("output", string(out))).Info("kubeadm join succeeded")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,15 @@ package kubernetes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions/components"
|
"github.com/edgelesssys/constellation/v2/internal/versions/components"
|
||||||
)
|
)
|
||||||
|
|
||||||
type clusterUtil interface {
|
type clusterUtil interface {
|
||||||
InstallComponents(ctx context.Context, kubernetesComponents components.Components) error
|
InstallComponents(ctx context.Context, kubernetesComponents components.Components) error
|
||||||
InitCluster(ctx context.Context, initConfig []byte, nodeName, clusterName string, ips []net.IP, conformanceMode bool, log *logger.Logger) ([]byte, error)
|
InitCluster(ctx context.Context, initConfig []byte, nodeName, clusterName string, ips []net.IP, conformanceMode bool, log *slog.Logger) ([]byte, error)
|
||||||
JoinCluster(ctx context.Context, joinConfig []byte, log *logger.Logger) error
|
JoinCluster(ctx context.Context, joinConfig []byte, log *slog.Logger) error
|
||||||
StartKubelet() error
|
StartKubelet() error
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ package kubernetes
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -20,10 +21,8 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/kubernetes"
|
"github.com/edgelesssys/constellation/v2/internal/kubernetes"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions/components"
|
"github.com/edgelesssys/constellation/v2/internal/versions/components"
|
||||||
"go.uber.org/zap"
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
|
@ -69,9 +68,9 @@ func New(cloudProvider string, clusterUtil clusterUtil, configProvider configura
|
||||||
|
|
||||||
// InitCluster initializes a new Kubernetes cluster and applies pod network provider.
|
// InitCluster initializes a new Kubernetes cluster and applies pod network provider.
|
||||||
func (k *KubeWrapper) InitCluster(
|
func (k *KubeWrapper) InitCluster(
|
||||||
ctx context.Context, versionString, clusterName string, conformanceMode bool, kubernetesComponents components.Components, apiServerCertSANs []string, serviceCIDR string, log *logger.Logger,
|
ctx context.Context, versionString, clusterName string, conformanceMode bool, kubernetesComponents components.Components, apiServerCertSANs []string, serviceCIDR string, log *slog.Logger,
|
||||||
) ([]byte, error) {
|
) ([]byte, error) {
|
||||||
log.With(zap.String("version", versionString)).Infof("Installing Kubernetes components")
|
log.With(slog.String("version", versionString)).Info("Installing Kubernetes components")
|
||||||
if err := k.clusterUtil.InstallComponents(ctx, kubernetesComponents); err != nil {
|
if err := k.clusterUtil.InstallComponents(ctx, kubernetesComponents); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -79,7 +78,7 @@ func (k *KubeWrapper) InitCluster(
|
||||||
var validIPs []net.IP
|
var validIPs []net.IP
|
||||||
|
|
||||||
// Step 1: retrieve cloud metadata for Kubernetes configuration
|
// Step 1: retrieve cloud metadata for Kubernetes configuration
|
||||||
log.Infof("Retrieving node metadata")
|
log.Info("Retrieving node metadata")
|
||||||
instance, err := k.providerMetadata.Self(ctx)
|
instance, err := k.providerMetadata.Self(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("retrieving own instance metadata: %w", err)
|
return nil, fmt.Errorf("retrieving own instance metadata: %w", err)
|
||||||
|
@ -108,14 +107,14 @@ func (k *KubeWrapper) InitCluster(
|
||||||
certSANs = append(certSANs, apiServerCertSANs...)
|
certSANs = append(certSANs, apiServerCertSANs...)
|
||||||
|
|
||||||
log.With(
|
log.With(
|
||||||
zap.String("nodeName", nodeName),
|
slog.String("nodeName", nodeName),
|
||||||
zap.String("providerID", instance.ProviderID),
|
slog.String("providerID", instance.ProviderID),
|
||||||
zap.String("nodeIP", nodeIP),
|
slog.String("nodeIP", nodeIP),
|
||||||
zap.String("controlPlaneHost", controlPlaneHost),
|
slog.String("controlPlaneHost", controlPlaneHost),
|
||||||
zap.String("controlPlanePort", controlPlanePort),
|
slog.String("controlPlanePort", controlPlanePort),
|
||||||
zap.String("certSANs", strings.Join(certSANs, ",")),
|
slog.String("certSANs", strings.Join(certSANs, ",")),
|
||||||
zap.String("podCIDR", subnetworkPodCIDR),
|
slog.String("podCIDR", subnetworkPodCIDR),
|
||||||
).Infof("Setting information for node")
|
).Info("Setting information for node")
|
||||||
|
|
||||||
// Step 2: configure kubeadm init config
|
// Step 2: configure kubeadm init config
|
||||||
ccmSupported := cloudprovider.FromString(k.cloudProvider) == cloudprovider.Azure ||
|
ccmSupported := cloudprovider.FromString(k.cloudProvider) == cloudprovider.Azure ||
|
||||||
|
@ -133,7 +132,7 @@ func (k *KubeWrapper) InitCluster(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("encoding kubeadm init configuration as YAML: %w", err)
|
return nil, fmt.Errorf("encoding kubeadm init configuration as YAML: %w", err)
|
||||||
}
|
}
|
||||||
log.Infof("Initializing Kubernetes cluster")
|
log.Info("Initializing Kubernetes cluster")
|
||||||
kubeConfig, err := k.clusterUtil.InitCluster(ctx, initConfigYAML, nodeName, clusterName, validIPs, conformanceMode, log)
|
kubeConfig, err := k.clusterUtil.InitCluster(ctx, initConfigYAML, nodeName, clusterName, validIPs, conformanceMode, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("kubeadm init: %w", err)
|
return nil, fmt.Errorf("kubeadm init: %w", err)
|
||||||
|
@ -178,7 +177,7 @@ func (k *KubeWrapper) InitCluster(
|
||||||
return nil, fmt.Errorf("annotating node with Kubernetes components hash: %w", err)
|
return nil, fmt.Errorf("annotating node with Kubernetes components hash: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Setting up internal-config ConfigMap")
|
log.Info("Setting up internal-config ConfigMap")
|
||||||
if err := k.setupInternalConfigMap(ctx); err != nil {
|
if err := k.setupInternalConfigMap(ctx); err != nil {
|
||||||
return nil, fmt.Errorf("failed to setup internal ConfigMap: %w", err)
|
return nil, fmt.Errorf("failed to setup internal ConfigMap: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -186,14 +185,14 @@ func (k *KubeWrapper) InitCluster(
|
||||||
}
|
}
|
||||||
|
|
||||||
// JoinCluster joins existing Kubernetes cluster.
|
// JoinCluster joins existing Kubernetes cluster.
|
||||||
func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTokenDiscovery, peerRole role.Role, k8sComponents components.Components, log *logger.Logger) error {
|
func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTokenDiscovery, peerRole role.Role, k8sComponents components.Components, log *slog.Logger) error {
|
||||||
log.With("k8sComponents", k8sComponents).Infof("Installing provided kubernetes components")
|
log.With("k8sComponents", k8sComponents).Info("Installing provided kubernetes components")
|
||||||
if err := k.clusterUtil.InstallComponents(ctx, k8sComponents); err != nil {
|
if err := k.clusterUtil.InstallComponents(ctx, k8sComponents); err != nil {
|
||||||
return fmt.Errorf("installing kubernetes components: %w", err)
|
return fmt.Errorf("installing kubernetes components: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 1: retrieve cloud metadata for Kubernetes configuration
|
// Step 1: retrieve cloud metadata for Kubernetes configuration
|
||||||
log.Infof("Retrieving node metadata")
|
log.Info("Retrieving node metadata")
|
||||||
instance, err := k.providerMetadata.Self(ctx)
|
instance, err := k.providerMetadata.Self(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("retrieving own instance metadata: %w", err)
|
return fmt.Errorf("retrieving own instance metadata: %w", err)
|
||||||
|
@ -214,12 +213,12 @@ func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTo
|
||||||
args.APIServerEndpoint = net.JoinHostPort(loadBalancerHost, loadBalancerPort)
|
args.APIServerEndpoint = net.JoinHostPort(loadBalancerHost, loadBalancerPort)
|
||||||
|
|
||||||
log.With(
|
log.With(
|
||||||
zap.String("nodeName", nodeName),
|
slog.String("nodeName", nodeName),
|
||||||
zap.String("providerID", providerID),
|
slog.String("providerID", providerID),
|
||||||
zap.String("nodeIP", nodeInternalIP),
|
slog.String("nodeIP", nodeInternalIP),
|
||||||
zap.String("loadBalancerHost", loadBalancerHost),
|
slog.String("loadBalancerHost", loadBalancerHost),
|
||||||
zap.String("loadBalancerPort", loadBalancerPort),
|
slog.String("loadBalancerPort", loadBalancerPort),
|
||||||
).Infof("Setting information for node")
|
).Info("Setting information for node")
|
||||||
|
|
||||||
// Step 2: configure kubeadm join config
|
// Step 2: configure kubeadm join config
|
||||||
ccmSupported := cloudprovider.FromString(k.cloudProvider) == cloudprovider.Azure ||
|
ccmSupported := cloudprovider.FromString(k.cloudProvider) == cloudprovider.Azure ||
|
||||||
|
@ -238,7 +237,7 @@ func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("encoding kubeadm join configuration as YAML: %w", err)
|
return fmt.Errorf("encoding kubeadm join configuration as YAML: %w", err)
|
||||||
}
|
}
|
||||||
log.With(zap.String("apiServerEndpoint", args.APIServerEndpoint)).Infof("Joining Kubernetes cluster")
|
log.With(slog.String("apiServerEndpoint", args.APIServerEndpoint)).Info("Joining Kubernetes cluster")
|
||||||
if err := k.clusterUtil.JoinCluster(ctx, joinConfigYAML, log); err != nil {
|
if err := k.clusterUtil.JoinCluster(ctx, joinConfigYAML, log); err != nil {
|
||||||
return fmt.Errorf("joining cluster: %v; %w ", string(joinConfigYAML), err)
|
return fmt.Errorf("joining cluster: %v; %w ", string(joinConfigYAML), err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ package kubernetes
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -440,7 +441,7 @@ func (s *stubClusterUtil) InstallComponents(_ context.Context, _ components.Comp
|
||||||
return s.installComponentsErr
|
return s.installComponentsErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stubClusterUtil) InitCluster(_ context.Context, initConfig []byte, _, _ string, _ []net.IP, _ bool, _ *logger.Logger) ([]byte, error) {
|
func (s *stubClusterUtil) InitCluster(_ context.Context, initConfig []byte, _, _ string, _ []net.IP, _ bool, _ *slog.Logger) ([]byte, error) {
|
||||||
s.initConfigs = append(s.initConfigs, initConfig)
|
s.initConfigs = append(s.initConfigs, initConfig)
|
||||||
return s.kubeconfig, s.initClusterErr
|
return s.kubeconfig, s.initClusterErr
|
||||||
}
|
}
|
||||||
|
@ -465,7 +466,7 @@ func (s *stubClusterUtil) SetupNodeOperator(_ context.Context, _ k8sapi.Client,
|
||||||
return s.setupNodeOperatorErr
|
return s.setupNodeOperatorErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stubClusterUtil) JoinCluster(_ context.Context, joinConfig []byte, _ *logger.Logger) error {
|
func (s *stubClusterUtil) JoinCluster(_ context.Context, joinConfig []byte, _ *slog.Logger) error {
|
||||||
s.joinConfigs = append(s.joinConfigs, joinConfig)
|
s.joinConfigs = append(s.joinConfigs, joinConfig)
|
||||||
return s.joinClusterErr
|
return s.joinClusterErr
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,6 @@ go_library(
|
||||||
"@io_k8s_sigs_yaml//:yaml",
|
"@io_k8s_sigs_yaml//:yaml",
|
||||||
"@org_golang_google_grpc//:go_default_library",
|
"@org_golang_google_grpc//:go_default_library",
|
||||||
"@org_golang_x_mod//semver",
|
"@org_golang_x_mod//semver",
|
||||||
"@org_uber_go_zap//zapcore",
|
|
||||||
] + select({
|
] + select({
|
||||||
"@io_bazel_rules_go//go/platform:android_amd64": [
|
"@io_bazel_rules_go//go/platform:android_amd64": [
|
||||||
"@org_golang_x_sys//unix",
|
"@org_golang_x_sys//unix",
|
||||||
|
|
|
@ -212,7 +212,6 @@ func runApply(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
spinner, err := newSpinnerOrStderr(cmd)
|
spinner, err := newSpinnerOrStderr(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -396,7 +395,7 @@ func (a *applyCmd) apply(
|
||||||
|
|
||||||
// Apply Attestation Config
|
// Apply Attestation Config
|
||||||
if !a.flags.skipPhases.contains(skipAttestationConfigPhase) {
|
if !a.flags.skipPhases.contains(skipAttestationConfigPhase) {
|
||||||
a.log.Debugf("Applying new attestation config to cluster")
|
a.log.Debug("Applying new attestation config to cluster")
|
||||||
if err := a.applyJoinConfig(cmd, conf.GetAttestationConfig(), stateFile.ClusterValues.MeasurementSalt); err != nil {
|
if err := a.applyJoinConfig(cmd, conf.GetAttestationConfig(), stateFile.ClusterValues.MeasurementSalt); err != nil {
|
||||||
return fmt.Errorf("applying attestation config: %w", err)
|
return fmt.Errorf("applying attestation config: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -443,7 +442,7 @@ func (a *applyCmd) apply(
|
||||||
|
|
||||||
func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher) (*config.Config, *state.State, error) {
|
func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationconfigapi.Fetcher) (*config.Config, *state.State, error) {
|
||||||
// Read user's config and state file
|
// Read user's config and state file
|
||||||
a.log.Debugf("Reading config from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))
|
a.log.Debug(fmt.Sprintf("Reading config from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename)))
|
||||||
conf, err := config.New(a.fileHandler, constants.ConfigFilename, configFetcher, a.flags.force)
|
conf, err := config.New(a.fileHandler, constants.ConfigFilename, configFetcher, a.flags.force)
|
||||||
var configValidationErr *config.ValidationError
|
var configValidationErr *config.ValidationError
|
||||||
if errors.As(err, &configValidationErr) {
|
if errors.As(err, &configValidationErr) {
|
||||||
|
@ -453,7 +452,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Debugf("Reading state file from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename))
|
a.log.Debug(fmt.Sprintf("Reading state file from %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename)))
|
||||||
stateFile, err := state.CreateOrRead(a.fileHandler, constants.StateFilename)
|
stateFile, err := state.CreateOrRead(a.fileHandler, constants.StateFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -464,7 +463,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc
|
||||||
// We don't run "hard" verification of skip-phases flags and state file here,
|
// We don't run "hard" verification of skip-phases flags and state file here,
|
||||||
// a user may still end up skipping phases that could result in errors later on.
|
// a user may still end up skipping phases that could result in errors later on.
|
||||||
// However, we perform basic steps, like ensuring init phase is not skipped if
|
// However, we perform basic steps, like ensuring init phase is not skipped if
|
||||||
a.log.Debugf("Validating state file")
|
a.log.Debug("Validating state file")
|
||||||
preCreateValidateErr := stateFile.Validate(state.PreCreate, conf.GetAttestationConfig().GetVariant())
|
preCreateValidateErr := stateFile.Validate(state.PreCreate, conf.GetAttestationConfig().GetVariant())
|
||||||
preInitValidateErr := stateFile.Validate(state.PreInit, conf.GetAttestationConfig().GetVariant())
|
preInitValidateErr := stateFile.Validate(state.PreInit, conf.GetAttestationConfig().GetVariant())
|
||||||
postInitValidateErr := stateFile.Validate(state.PostInit, conf.GetAttestationConfig().GetVariant())
|
postInitValidateErr := stateFile.Validate(state.PostInit, conf.GetAttestationConfig().GetVariant())
|
||||||
|
@ -473,7 +472,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc
|
||||||
// in which case the workspace has to be clean
|
// in which case the workspace has to be clean
|
||||||
if preCreateValidateErr == nil {
|
if preCreateValidateErr == nil {
|
||||||
// We can't skip the infrastructure phase if no infrastructure has been defined
|
// We can't skip the infrastructure phase if no infrastructure has been defined
|
||||||
a.log.Debugf("State file is in pre-create state, checking workspace")
|
a.log.Debug("State file is in pre-create state, checking workspace")
|
||||||
if a.flags.skipPhases.contains(skipInfrastructurePhase) {
|
if a.flags.skipPhases.contains(skipInfrastructurePhase) {
|
||||||
return nil, nil, preInitValidateErr
|
return nil, nil, preInitValidateErr
|
||||||
}
|
}
|
||||||
|
@ -482,7 +481,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Debugf("No Terraform state found in current working directory. Preparing to create a new cluster.")
|
a.log.Debug("No Terraform state found in current working directory. Preparing to create a new cluster.")
|
||||||
printCreateWarnings(cmd.ErrOrStderr(), conf)
|
printCreateWarnings(cmd.ErrOrStderr(), conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,7 +490,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc
|
||||||
// If so, we need to run the init RPC
|
// If so, we need to run the init RPC
|
||||||
if preInitValidateErr == nil || (preCreateValidateErr == nil && !a.flags.skipPhases.contains(skipInitPhase)) {
|
if preInitValidateErr == nil || (preCreateValidateErr == nil && !a.flags.skipPhases.contains(skipInitPhase)) {
|
||||||
// We can't skip the init phase if the init RPC hasn't been run yet
|
// We can't skip the init phase if the init RPC hasn't been run yet
|
||||||
a.log.Debugf("State file is in pre-init state, checking workspace")
|
a.log.Debug("State file is in pre-init state, checking workspace")
|
||||||
if a.flags.skipPhases.contains(skipInitPhase) {
|
if a.flags.skipPhases.contains(skipInitPhase) {
|
||||||
return nil, nil, postInitValidateErr
|
return nil, nil, postInitValidateErr
|
||||||
}
|
}
|
||||||
|
@ -507,7 +506,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc
|
||||||
// If the state file is in a post-init state,
|
// If the state file is in a post-init state,
|
||||||
// we need to make sure specific files exist in the workspace
|
// we need to make sure specific files exist in the workspace
|
||||||
if postInitValidateErr == nil {
|
if postInitValidateErr == nil {
|
||||||
a.log.Debugf("State file is in post-init state, checking workspace")
|
a.log.Debug("State file is in post-init state, checking workspace")
|
||||||
if err := a.checkPostInitFilesExist(); err != nil {
|
if err := a.checkPostInitFilesExist(); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -522,16 +521,16 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc
|
||||||
// If we need to run the init RPC, the version has to be valid
|
// If we need to run the init RPC, the version has to be valid
|
||||||
// Otherwise, we are able to use an outdated version, meaning we skip the K8s upgrade
|
// Otherwise, we are able to use an outdated version, meaning we skip the K8s upgrade
|
||||||
// We skip version validation if the user explicitly skips the Kubernetes phase
|
// We skip version validation if the user explicitly skips the Kubernetes phase
|
||||||
a.log.Debugf("Validating Kubernetes version %s", conf.KubernetesVersion)
|
a.log.Debug(fmt.Sprintf("Validating Kubernetes version %s", conf.KubernetesVersion))
|
||||||
validVersion, err := versions.NewValidK8sVersion(string(conf.KubernetesVersion), true)
|
validVersion, err := versions.NewValidK8sVersion(string(conf.KubernetesVersion), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Debugf("Kubernetes version not valid: %s", err)
|
a.log.Debug(fmt.Sprintf("Kubernetes version not valid: %s", err))
|
||||||
if !a.flags.skipPhases.contains(skipInitPhase) {
|
if !a.flags.skipPhases.contains(skipInitPhase) {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !a.flags.skipPhases.contains(skipK8sPhase) {
|
if !a.flags.skipPhases.contains(skipK8sPhase) {
|
||||||
a.log.Debugf("Checking if user wants to continue anyway")
|
a.log.Debug("Checking if user wants to continue anyway")
|
||||||
if !a.flags.yes {
|
if !a.flags.yes {
|
||||||
confirmed, err := askToConfirm(cmd,
|
confirmed, err := askToConfirm(cmd,
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
|
@ -548,7 +547,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc
|
||||||
}
|
}
|
||||||
|
|
||||||
a.flags.skipPhases.add(skipK8sPhase)
|
a.flags.skipPhases.add(skipK8sPhase)
|
||||||
a.log.Debugf("Outdated Kubernetes version accepted, Kubernetes upgrade will be skipped")
|
a.log.Debug("Outdated Kubernetes version accepted, Kubernetes upgrade will be skipped")
|
||||||
}
|
}
|
||||||
|
|
||||||
validVersionString, err := versions.ResolveK8sPatchVersion(xsemver.MajorMinor(string(conf.KubernetesVersion)))
|
validVersionString, err := versions.ResolveK8sPatchVersion(xsemver.MajorMinor(string(conf.KubernetesVersion)))
|
||||||
|
@ -564,7 +563,7 @@ func (a *applyCmd) validateInputs(cmd *cobra.Command, configFetcher attestationc
|
||||||
cmd.PrintErrf("Warning: Constellation with Kubernetes %s is still in preview. Use only for evaluation purposes.\n", validVersion)
|
cmd.PrintErrf("Warning: Constellation with Kubernetes %s is still in preview. Use only for evaluation purposes.\n", validVersion)
|
||||||
}
|
}
|
||||||
conf.KubernetesVersion = validVersion
|
conf.KubernetesVersion = validVersion
|
||||||
a.log.Debugf("Target Kubernetes version set to %s", conf.KubernetesVersion)
|
a.log.Debug(fmt.Sprintf("Target Kubernetes version set to %s", conf.KubernetesVersion))
|
||||||
|
|
||||||
// Validate microservice version (helm versions) in the user's config matches the version of the CLI
|
// Validate microservice version (helm versions) in the user's config matches the version of the CLI
|
||||||
// This makes sure we catch potential errors early, not just after we already ran Terraform migrations or the init RPC
|
// This makes sure we catch potential errors early, not just after we already ran Terraform migrations or the init RPC
|
||||||
|
@ -592,9 +591,9 @@ func (a *applyCmd) applyJoinConfig(cmd *cobra.Command, newConfig config.Attestat
|
||||||
) error {
|
) error {
|
||||||
clusterAttestationConfig, err := a.applier.GetClusterAttestationConfig(cmd.Context(), newConfig.GetVariant())
|
clusterAttestationConfig, err := a.applier.GetClusterAttestationConfig(cmd.Context(), newConfig.GetVariant())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Debugf("Getting cluster attestation config failed: %s", err)
|
a.log.Debug(fmt.Sprintf("Getting cluster attestation config failed: %s", err))
|
||||||
if k8serrors.IsNotFound(err) {
|
if k8serrors.IsNotFound(err) {
|
||||||
a.log.Debugf("Creating new join config")
|
a.log.Debug("Creating new join config")
|
||||||
return a.applier.ApplyJoinConfig(cmd.Context(), newConfig, measurementSalt)
|
return a.applier.ApplyJoinConfig(cmd.Context(), newConfig, measurementSalt)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("getting cluster attestation config: %w", err)
|
return fmt.Errorf("getting cluster attestation config: %w", err)
|
||||||
|
@ -606,7 +605,7 @@ func (a *applyCmd) applyJoinConfig(cmd *cobra.Command, newConfig config.Attestat
|
||||||
return fmt.Errorf("comparing attestation configs: %w", err)
|
return fmt.Errorf("comparing attestation configs: %w", err)
|
||||||
}
|
}
|
||||||
if equal {
|
if equal {
|
||||||
a.log.Debugf("Current attestation config is equal to the new config, nothing to do")
|
a.log.Debug("Current attestation config is equal to the new config, nothing to do")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,7 +684,7 @@ func (a *applyCmd) checkCreateFilesClean() error {
|
||||||
if err := a.checkInitFilesClean(); err != nil {
|
if err := a.checkInitFilesClean(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
a.log.Debugf("Checking Terraform state")
|
a.log.Debug("Checking Terraform state")
|
||||||
if _, err := a.fileHandler.Stat(constants.TerraformWorkingDir); err == nil {
|
if _, err := a.fileHandler.Stat(constants.TerraformWorkingDir); err == nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"terraform state %q already exists in working directory, run 'constellation terminate' before creating a new cluster",
|
"terraform state %q already exists in working directory, run 'constellation terminate' before creating a new cluster",
|
||||||
|
@ -700,7 +699,7 @@ func (a *applyCmd) checkCreateFilesClean() error {
|
||||||
|
|
||||||
// checkInitFilesClean ensures that the workspace is clean before running the init RPC.
|
// checkInitFilesClean ensures that the workspace is clean before running the init RPC.
|
||||||
func (a *applyCmd) checkInitFilesClean() error {
|
func (a *applyCmd) checkInitFilesClean() error {
|
||||||
a.log.Debugf("Checking admin configuration file")
|
a.log.Debug("Checking admin configuration file")
|
||||||
if _, err := a.fileHandler.Stat(constants.AdminConfFilename); err == nil {
|
if _, err := a.fileHandler.Stat(constants.AdminConfFilename); err == nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"file %q already exists in working directory, run 'constellation terminate' before creating a new cluster",
|
"file %q already exists in working directory, run 'constellation terminate' before creating a new cluster",
|
||||||
|
@ -709,7 +708,7 @@ func (a *applyCmd) checkInitFilesClean() error {
|
||||||
} else if !errors.Is(err, fs.ErrNotExist) {
|
} else if !errors.Is(err, fs.ErrNotExist) {
|
||||||
return fmt.Errorf("checking for %q: %w", a.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename), err)
|
return fmt.Errorf("checking for %q: %w", a.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename), err)
|
||||||
}
|
}
|
||||||
a.log.Debugf("Checking master secrets file")
|
a.log.Debug("Checking master secrets file")
|
||||||
if _, err := a.fileHandler.Stat(constants.MasterSecretFilename); err == nil {
|
if _, err := a.fileHandler.Stat(constants.MasterSecretFilename); err == nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"file %q already exists in working directory. Constellation won't overwrite previous master secrets. Move it somewhere or delete it before creating a new cluster",
|
"file %q already exists in working directory. Constellation won't overwrite previous master secrets. Move it somewhere or delete it before creating a new cluster",
|
||||||
|
@ -805,20 +804,20 @@ type warnLogger struct {
|
||||||
log debugLog
|
log debugLog
|
||||||
}
|
}
|
||||||
|
|
||||||
// Infof messages are reduced to debug messages, since we don't want
|
// Info messages are reduced to debug messages, since we don't want
|
||||||
// the extra info when using the CLI without setting the debug flag.
|
// the extra info when using the CLI without setting the debug flag.
|
||||||
func (wl warnLogger) Infof(fmtStr string, args ...any) {
|
func (wl warnLogger) Info(msg string, args ...any) {
|
||||||
wl.log.Debugf(fmtStr, args...)
|
wl.log.Debug(msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warnf prints a formatted warning from the validator.
|
// Warn prints a formatted warning from the validator.
|
||||||
func (wl warnLogger) Warnf(fmtStr string, args ...any) {
|
func (wl warnLogger) Warn(msg string, args ...any) {
|
||||||
wl.cmd.PrintErrf("Warning: %s\n", fmt.Sprintf(fmtStr, args...))
|
wl.cmd.PrintErrf("Warning: %s %s\n", msg, fmt.Sprint(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
type warnLog interface {
|
type warnLog interface {
|
||||||
Warnf(format string, args ...any)
|
Warn(msg string, args ...any)
|
||||||
Infof(format string, args ...any)
|
Info(msg string, args ...any)
|
||||||
}
|
}
|
||||||
|
|
||||||
// applier is used to run the different phases of the apply command.
|
// applier is used to run the different phases of the apply command.
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
// runHelmApply handles installing or upgrading helm charts for the cluster.
|
// runHelmApply handles installing or upgrading helm charts for the cluster.
|
||||||
func (a *applyCmd) runHelmApply(cmd *cobra.Command, conf *config.Config, stateFile *state.State, upgradeDir string,
|
func (a *applyCmd) runHelmApply(cmd *cobra.Command, conf *config.Config, stateFile *state.State, upgradeDir string,
|
||||||
) error {
|
) error {
|
||||||
a.log.Debugf("Installing or upgrading Helm charts")
|
a.log.Debug("Installing or upgrading Helm charts")
|
||||||
var masterSecret uri.MasterSecret
|
var masterSecret uri.MasterSecret
|
||||||
if err := a.fileHandler.ReadJSON(constants.MasterSecretFilename, &masterSecret); err != nil {
|
if err := a.fileHandler.ReadJSON(constants.MasterSecretFilename, &masterSecret); err != nil {
|
||||||
return fmt.Errorf("reading master secret: %w", err)
|
return fmt.Errorf("reading master secret: %w", err)
|
||||||
|
@ -44,13 +44,13 @@ func (a *applyCmd) runHelmApply(cmd *cobra.Command, conf *config.Config, stateFi
|
||||||
AllowDestructive: helm.DenyDestructive,
|
AllowDestructive: helm.DenyDestructive,
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Debugf("Getting service account URI")
|
a.log.Debug("Getting service account URI")
|
||||||
serviceAccURI, err := cloudcmd.GetMarshaledServiceAccountURI(conf, a.fileHandler)
|
serviceAccURI, err := cloudcmd.GetMarshaledServiceAccountURI(conf, a.fileHandler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Debugf("Preparing Helm charts")
|
a.log.Debug("Preparing Helm charts")
|
||||||
executor, includesUpgrades, err := a.applier.PrepareHelmCharts(options, stateFile, serviceAccURI, masterSecret, conf.Provider.OpenStack)
|
executor, includesUpgrades, err := a.applier.PrepareHelmCharts(options, stateFile, serviceAccURI, masterSecret, conf.Provider.OpenStack)
|
||||||
if errors.Is(err, helm.ErrConfirmationMissing) {
|
if errors.Is(err, helm.ErrConfirmationMissing) {
|
||||||
if !a.flags.yes {
|
if !a.flags.yes {
|
||||||
|
@ -75,12 +75,12 @@ func (a *applyCmd) runHelmApply(cmd *cobra.Command, conf *config.Config, stateFi
|
||||||
cmd.PrintErrln(err)
|
cmd.PrintErrln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Debugf("Backing up Helm charts")
|
a.log.Debug("Backing up Helm charts")
|
||||||
if err := a.backupHelmCharts(cmd.Context(), executor, includesUpgrades, upgradeDir); err != nil {
|
if err := a.backupHelmCharts(cmd.Context(), executor, includesUpgrades, upgradeDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Debugf("Applying Helm charts")
|
a.log.Debug("Applying Helm charts")
|
||||||
if !a.flags.skipPhases.contains(skipInitPhase) {
|
if !a.flags.skipPhases.contains(skipInitPhase) {
|
||||||
a.spinner.Start("Installing Kubernetes components ", false)
|
a.spinner.Start("Installing Kubernetes components ", false)
|
||||||
} else {
|
} else {
|
||||||
|
@ -108,10 +108,10 @@ func (a *applyCmd) backupHelmCharts(
|
||||||
if err := executor.SaveCharts(chartDir, a.fileHandler); err != nil {
|
if err := executor.SaveCharts(chartDir, a.fileHandler); err != nil {
|
||||||
return fmt.Errorf("saving Helm charts to disk: %w", err)
|
return fmt.Errorf("saving Helm charts to disk: %w", err)
|
||||||
}
|
}
|
||||||
a.log.Debugf("Helm charts saved to %s", a.flags.pathPrefixer.PrefixPrintablePath(chartDir))
|
a.log.Debug(fmt.Sprintf("Helm charts saved to %s", a.flags.pathPrefixer.PrefixPrintablePath(chartDir)))
|
||||||
|
|
||||||
if includesUpgrades {
|
if includesUpgrades {
|
||||||
a.log.Debugf("Creating backup of CRDs and CRs")
|
a.log.Debug("Creating backup of CRDs and CRs")
|
||||||
crds, err := a.applier.BackupCRDs(ctx, a.fileHandler, upgradeDir)
|
crds, err := a.applier.BackupCRDs(ctx, a.fileHandler, upgradeDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating CRD backup: %w", err)
|
return fmt.Errorf("creating CRD backup: %w", err)
|
||||||
|
|
|
@ -29,13 +29,13 @@ import (
|
||||||
// On success, it writes the Kubernetes admin config file to disk.
|
// On success, it writes the Kubernetes admin config file to disk.
|
||||||
// Therefore it is skipped if the Kubernetes admin config file already exists.
|
// Therefore it is skipped if the Kubernetes admin config file already exists.
|
||||||
func (a *applyCmd) runInit(cmd *cobra.Command, conf *config.Config, stateFile *state.State) (*bytes.Buffer, error) {
|
func (a *applyCmd) runInit(cmd *cobra.Command, conf *config.Config, stateFile *state.State) (*bytes.Buffer, error) {
|
||||||
a.log.Debugf("Creating aTLS Validator for %s", conf.GetAttestationConfig().GetVariant())
|
a.log.Debug(fmt.Sprintf("Creating aTLS Validator for %s", conf.GetAttestationConfig().GetVariant()))
|
||||||
validator, err := choose.Validator(conf.GetAttestationConfig(), a.wLog)
|
validator, err := choose.Validator(conf.GetAttestationConfig(), a.wLog)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("creating validator: %w", err)
|
return nil, fmt.Errorf("creating validator: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Debugf("Running init RPC")
|
a.log.Debug("Running init RPC")
|
||||||
masterSecret, err := a.generateAndPersistMasterSecret(cmd.OutOrStdout())
|
masterSecret, err := a.generateAndPersistMasterSecret(cmd.OutOrStdout())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("generating master secret: %w", err)
|
return nil, fmt.Errorf("generating master secret: %w", err)
|
||||||
|
@ -74,9 +74,9 @@ func (a *applyCmd) runInit(cmd *cobra.Command, conf *config.Config, stateFile *s
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
a.log.Debugf("Initialization request successful")
|
a.log.Debug("Initialization request successful")
|
||||||
|
|
||||||
a.log.Debugf("Buffering init success message")
|
a.log.Debug("Buffering init success message")
|
||||||
bufferedOutput := &bytes.Buffer{}
|
bufferedOutput := &bytes.Buffer{}
|
||||||
if err := a.writeInitOutput(stateFile, resp, a.flags.mergeConfigs, bufferedOutput, measurementSalt); err != nil {
|
if err := a.writeInitOutput(stateFile, resp, a.flags.mergeConfigs, bufferedOutput, measurementSalt); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -121,7 +121,7 @@ func (a *applyCmd) writeInitOutput(
|
||||||
if err := a.fileHandler.Write(constants.AdminConfFilename, initResp.Kubeconfig, file.OptNone); err != nil {
|
if err := a.fileHandler.Write(constants.AdminConfFilename, initResp.Kubeconfig, file.OptNone); err != nil {
|
||||||
return fmt.Errorf("writing kubeconfig: %w", err)
|
return fmt.Errorf("writing kubeconfig: %w", err)
|
||||||
}
|
}
|
||||||
a.log.Debugf("Kubeconfig written to %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename))
|
a.log.Debug(fmt.Sprintf("Kubeconfig written to %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename)))
|
||||||
|
|
||||||
if mergeConfig {
|
if mergeConfig {
|
||||||
if err := a.merger.mergeConfigs(constants.AdminConfFilename, a.fileHandler); err != nil {
|
if err := a.merger.mergeConfigs(constants.AdminConfFilename, a.fileHandler); err != nil {
|
||||||
|
@ -136,7 +136,7 @@ func (a *applyCmd) writeInitOutput(
|
||||||
return fmt.Errorf("writing Constellation state file: %w", err)
|
return fmt.Errorf("writing Constellation state file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Debugf("Constellation state file written to %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename))
|
a.log.Debug(fmt.Sprintf("Constellation state file written to %s", a.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename)))
|
||||||
|
|
||||||
if !mergeConfig {
|
if !mergeConfig {
|
||||||
fmt.Fprintln(wr, "You can now connect to your cluster by executing:")
|
fmt.Fprintln(wr, "You can now connect to your cluster by executing:")
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
|
|
||||||
// runTerraformApply checks if changes to Terraform are required and applies them.
|
// runTerraformApply checks if changes to Terraform are required and applies them.
|
||||||
func (a *applyCmd) runTerraformApply(cmd *cobra.Command, conf *config.Config, stateFile *state.State, upgradeDir string) error {
|
func (a *applyCmd) runTerraformApply(cmd *cobra.Command, conf *config.Config, stateFile *state.State, upgradeDir string) error {
|
||||||
a.log.Debugf("Checking if Terraform migrations are required")
|
a.log.Debug("Checking if Terraform migrations are required")
|
||||||
terraformClient, removeClient, err := a.newInfraApplier(cmd.Context())
|
terraformClient, removeClient, err := a.newInfraApplier(cmd.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating Terraform client: %w", err)
|
return fmt.Errorf("creating Terraform client: %w", err)
|
||||||
|
@ -39,18 +39,18 @@ func (a *applyCmd) runTerraformApply(cmd *cobra.Command, conf *config.Config, st
|
||||||
if changesRequired, err := a.planTerraformChanges(cmd, conf, terraformClient); err != nil {
|
if changesRequired, err := a.planTerraformChanges(cmd, conf, terraformClient); err != nil {
|
||||||
return fmt.Errorf("planning Terraform migrations: %w", err)
|
return fmt.Errorf("planning Terraform migrations: %w", err)
|
||||||
} else if !changesRequired {
|
} else if !changesRequired {
|
||||||
a.log.Debugf("No changes to infrastructure required, skipping Terraform migrations")
|
a.log.Debug("No changes to infrastructure required, skipping Terraform migrations")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Debugf("Apply new Terraform resources for infrastructure changes")
|
a.log.Debug("Apply new Terraform resources for infrastructure changes")
|
||||||
newInfraState, err := a.applyTerraformChanges(cmd, conf, terraformClient, upgradeDir, isNewCluster)
|
newInfraState, err := a.applyTerraformChanges(cmd, conf, terraformClient, upgradeDir, isNewCluster)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge the original state with the new infrastructure values
|
// Merge the original state with the new infrastructure values
|
||||||
a.log.Debugf("Updating state file with new infrastructure state")
|
a.log.Debug("Updating state file with new infrastructure state")
|
||||||
if _, err := stateFile.Merge(
|
if _, err := stateFile.Merge(
|
||||||
// temporary state with new infrastructure values
|
// temporary state with new infrastructure values
|
||||||
state.New().SetInfrastructure(newInfraState),
|
state.New().SetInfrastructure(newInfraState),
|
||||||
|
@ -68,7 +68,7 @@ func (a *applyCmd) runTerraformApply(cmd *cobra.Command, conf *config.Config, st
|
||||||
// planTerraformChanges checks if any changes to the Terraform state are required.
|
// planTerraformChanges checks if any changes to the Terraform state are required.
|
||||||
// If no state exists, this function will return true and the caller should create a new state.
|
// If no state exists, this function will return true and the caller should create a new state.
|
||||||
func (a *applyCmd) planTerraformChanges(cmd *cobra.Command, conf *config.Config, terraformClient cloudApplier) (bool, error) {
|
func (a *applyCmd) planTerraformChanges(cmd *cobra.Command, conf *config.Config, terraformClient cloudApplier) (bool, error) {
|
||||||
a.log.Debugf("Planning Terraform changes")
|
a.log.Debug("Planning Terraform changes")
|
||||||
|
|
||||||
// Check if there are any Terraform changes to apply
|
// Check if there are any Terraform changes to apply
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ func (a *applyCmd) planTerraformChanges(cmd *cobra.Command, conf *config.Config,
|
||||||
//
|
//
|
||||||
// var manualMigrations []terraform.StateMigration
|
// var manualMigrations []terraform.StateMigration
|
||||||
// for _, migration := range manualMigrations {
|
// for _, migration := range manualMigrations {
|
||||||
// u.log.Debugf("Adding manual Terraform migration: %s", migration.DisplayName)
|
// u.log.Debug(fmt.Sprintf("Adding manual Terraform migration: %s", migration.DisplayName))
|
||||||
// u.infraApplier.AddManualStateMigration(migration)
|
// u.infraApplier.AddManualStateMigration(migration)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ func (a *applyCmd) applyTerraformChangesWithMessage(
|
||||||
return state.Infrastructure{}, errors.New(abortErrorMsg)
|
return state.Infrastructure{}, errors.New(abortErrorMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.log.Debugf("Applying Terraform changes")
|
a.log.Debug("Applying Terraform changes")
|
||||||
|
|
||||||
a.spinner.Start(progressMsg, false)
|
a.spinner.Start(progressMsg, false)
|
||||||
infraState, err := terraformClient.Apply(cmd.Context(), csp, attestation, rollbackBehavior)
|
infraState, err := terraformClient.Apply(cmd.Context(), csp, attestation, rollbackBehavior)
|
||||||
|
@ -186,7 +186,7 @@ func printCreateInfo(out io.Writer, conf *config.Config, log debugLog) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(otherGroupNames) > 0 {
|
if len(otherGroupNames) > 0 {
|
||||||
log.Debugf("Creating %d additional node groups: %v", len(otherGroupNames), otherGroupNames)
|
log.Debug(fmt.Sprintf("Creating %d additional node groups: %v", len(otherGroupNames), otherGroupNames))
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(out, "The following Constellation cluster will be created:\n")
|
fmt.Fprintf(out, "The following Constellation cluster will be created:\n")
|
||||||
|
|
|
@ -93,7 +93,6 @@ func runConfigFetchMeasurements(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
fileHandler := file.NewHandler(afero.NewOsFs())
|
fileHandler := file.NewHandler(afero.NewOsFs())
|
||||||
rekor, err := sigstore.NewRekor()
|
rekor, err := sigstore.NewRekor()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -105,7 +104,7 @@ func runConfigFetchMeasurements(cmd *cobra.Command, _ []string) error {
|
||||||
if err := cfm.flags.parse(cmd.Flags()); err != nil {
|
if err := cfm.flags.parse(cmd.Flags()); err != nil {
|
||||||
return fmt.Errorf("parsing flags: %w", err)
|
return fmt.Errorf("parsing flags: %w", err)
|
||||||
}
|
}
|
||||||
cfm.log.Debugf("Using flags %+v", cfm.flags)
|
cfm.log.Debug(fmt.Sprintf("Using flags %+v", cfm.flags))
|
||||||
|
|
||||||
fetcher := attestationconfigapi.NewFetcherWithClient(http.DefaultClient, constants.CDNRepositoryURL)
|
fetcher := attestationconfigapi.NewFetcherWithClient(http.DefaultClient, constants.CDNRepositoryURL)
|
||||||
return cfm.configFetchMeasurements(cmd, fileHandler, fetcher)
|
return cfm.configFetchMeasurements(cmd, fileHandler, fetcher)
|
||||||
|
@ -119,7 +118,7 @@ func (cfm *configFetchMeasurementsCmd) configFetchMeasurements(
|
||||||
return errors.New("fetching measurements is not supported")
|
return errors.New("fetching measurements is not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
cfm.log.Debugf("Loading configuration file from %q", cfm.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))
|
cfm.log.Debug(fmt.Sprintf("Loading configuration file from %q", cfm.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename)))
|
||||||
|
|
||||||
conf, err := config.New(fileHandler, constants.ConfigFilename, fetcher, cfm.flags.force)
|
conf, err := config.New(fileHandler, constants.ConfigFilename, fetcher, cfm.flags.force)
|
||||||
var configValidationErr *config.ValidationError
|
var configValidationErr *config.ValidationError
|
||||||
|
@ -134,11 +133,11 @@ func (cfm *configFetchMeasurementsCmd) configFetchMeasurements(
|
||||||
cmd.PrintErrln("Configured image doesn't look like a released production image. Double check image before deploying to production.")
|
cmd.PrintErrln("Configured image doesn't look like a released production image. Double check image before deploying to production.")
|
||||||
}
|
}
|
||||||
|
|
||||||
cfm.log.Debugf("Creating context")
|
cfm.log.Debug("Creating context")
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
cfm.log.Debugf("Updating URLs")
|
cfm.log.Debug("Updating URLs")
|
||||||
if err := cfm.flags.updateURLs(conf); err != nil {
|
if err := cfm.flags.updateURLs(conf); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -153,14 +152,14 @@ func (cfm *configFetchMeasurementsCmd) configFetchMeasurements(
|
||||||
return fmt.Errorf("fetching and verifying measurements: %w", err)
|
return fmt.Errorf("fetching and verifying measurements: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfm.log.Debugf("Measurements: %#v\n", fetchedMeasurements)
|
cfm.log.Debug(fmt.Sprintf("Measurements: %#v\n", fetchedMeasurements))
|
||||||
|
|
||||||
cfm.log.Debugf("Updating measurements in configuration")
|
cfm.log.Debug("Updating measurements in configuration")
|
||||||
conf.UpdateMeasurements(fetchedMeasurements)
|
conf.UpdateMeasurements(fetchedMeasurements)
|
||||||
if err := fileHandler.WriteYAML(constants.ConfigFilename, conf, file.OptOverwrite); err != nil {
|
if err := fileHandler.WriteYAML(constants.ConfigFilename, conf, file.OptOverwrite); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cfm.log.Debugf("Configuration written to %s", cfm.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))
|
cfm.log.Debug(fmt.Sprintf("Configuration written to %s", cfm.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename)))
|
||||||
cmd.Print("Successfully fetched measurements and updated Configuration\n")
|
cmd.Print("Successfully fetched measurements and updated Configuration\n")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,6 @@ func runConfigGenerate(cmd *cobra.Command, args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
|
|
||||||
fileHandler := file.NewHandler(afero.NewOsFs())
|
fileHandler := file.NewHandler(afero.NewOsFs())
|
||||||
provider := cloudprovider.FromString(args[0])
|
provider := cloudprovider.FromString(args[0])
|
||||||
|
@ -86,13 +85,13 @@ func runConfigGenerate(cmd *cobra.Command, args []string) error {
|
||||||
if err := cg.flags.parse(cmd.Flags()); err != nil {
|
if err := cg.flags.parse(cmd.Flags()); err != nil {
|
||||||
return fmt.Errorf("parsing flags: %w", err)
|
return fmt.Errorf("parsing flags: %w", err)
|
||||||
}
|
}
|
||||||
log.Debugf("Parsed flags as %+v", cg.flags)
|
log.Debug(fmt.Sprintf("Parsed flags as %+v", cg.flags))
|
||||||
|
|
||||||
return cg.configGenerate(cmd, fileHandler, provider, args[0])
|
return cg.configGenerate(cmd, fileHandler, provider, args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cg *configGenerateCmd) configGenerate(cmd *cobra.Command, fileHandler file.Handler, provider cloudprovider.Provider, rawProvider string) error {
|
func (cg *configGenerateCmd) configGenerate(cmd *cobra.Command, fileHandler file.Handler, provider cloudprovider.Provider, rawProvider string) error {
|
||||||
cg.log.Debugf("Using cloud provider %s", provider.String())
|
cg.log.Debug(fmt.Sprintf("Using cloud provider %s", provider.String()))
|
||||||
|
|
||||||
// Config creation
|
// Config creation
|
||||||
conf, err := createConfigWithAttestationVariant(provider, rawProvider, cg.flags.attestationVariant)
|
conf, err := createConfigWithAttestationVariant(provider, rawProvider, cg.flags.attestationVariant)
|
||||||
|
@ -100,7 +99,7 @@ func (cg *configGenerateCmd) configGenerate(cmd *cobra.Command, fileHandler file
|
||||||
return fmt.Errorf("creating config: %w", err)
|
return fmt.Errorf("creating config: %w", err)
|
||||||
}
|
}
|
||||||
conf.KubernetesVersion = cg.flags.k8sVersion
|
conf.KubernetesVersion = cg.flags.k8sVersion
|
||||||
cg.log.Debugf("Writing YAML data to configuration file")
|
cg.log.Debug("Writing YAML data to configuration file")
|
||||||
if err := fileHandler.WriteYAML(constants.ConfigFilename, conf, file.OptMkdirAll); err != nil {
|
if err := fileHandler.WriteYAML(constants.ConfigFilename, conf, file.OptMkdirAll); err != nil {
|
||||||
return fmt.Errorf("writing config file: %w", err)
|
return fmt.Errorf("writing config file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,6 @@ func runIAMCreate(cmd *cobra.Command, providerCreator providerIAMCreator, provid
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
|
|
||||||
iamCreator := &iamCreator{
|
iamCreator := &iamCreator{
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
|
@ -134,7 +133,7 @@ func (c *iamCreator) create(ctx context.Context) error {
|
||||||
|
|
||||||
var conf config.Config
|
var conf config.Config
|
||||||
if c.flags.updateConfig {
|
if c.flags.updateConfig {
|
||||||
c.log.Debugf("Parsing config %s", c.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))
|
c.log.Debug(fmt.Sprintf("Parsing config %s", c.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename)))
|
||||||
if err := c.fileHandler.ReadYAML(constants.ConfigFilename, &conf); err != nil {
|
if err := c.fileHandler.ReadYAML(constants.ConfigFilename, &conf); err != nil {
|
||||||
return fmt.Errorf("error reading the configuration file: %w", err)
|
return fmt.Errorf("error reading the configuration file: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -154,7 +153,7 @@ func (c *iamCreator) create(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.cmd.Println() // Print empty line to separate after spinner ended.
|
c.cmd.Println() // Print empty line to separate after spinner ended.
|
||||||
c.log.Debugf("Successfully created the IAM cloud resources")
|
c.log.Debug("Successfully created the IAM cloud resources")
|
||||||
|
|
||||||
err = c.providerCreator.parseAndWriteIDFile(iamFile, c.fileHandler)
|
err = c.providerCreator.parseAndWriteIDFile(iamFile, c.fileHandler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -162,7 +161,7 @@ func (c *iamCreator) create(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.flags.updateConfig {
|
if c.flags.updateConfig {
|
||||||
c.log.Debugf("Writing IAM configuration to %s", c.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))
|
c.log.Debug(fmt.Sprintf("Writing IAM configuration to %s", c.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename)))
|
||||||
c.providerCreator.writeOutputValuesToConfig(&conf, iamFile)
|
c.providerCreator.writeOutputValuesToConfig(&conf, iamFile)
|
||||||
if err := c.fileHandler.WriteYAML(constants.ConfigFilename, conf, file.OptOverwrite); err != nil {
|
if err := c.fileHandler.WriteYAML(constants.ConfigFilename, conf, file.OptOverwrite); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -58,7 +58,6 @@ func runIAMDestroy(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
spinner := newSpinner(cmd.ErrOrStderr())
|
spinner := newSpinner(cmd.ErrOrStderr())
|
||||||
destroyer := cloudcmd.NewIAMDestroyer()
|
destroyer := cloudcmd.NewIAMDestroyer()
|
||||||
fsHandler := file.NewHandler(afero.NewOsFs())
|
fsHandler := file.NewHandler(afero.NewOsFs())
|
||||||
|
@ -78,25 +77,25 @@ type destroyCmd struct {
|
||||||
|
|
||||||
func (c *destroyCmd) iamDestroy(cmd *cobra.Command, spinner spinnerInterf, destroyer iamDestroyer, fsHandler file.Handler) error {
|
func (c *destroyCmd) iamDestroy(cmd *cobra.Command, spinner spinnerInterf, destroyer iamDestroyer, fsHandler file.Handler) error {
|
||||||
// check if there is a possibility that the cluster is still running by looking out for specific files
|
// check if there is a possibility that the cluster is still running by looking out for specific files
|
||||||
c.log.Debugf("Checking if %q exists", c.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename))
|
c.log.Debug(fmt.Sprintf("Checking if %q exists", c.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename)))
|
||||||
if _, err := fsHandler.Stat(constants.AdminConfFilename); !errors.Is(err, os.ErrNotExist) {
|
if _, err := fsHandler.Stat(constants.AdminConfFilename); !errors.Is(err, os.ErrNotExist) {
|
||||||
return fmt.Errorf("file %q still exists, please make sure to terminate your cluster before destroying your IAM configuration", c.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename))
|
return fmt.Errorf("file %q still exists, please make sure to terminate your cluster before destroying your IAM configuration", c.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Debugf("Checking if %q exists", c.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename))
|
c.log.Debug(fmt.Sprintf("Checking if %q exists", c.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename)))
|
||||||
if _, err := fsHandler.Stat(constants.StateFilename); !errors.Is(err, os.ErrNotExist) {
|
if _, err := fsHandler.Stat(constants.StateFilename); !errors.Is(err, os.ErrNotExist) {
|
||||||
return fmt.Errorf("file %q still exists, please make sure to terminate your cluster before destroying your IAM configuration", c.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename))
|
return fmt.Errorf("file %q still exists, please make sure to terminate your cluster before destroying your IAM configuration", c.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename))
|
||||||
}
|
}
|
||||||
|
|
||||||
gcpFileExists := false
|
gcpFileExists := false
|
||||||
|
|
||||||
c.log.Debugf("Checking if %q exists", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename))
|
c.log.Debug(fmt.Sprintf("Checking if %q exists", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename)))
|
||||||
if _, err := fsHandler.Stat(constants.GCPServiceAccountKeyFilename); err != nil {
|
if _, err := fsHandler.Stat(constants.GCPServiceAccountKeyFilename); err != nil {
|
||||||
if !errors.Is(err, os.ErrNotExist) {
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.log.Debugf("%q exists", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename))
|
c.log.Debug(fmt.Sprintf("%q exists", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename)))
|
||||||
gcpFileExists = true
|
gcpFileExists = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +116,7 @@ func (c *destroyCmd) iamDestroy(cmd *cobra.Command, spinner spinnerInterf, destr
|
||||||
}
|
}
|
||||||
|
|
||||||
if gcpFileExists {
|
if gcpFileExists {
|
||||||
c.log.Debugf("Starting to delete %q", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename))
|
c.log.Debug(fmt.Sprintf("Starting to delete %q", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename)))
|
||||||
proceed, err := c.deleteGCPServiceAccountKeyFile(cmd, destroyer, fsHandler)
|
proceed, err := c.deleteGCPServiceAccountKeyFile(cmd, destroyer, fsHandler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -128,7 +127,7 @@ func (c *destroyCmd) iamDestroy(cmd *cobra.Command, spinner spinnerInterf, destr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Debugf("Starting to destroy IAM configuration")
|
c.log.Debug("Starting to destroy IAM configuration")
|
||||||
|
|
||||||
spinner.Start("Destroying IAM configuration", false)
|
spinner.Start("Destroying IAM configuration", false)
|
||||||
defer spinner.Stop()
|
defer spinner.Stop()
|
||||||
|
@ -144,18 +143,18 @@ func (c *destroyCmd) iamDestroy(cmd *cobra.Command, spinner spinnerInterf, destr
|
||||||
func (c *destroyCmd) deleteGCPServiceAccountKeyFile(cmd *cobra.Command, destroyer iamDestroyer, fsHandler file.Handler) (bool, error) {
|
func (c *destroyCmd) deleteGCPServiceAccountKeyFile(cmd *cobra.Command, destroyer iamDestroyer, fsHandler file.Handler) (bool, error) {
|
||||||
var fileSaKey gcpshared.ServiceAccountKey
|
var fileSaKey gcpshared.ServiceAccountKey
|
||||||
|
|
||||||
c.log.Debugf("Parsing %q", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename))
|
c.log.Debug(fmt.Sprintf("Parsing %q", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename)))
|
||||||
if err := fsHandler.ReadJSON(constants.GCPServiceAccountKeyFilename, &fileSaKey); err != nil {
|
if err := fsHandler.ReadJSON(constants.GCPServiceAccountKeyFilename, &fileSaKey); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Debugf("Getting service account key from the tfstate")
|
c.log.Debug("Getting service account key from the tfstate")
|
||||||
tfSaKey, err := destroyer.GetTfStateServiceAccountKey(cmd.Context(), constants.TerraformIAMWorkingDir)
|
tfSaKey, err := destroyer.GetTfStateServiceAccountKey(cmd.Context(), constants.TerraformIAMWorkingDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Debugf("Checking if keys are the same")
|
c.log.Debug("Checking if keys are the same")
|
||||||
if tfSaKey != fileSaKey {
|
if tfSaKey != fileSaKey {
|
||||||
cmd.Printf(
|
cmd.Printf(
|
||||||
"The key in %q don't match up with your Terraform state. %q will not be deleted.\n",
|
"The key in %q don't match up with your Terraform state. %q will not be deleted.\n",
|
||||||
|
@ -169,6 +168,6 @@ func (c *destroyCmd) deleteGCPServiceAccountKeyFile(cmd *cobra.Command, destroye
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Debugf("Successfully deleted %q", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename))
|
c.log.Debug(fmt.Sprintf("Successfully deleted %q", c.flags.pathPrefixer.PrefixPrintablePath(constants.GCPServiceAccountKeyFilename)))
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ func (i iamUpgradeApplyCmd) iamUpgradeApply(cmd *cobra.Command, iamUpgrader iamU
|
||||||
return errors.New("IAM upgrade aborted by user")
|
return errors.New("IAM upgrade aborted by user")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i.log.Debugf("Applying Terraform IAM migrations")
|
i.log.Debug("Applying Terraform IAM migrations")
|
||||||
if err := iamUpgrader.ApplyIAMUpgrade(cmd.Context(), conf.GetProvider()); err != nil {
|
if err := iamUpgrader.ApplyIAMUpgrade(cmd.Context(), conf.GetProvider()); err != nil {
|
||||||
return fmt.Errorf("applying terraform migrations: %w", err)
|
return fmt.Errorf("applying terraform migrations: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ func (c *kubeconfigMerger) mergeConfigs(configPath string, fileHandler file.Hand
|
||||||
clientcmd.RecommendedHomeFile,
|
clientcmd.RecommendedHomeFile,
|
||||||
configPath, // our config should overwrite the default config
|
configPath, // our config should overwrite the default config
|
||||||
}
|
}
|
||||||
c.log.Debugf("Kubeconfig file loading precedence: %v", loadingRules.Precedence)
|
c.log.Debug(fmt.Sprintf("Kubeconfig file loading precedence: %v", loadingRules.Precedence))
|
||||||
|
|
||||||
// merge the kubeconfigs
|
// merge the kubeconfigs
|
||||||
cfg, err := loadingRules.Load()
|
cfg, err := loadingRules.Load()
|
||||||
|
@ -82,7 +82,7 @@ func (c *kubeconfigMerger) mergeConfigs(configPath string, fileHandler file.Hand
|
||||||
|
|
||||||
// Set the current context to the cluster we just created
|
// Set the current context to the cluster we just created
|
||||||
cfg.CurrentContext = constellConfig.CurrentContext
|
cfg.CurrentContext = constellConfig.CurrentContext
|
||||||
c.log.Debugf("Set current context to %s", cfg.CurrentContext)
|
c.log.Debug(fmt.Sprintf("Set current context to %s", cfg.CurrentContext))
|
||||||
|
|
||||||
json, err := runtime.Encode(clientcodec.Codec, cfg)
|
json, err := runtime.Encode(clientcodec.Codec, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -97,7 +97,7 @@ func (c *kubeconfigMerger) mergeConfigs(configPath string, fileHandler file.Hand
|
||||||
if err := fileHandler.Write(clientcmd.RecommendedHomeFile, mergedKubeconfig, file.OptOverwrite); err != nil {
|
if err := fileHandler.Write(clientcmd.RecommendedHomeFile, mergedKubeconfig, file.OptOverwrite); err != nil {
|
||||||
return fmt.Errorf("writing merged kubeconfig to file: %w", err)
|
return fmt.Errorf("writing merged kubeconfig to file: %w", err)
|
||||||
}
|
}
|
||||||
c.log.Debugf("Merged kubeconfig into default config file: %s", clientcmd.RecommendedHomeFile)
|
c.log.Debug(fmt.Sprintf("Merged kubeconfig into default config file: %s", clientcmd.RecommendedHomeFile))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
// is used. It is a no-op in the open source version of Constellation.
|
// is used. It is a no-op in the open source version of Constellation.
|
||||||
func (a *applyCmd) checkLicenseFile(cmd *cobra.Command, csp cloudprovider.Provider) {
|
func (a *applyCmd) checkLicenseFile(cmd *cobra.Command, csp cloudprovider.Provider) {
|
||||||
var licenseID string
|
var licenseID string
|
||||||
a.log.Debugf("Running license check")
|
a.log.Debug("Running license check")
|
||||||
|
|
||||||
readBytes, err := a.fileHandler.Read(constants.LicenseFilename)
|
readBytes, err := a.fileHandler.Read(constants.LicenseFilename)
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
@ -52,5 +52,5 @@ func (a *applyCmd) checkLicenseFile(cmd *cobra.Command, csp cloudprovider.Provid
|
||||||
cmd.Printf("Please keep your vCPU quota (%d) in mind.\n", quota)
|
cmd.Printf("Please keep your vCPU quota (%d) in mind.\n", quota)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Debugf("Checked license")
|
a.log.Debug("Checked license")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,25 +7,25 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type debugLog interface {
|
type debugLog interface {
|
||||||
Debugf(format string, args ...any)
|
Debug(msg string, args ...any)
|
||||||
Sync()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCLILogger(cmd *cobra.Command) (debugLog, error) {
|
func newCLILogger(cmd *cobra.Command) (debugLog, error) {
|
||||||
logLvl := zapcore.InfoLevel
|
logLvl := slog.LevelInfo
|
||||||
debugLog, err := cmd.Flags().GetBool("debug")
|
debugLog, err := cmd.Flags().GetBool("debug")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if debugLog {
|
if debugLog {
|
||||||
logLvl = zapcore.DebugLevel
|
logLvl = slog.LevelDebug
|
||||||
}
|
}
|
||||||
|
|
||||||
return logger.New(logger.PlainLog, logLvl), nil
|
return logger.NewTextLogger(logLvl), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ func runPatchMAA(cmd *cobra.Command, args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
|
|
||||||
p := maa.NewAzurePolicyPatcher()
|
p := maa.NewAzurePolicyPatcher()
|
||||||
|
|
||||||
|
@ -57,7 +56,7 @@ func runPatchMAA(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *maaPatchCmd) patchMAA(cmd *cobra.Command, attestationURL string) error {
|
func (c *maaPatchCmd) patchMAA(cmd *cobra.Command, attestationURL string) error {
|
||||||
c.log.Debugf("Using attestation URL %s", attestationURL)
|
c.log.Debug(fmt.Sprintf("Using attestation URL %s", attestationURL))
|
||||||
|
|
||||||
if err := c.patcher.Patch(cmd.Context(), attestationURL); err != nil {
|
if err := c.patcher.Patch(cmd.Context(), attestationURL); err != nil {
|
||||||
return fmt.Errorf("patching MAA attestation policy: %w", err)
|
return fmt.Errorf("patching MAA attestation policy: %w", err)
|
||||||
|
|
|
@ -50,7 +50,6 @@ func runUp(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
|
|
||||||
m := &miniUpCmd{
|
m := &miniUpCmd{
|
||||||
log: log,
|
log: log,
|
||||||
|
@ -152,7 +151,7 @@ func (m *miniUpCmd) prepareConfig(cmd *cobra.Command) (*config.Config, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("mini default config is invalid: %v", err)
|
return nil, fmt.Errorf("mini default config is invalid: %v", err)
|
||||||
}
|
}
|
||||||
m.log.Debugf("Prepared configuration")
|
m.log.Debug("Prepared configuration")
|
||||||
|
|
||||||
return config, m.fileHandler.WriteYAML(constants.ConfigFilename, config, file.OptOverwrite)
|
return config, m.fileHandler.WriteYAML(constants.ConfigFilename, config, file.OptOverwrite)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,12 @@ func (m *miniUpCmd) checkSystemRequirements(out io.Writer) error {
|
||||||
return fmt.Errorf("creation of a QEMU based Constellation is not supported for %s/%s, a linux/amd64 platform is required", runtime.GOOS, runtime.GOARCH)
|
return fmt.Errorf("creation of a QEMU based Constellation is not supported for %s/%s, a linux/amd64 platform is required", runtime.GOOS, runtime.GOARCH)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.log.Debugf("Checked arch and os")
|
m.log.Debug("Checked arch and os")
|
||||||
// check if /dev/kvm exists
|
// check if /dev/kvm exists
|
||||||
if _, err := os.Stat("/dev/kvm"); err != nil {
|
if _, err := os.Stat("/dev/kvm"); err != nil {
|
||||||
return fmt.Errorf("unable to access KVM device: %w", err)
|
return fmt.Errorf("unable to access KVM device: %w", err)
|
||||||
}
|
}
|
||||||
m.log.Debugf("Checked that /dev/kvm exists")
|
m.log.Debug("Checked that /dev/kvm exists")
|
||||||
// check CPU cores
|
// check CPU cores
|
||||||
if runtime.NumCPU() < 4 {
|
if runtime.NumCPU() < 4 {
|
||||||
return fmt.Errorf("insufficient CPU cores: %d, at least 4 cores are required by MiniConstellation", runtime.NumCPU())
|
return fmt.Errorf("insufficient CPU cores: %d, at least 4 cores are required by MiniConstellation", runtime.NumCPU())
|
||||||
|
@ -45,7 +45,7 @@ func (m *miniUpCmd) checkSystemRequirements(out io.Writer) error {
|
||||||
if runtime.NumCPU() < 6 {
|
if runtime.NumCPU() < 6 {
|
||||||
fmt.Fprintf(out, "WARNING: Only %d CPU cores available. This may cause performance issues.\n", runtime.NumCPU())
|
fmt.Fprintf(out, "WARNING: Only %d CPU cores available. This may cause performance issues.\n", runtime.NumCPU())
|
||||||
}
|
}
|
||||||
m.log.Debugf("Checked CPU cores - there are %d", runtime.NumCPU())
|
m.log.Debug(fmt.Sprintf("Checked CPU cores - there are %d", runtime.NumCPU()))
|
||||||
|
|
||||||
// check memory
|
// check memory
|
||||||
f, err := os.Open("/proc/meminfo")
|
f, err := os.Open("/proc/meminfo")
|
||||||
|
@ -63,7 +63,7 @@ func (m *miniUpCmd) checkSystemRequirements(out io.Writer) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.log.Debugf("Scanned for available memory")
|
m.log.Debug("Scanned for available memory")
|
||||||
memGB := memKB / 1024 / 1024
|
memGB := memKB / 1024 / 1024
|
||||||
if memGB < 4 {
|
if memGB < 4 {
|
||||||
return fmt.Errorf("insufficient memory: %dGB, at least 4GB of memory are required by MiniConstellation", memGB)
|
return fmt.Errorf("insufficient memory: %dGB, at least 4GB of memory are required by MiniConstellation", memGB)
|
||||||
|
@ -71,7 +71,7 @@ func (m *miniUpCmd) checkSystemRequirements(out io.Writer) error {
|
||||||
if memGB < 6 {
|
if memGB < 6 {
|
||||||
fmt.Fprintln(out, "WARNING: Less than 6GB of memory available. This may cause performance issues.")
|
fmt.Fprintln(out, "WARNING: Less than 6GB of memory available. This may cause performance issues.")
|
||||||
}
|
}
|
||||||
m.log.Debugf("Checked available memory, you have %dGB available", memGB)
|
m.log.Debug(fmt.Sprintf("Checked available memory, you have %dGB available", memGB))
|
||||||
|
|
||||||
var stat unix.Statfs_t
|
var stat unix.Statfs_t
|
||||||
if err := unix.Statfs(".", &stat); err != nil {
|
if err := unix.Statfs(".", &stat); err != nil {
|
||||||
|
@ -81,7 +81,7 @@ func (m *miniUpCmd) checkSystemRequirements(out io.Writer) error {
|
||||||
if freeSpaceGB < 20 {
|
if freeSpaceGB < 20 {
|
||||||
return fmt.Errorf("insufficient disk space: %dGB, at least 20GB of disk space are required by MiniConstellation", freeSpaceGB)
|
return fmt.Errorf("insufficient disk space: %dGB, at least 20GB of disk space are required by MiniConstellation", freeSpaceGB)
|
||||||
}
|
}
|
||||||
m.log.Debugf("Checked for free space available, you have %dGB available", freeSpaceGB)
|
m.log.Debug(fmt.Sprintf("Checked for free space available, you have %dGB available", freeSpaceGB))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,6 @@ func runRecover(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
fileHandler := file.NewHandler(afero.NewOsFs())
|
fileHandler := file.NewHandler(afero.NewOsFs())
|
||||||
newDialer := func(validator atls.Validator) *dialer.Dialer {
|
newDialer := func(validator atls.Validator) *dialer.Dialer {
|
||||||
return dialer.New(nil, validator, &net.Dialer{})
|
return dialer.New(nil, validator, &net.Dialer{})
|
||||||
|
@ -85,7 +84,7 @@ func runRecover(cmd *cobra.Command, _ []string) error {
|
||||||
if err := r.flags.parse(cmd.Flags()); err != nil {
|
if err := r.flags.parse(cmd.Flags()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.log.Debugf("Using flags: %+v", r.flags)
|
r.log.Debug(fmt.Sprintf("Using flags: %+v", r.flags))
|
||||||
return r.recover(cmd, fileHandler, 5*time.Second, &recoverDoer{log: r.log}, newDialer)
|
return r.recover(cmd, fileHandler, 5*time.Second, &recoverDoer{log: r.log}, newDialer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,12 +93,12 @@ func (r *recoverCmd) recover(
|
||||||
doer recoverDoerInterface, newDialer func(validator atls.Validator) *dialer.Dialer,
|
doer recoverDoerInterface, newDialer func(validator atls.Validator) *dialer.Dialer,
|
||||||
) error {
|
) error {
|
||||||
var masterSecret uri.MasterSecret
|
var masterSecret uri.MasterSecret
|
||||||
r.log.Debugf("Loading master secret file from %s", r.flags.pathPrefixer.PrefixPrintablePath(constants.MasterSecretFilename))
|
r.log.Debug(fmt.Sprintf("Loading master secret file from %s", r.flags.pathPrefixer.PrefixPrintablePath(constants.MasterSecretFilename)))
|
||||||
if err := fileHandler.ReadJSON(constants.MasterSecretFilename, &masterSecret); err != nil {
|
if err := fileHandler.ReadJSON(constants.MasterSecretFilename, &masterSecret); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r.log.Debugf("Loading configuration file from %q", r.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))
|
r.log.Debug(fmt.Sprintf("Loading configuration file from %q", r.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename)))
|
||||||
conf, err := config.New(fileHandler, constants.ConfigFilename, r.configFetcher, r.flags.force)
|
conf, err := config.New(fileHandler, constants.ConfigFilename, r.configFetcher, r.flags.force)
|
||||||
var configValidationErr *config.ValidationError
|
var configValidationErr *config.ValidationError
|
||||||
if errors.As(err, &configValidationErr) {
|
if errors.As(err, &configValidationErr) {
|
||||||
|
@ -109,7 +108,7 @@ func (r *recoverCmd) recover(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r.log.Debugf("Got provider %s", conf.GetProvider())
|
r.log.Debug(fmt.Sprintf("Got provider %s", conf.GetProvider()))
|
||||||
if conf.GetProvider() == cloudprovider.Azure {
|
if conf.GetProvider() == cloudprovider.Azure {
|
||||||
interval = 20 * time.Second // Azure LB takes a while to remove unhealthy instances
|
interval = 20 * time.Second // Azure LB takes a while to remove unhealthy instances
|
||||||
}
|
}
|
||||||
|
@ -130,16 +129,16 @@ func (r *recoverCmd) recover(
|
||||||
conf.UpdateMAAURL(stateFile.Infrastructure.Azure.AttestationURL)
|
conf.UpdateMAAURL(stateFile.Infrastructure.Azure.AttestationURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.log.Debugf("Creating aTLS Validator for %s", conf.GetAttestationConfig().GetVariant())
|
r.log.Debug(fmt.Sprintf("Creating aTLS Validator for %s", conf.GetAttestationConfig().GetVariant()))
|
||||||
validator, err := choose.Validator(conf.GetAttestationConfig(), warnLogger{cmd: cmd, log: r.log})
|
validator, err := choose.Validator(conf.GetAttestationConfig(), warnLogger{cmd: cmd, log: r.log})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating new validator: %w", err)
|
return fmt.Errorf("creating new validator: %w", err)
|
||||||
}
|
}
|
||||||
r.log.Debugf("Created a new validator")
|
r.log.Debug("Created a new validator")
|
||||||
doer.setDialer(newDialer(validator), endpoint)
|
doer.setDialer(newDialer(validator), endpoint)
|
||||||
r.log.Debugf("Set dialer for endpoint %s", endpoint)
|
r.log.Debug(fmt.Sprintf("Set dialer for endpoint %s", endpoint))
|
||||||
doer.setURIs(masterSecret.EncodeToURI(), uri.NoStoreURI)
|
doer.setURIs(masterSecret.EncodeToURI(), uri.NoStoreURI)
|
||||||
r.log.Debugf("Set secrets")
|
r.log.Debug("Set secrets")
|
||||||
if err := r.recoverCall(cmd.Context(), cmd.OutOrStdout(), interval, doer); err != nil {
|
if err := r.recoverCall(cmd.Context(), cmd.OutOrStdout(), interval, doer); err != nil {
|
||||||
if grpcRetry.ServiceIsUnavailable(err) {
|
if grpcRetry.ServiceIsUnavailable(err) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -167,12 +166,12 @@ func (r *recoverCmd) recoverCall(ctx context.Context, out io.Writer, interval ti
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
r.log.Debugf("Encountered error (retriable: %t): %s", retry, err)
|
r.log.Debug(fmt.Sprintf("Encountered error (retriable: %t): %s", retry, err))
|
||||||
return retry
|
return retry
|
||||||
}
|
}
|
||||||
|
|
||||||
retrier := retry.NewIntervalRetrier(doer, interval, retryOnceOnFailure)
|
retrier := retry.NewIntervalRetrier(doer, interval, retryOnceOnFailure)
|
||||||
r.log.Debugf("Created new interval retrier")
|
r.log.Debug("Created new interval retrier")
|
||||||
err = retrier.Do(ctx)
|
err = retrier.Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
|
@ -180,7 +179,7 @@ func (r *recoverCmd) recoverCall(ctx context.Context, out io.Writer, interval ti
|
||||||
fmt.Fprintln(out, "Pushed recovery key.")
|
fmt.Fprintln(out, "Pushed recovery key.")
|
||||||
ctr++
|
ctr++
|
||||||
}
|
}
|
||||||
r.log.Debugf("Retry counter is %d", ctr)
|
r.log.Debug(fmt.Sprintf("Retry counter is %d", ctr))
|
||||||
if ctr > 0 {
|
if ctr > 0 {
|
||||||
fmt.Fprintf(out, "Recovered %d control-plane nodes.\n", ctr)
|
fmt.Fprintf(out, "Recovered %d control-plane nodes.\n", ctr)
|
||||||
} else if grpcRetry.ServiceIsUnavailable(err) {
|
} else if grpcRetry.ServiceIsUnavailable(err) {
|
||||||
|
@ -222,11 +221,11 @@ func (d *recoverDoer) Do(ctx context.Context) (retErr error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("dialing recovery server: %w", err)
|
return fmt.Errorf("dialing recovery server: %w", err)
|
||||||
}
|
}
|
||||||
d.log.Debugf("Dialed recovery server")
|
d.log.Debug("Dialed recovery server")
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
protoClient := recoverproto.NewAPIClient(conn)
|
protoClient := recoverproto.NewAPIClient(conn)
|
||||||
d.log.Debugf("Created protoClient")
|
d.log.Debug("Created protoClient")
|
||||||
|
|
||||||
req := &recoverproto.RecoverMessage{
|
req := &recoverproto.RecoverMessage{
|
||||||
KmsUri: d.kmsURI,
|
KmsUri: d.kmsURI,
|
||||||
|
@ -238,7 +237,7 @@ func (d *recoverDoer) Do(ctx context.Context) (retErr error) {
|
||||||
return fmt.Errorf("calling recover: %w", err)
|
return fmt.Errorf("calling recover: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.log.Debugf("Received confirmation")
|
d.log.Debug("Received confirmation")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,6 @@ func runStatus(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
|
|
||||||
fileHandler := file.NewHandler(afero.NewOsFs())
|
fileHandler := file.NewHandler(afero.NewOsFs())
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,6 @@ func runUpgradeCheck(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
|
|
||||||
var flags upgradeCheckFlags
|
var flags upgradeCheckFlags
|
||||||
if err := flags.parse(cmd.Flags()); err != nil {
|
if err := flags.parse(cmd.Flags()); err != nil {
|
||||||
|
@ -188,7 +187,7 @@ func (u *upgradeCheckCmd) upgradeCheck(cmd *cobra.Command, fetcher attestationco
|
||||||
// get current image version of the cluster
|
// get current image version of the cluster
|
||||||
csp := conf.GetProvider()
|
csp := conf.GetProvider()
|
||||||
attestationVariant := conf.GetAttestationConfig().GetVariant()
|
attestationVariant := conf.GetAttestationConfig().GetVariant()
|
||||||
u.log.Debugf("Using provider %s with attestation variant %s", csp.String(), attestationVariant.String())
|
u.log.Debug(fmt.Sprintf("Using provider %s with attestation variant %s", csp.String(), attestationVariant.String()))
|
||||||
|
|
||||||
current, err := u.collect.currentVersions(cmd.Context())
|
current, err := u.collect.currentVersions(cmd.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -199,18 +198,18 @@ func (u *upgradeCheckCmd) upgradeCheck(cmd *cobra.Command, fetcher attestationco
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
u.log.Debugf("Current cli version: %s", current.cli)
|
u.log.Debug(fmt.Sprintf("Current cli version: %s", current.cli))
|
||||||
u.log.Debugf("Supported cli version(s): %s", supported.cli)
|
u.log.Debug(fmt.Sprintf("Supported cli version(s): %s", supported.cli))
|
||||||
u.log.Debugf("Current service version: %s", current.service)
|
u.log.Debug(fmt.Sprintf("Current service version: %s", current.service))
|
||||||
u.log.Debugf("Supported service version: %s", supported.service)
|
u.log.Debug(fmt.Sprintf("Supported service version: %s", supported.service))
|
||||||
u.log.Debugf("Current k8s version: %s", current.k8s)
|
u.log.Debug(fmt.Sprintf("Current k8s version: %s", current.k8s))
|
||||||
u.log.Debugf("Supported k8s version(s): %s", supported.k8s)
|
u.log.Debug(fmt.Sprintf("Supported k8s version(s): %s", supported.k8s))
|
||||||
|
|
||||||
// Filter versions to only include upgrades
|
// Filter versions to only include upgrades
|
||||||
newServices := supported.service
|
newServices := supported.service
|
||||||
if err := supported.service.IsUpgradeTo(current.service); err != nil {
|
if err := supported.service.IsUpgradeTo(current.service); err != nil {
|
||||||
newServices = consemver.Semver{}
|
newServices = consemver.Semver{}
|
||||||
u.log.Debugf("No valid service upgrades are available from %q to %q. The minor version can only drift by 1.\n", current.service.String(), supported.service.String())
|
u.log.Debug(fmt.Sprintf("No valid service upgrades are available from %q to %q. The minor version can only drift by 1.\n", current.service.String(), supported.service.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
newKubernetes := filterK8sUpgrades(current.k8s, supported.k8s)
|
newKubernetes := filterK8sUpgrades(current.k8s, supported.k8s)
|
||||||
|
@ -222,13 +221,13 @@ func (u *upgradeCheckCmd) upgradeCheck(cmd *cobra.Command, fetcher attestationco
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
u.log.Debugf("Planning Terraform migrations")
|
u.log.Debug("Planning Terraform migrations")
|
||||||
|
|
||||||
// Add manual migrations here if required
|
// Add manual migrations here if required
|
||||||
//
|
//
|
||||||
// var manualMigrations []terraform.StateMigration
|
// var manualMigrations []terraform.StateMigration
|
||||||
// for _, migration := range manualMigrations {
|
// for _, migration := range manualMigrations {
|
||||||
// u.log.Debugf("Adding manual Terraform migration: %s", migration.DisplayName)
|
// u.log.Debug("Adding manual Terraform migration: %s", migration.DisplayName)
|
||||||
// u.terraformChecker.AddManualStateMigration(migration)
|
// u.terraformChecker.AddManualStateMigration(migration)
|
||||||
// }
|
// }
|
||||||
cmd.Println("The following Terraform migrations are available with this CLI:")
|
cmd.Println("The following Terraform migrations are available with this CLI:")
|
||||||
|
@ -344,7 +343,7 @@ func (v *versionCollector) newMeasurements(ctx context.Context, csp cloudprovide
|
||||||
// get expected measurements for each image
|
// get expected measurements for each image
|
||||||
upgrades := make(map[string]measurements.M)
|
upgrades := make(map[string]measurements.M)
|
||||||
for _, version := range versions {
|
for _, version := range versions {
|
||||||
v.log.Debugf("Fetching measurements for image: %s", version)
|
v.log.Debug(fmt.Sprintf("Fetching measurements for image: %s", version.Version()))
|
||||||
shortPath := version.ShortPath()
|
shortPath := version.ShortPath()
|
||||||
|
|
||||||
publicKey, err := keyselect.CosignPublicKeyForVersion(version)
|
publicKey, err := keyselect.CosignPublicKeyForVersion(version)
|
||||||
|
@ -365,7 +364,7 @@ func (v *versionCollector) newMeasurements(ctx context.Context, csp cloudprovide
|
||||||
}
|
}
|
||||||
upgrades[shortPath] = measurements
|
upgrades[shortPath] = measurements
|
||||||
}
|
}
|
||||||
v.log.Debugf("Compatible image measurements are %v", upgrades)
|
v.log.Debug(fmt.Sprintf("Compatible image measurements are %v", upgrades))
|
||||||
|
|
||||||
return upgrades, nil
|
return upgrades, nil
|
||||||
}
|
}
|
||||||
|
@ -453,9 +452,9 @@ func (v *versionCollector) newImages(ctx context.Context, currentImageVersion co
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("calculating next image minor version: %w", err)
|
return nil, fmt.Errorf("calculating next image minor version: %w", err)
|
||||||
}
|
}
|
||||||
v.log.Debugf("Current image minor version is %s", currentImageMinorVer)
|
v.log.Debug(fmt.Sprintf("Current image minor version is %s", currentImageMinorVer))
|
||||||
v.log.Debugf("Current CLI minor version is %s", currentCLIMinorVer)
|
v.log.Debug(fmt.Sprintf("Current CLI minor version is %s", currentCLIMinorVer))
|
||||||
v.log.Debugf("Next image minor version is %s", nextImageMinorVer)
|
v.log.Debug(fmt.Sprintf("Next image minor version is %s", nextImageMinorVer))
|
||||||
|
|
||||||
allowedMinorVersions := []string{currentImageMinorVer, nextImageMinorVer}
|
allowedMinorVersions := []string{currentImageMinorVer, nextImageMinorVer}
|
||||||
switch cliImageCompare := semver.Compare(currentCLIMinorVer, currentImageMinorVer); {
|
switch cliImageCompare := semver.Compare(currentCLIMinorVer, currentImageMinorVer); {
|
||||||
|
@ -471,7 +470,7 @@ func (v *versionCollector) newImages(ctx context.Context, currentImageVersion co
|
||||||
case cliImageCompare > 0:
|
case cliImageCompare > 0:
|
||||||
allowedMinorVersions = []string{currentImageMinorVer, nextImageMinorVer}
|
allowedMinorVersions = []string{currentImageMinorVer, nextImageMinorVer}
|
||||||
}
|
}
|
||||||
v.log.Debugf("Allowed minor versions are %#v", allowedMinorVersions)
|
v.log.Debug(fmt.Sprintf("Allowed minor versions are %#v", allowedMinorVersions))
|
||||||
|
|
||||||
newerImages, err := v.newerVersions(ctx, allowedMinorVersions)
|
newerImages, err := v.newerVersions(ctx, allowedMinorVersions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -494,7 +493,7 @@ func (v *versionCollector) newerVersions(ctx context.Context, allowedVersions []
|
||||||
patchList, err := v.verListFetcher.FetchVersionList(ctx, patchList)
|
patchList, err := v.verListFetcher.FetchVersionList(ctx, patchList)
|
||||||
var notFound *fetcher.NotFoundError
|
var notFound *fetcher.NotFoundError
|
||||||
if errors.As(err, ¬Found) {
|
if errors.As(err, ¬Found) {
|
||||||
v.log.Debugf("Skipping version: %s", err)
|
v.log.Debug(fmt.Sprintf("Skipping version: %s", err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -502,7 +501,7 @@ func (v *versionCollector) newerVersions(ctx context.Context, allowedVersions []
|
||||||
}
|
}
|
||||||
updateCandidates = append(updateCandidates, patchList.StructuredVersions()...)
|
updateCandidates = append(updateCandidates, patchList.StructuredVersions()...)
|
||||||
}
|
}
|
||||||
v.log.Debugf("Update candidates are %v", updateCandidates)
|
v.log.Debug(fmt.Sprintf("Update candidates are %v", updateCandidates))
|
||||||
|
|
||||||
return updateCandidates, nil
|
return updateCandidates, nil
|
||||||
}
|
}
|
||||||
|
@ -604,7 +603,7 @@ func getCompatibleImageMeasurements(ctx context.Context, writer io.Writer, clien
|
||||||
}
|
}
|
||||||
|
|
||||||
var fetchedMeasurements measurements.M
|
var fetchedMeasurements measurements.M
|
||||||
log.Debugf("Fetching for measurement url: %s", measurementsURL)
|
log.Debug(fmt.Sprintf("Fetching for measurement url: %s", measurementsURL))
|
||||||
|
|
||||||
hash, err := fetchedMeasurements.FetchAndVerify(
|
hash, err := fetchedMeasurements.FetchAndVerify(
|
||||||
ctx, client, cosign,
|
ctx, client, cosign,
|
||||||
|
@ -658,7 +657,7 @@ func (v *versionCollector) newCLIVersions(ctx context.Context) ([]consemver.Semv
|
||||||
return nil, fmt.Errorf("parsing version %s: %w", version, err)
|
return nil, fmt.Errorf("parsing version %s: %w", version, err)
|
||||||
}
|
}
|
||||||
if err := target.IsUpgradeTo(v.cliVersion); err != nil {
|
if err := target.IsUpgradeTo(v.cliVersion); err != nil {
|
||||||
v.log.Debugf("Skipping incompatible minor version %q: %s", version, err)
|
v.log.Debug(fmt.Sprintf("Skipping incompatible minor version %q: %s", version, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
list := versionsapi.List{
|
list := versionsapi.List{
|
||||||
|
@ -692,7 +691,7 @@ func (v *versionCollector) filterCompatibleCLIVersions(ctx context.Context, cliP
|
||||||
var compatibleVersions []consemver.Semver
|
var compatibleVersions []consemver.Semver
|
||||||
for _, version := range cliPatchVersions {
|
for _, version := range cliPatchVersions {
|
||||||
if err := version.IsUpgradeTo(v.cliVersion); err != nil {
|
if err := version.IsUpgradeTo(v.cliVersion); err != nil {
|
||||||
v.log.Debugf("Skipping incompatible patch version %q: %s", version, err)
|
v.log.Debug(fmt.Sprintf("Skipping incompatible patch version %q: %s", version, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
req := versionsapi.CLIInfo{
|
req := versionsapi.CLIInfo{
|
||||||
|
|
|
@ -100,7 +100,6 @@ func runVerify(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating logger: %w", err)
|
return fmt.Errorf("creating logger: %w", err)
|
||||||
}
|
}
|
||||||
defer log.Sync()
|
|
||||||
|
|
||||||
fileHandler := file.NewHandler(afero.NewOsFs())
|
fileHandler := file.NewHandler(afero.NewOsFs())
|
||||||
verifyClient := &constellationVerifier{
|
verifyClient := &constellationVerifier{
|
||||||
|
@ -129,7 +128,7 @@ func runVerify(cmd *cobra.Command, _ []string) error {
|
||||||
if err := v.flags.parse(cmd.Flags()); err != nil {
|
if err := v.flags.parse(cmd.Flags()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
v.log.Debugf("Using flags: %+v", v.flags)
|
v.log.Debug(fmt.Sprintf("Using flags: %+v", v.flags))
|
||||||
fetcher := attestationconfigapi.NewFetcher()
|
fetcher := attestationconfigapi.NewFetcher()
|
||||||
return v.verify(cmd, verifyClient, formatterFactory, fetcher)
|
return v.verify(cmd, verifyClient, formatterFactory, fetcher)
|
||||||
}
|
}
|
||||||
|
@ -137,7 +136,7 @@ func runVerify(cmd *cobra.Command, _ []string) error {
|
||||||
type formatterFactory func(output string, attestation variant.Variant, log debugLog) (attestationDocFormatter, error)
|
type formatterFactory func(output string, attestation variant.Variant, log debugLog) (attestationDocFormatter, error)
|
||||||
|
|
||||||
func (c *verifyCmd) verify(cmd *cobra.Command, verifyClient verifyClient, factory formatterFactory, configFetcher attestationconfigapi.Fetcher) error {
|
func (c *verifyCmd) verify(cmd *cobra.Command, verifyClient verifyClient, factory formatterFactory, configFetcher attestationconfigapi.Fetcher) error {
|
||||||
c.log.Debugf("Loading configuration file from %q", c.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename))
|
c.log.Debug(fmt.Sprintf("Loading configuration file from %q", c.flags.pathPrefixer.PrefixPrintablePath(constants.ConfigFilename)))
|
||||||
conf, err := config.New(c.fileHandler, constants.ConfigFilename, configFetcher, c.flags.force)
|
conf, err := config.New(c.fileHandler, constants.ConfigFilename, configFetcher, c.flags.force)
|
||||||
var configValidationErr *config.ValidationError
|
var configValidationErr *config.ValidationError
|
||||||
if errors.As(err, &configValidationErr) {
|
if errors.As(err, &configValidationErr) {
|
||||||
|
@ -170,13 +169,13 @@ func (c *verifyCmd) verify(cmd *cobra.Command, verifyClient verifyClient, factor
|
||||||
}
|
}
|
||||||
conf.UpdateMAAURL(maaURL)
|
conf.UpdateMAAURL(maaURL)
|
||||||
|
|
||||||
c.log.Debugf("Updating expected PCRs")
|
c.log.Debug("Updating expected PCRs")
|
||||||
attConfig := conf.GetAttestationConfig()
|
attConfig := conf.GetAttestationConfig()
|
||||||
if err := updateInitMeasurements(attConfig, ownerID, clusterID); err != nil {
|
if err := updateInitMeasurements(attConfig, ownerID, clusterID); err != nil {
|
||||||
return fmt.Errorf("updating expected PCRs: %w", err)
|
return fmt.Errorf("updating expected PCRs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Debugf("Creating aTLS Validator for %s", conf.GetAttestationConfig().GetVariant())
|
c.log.Debug(fmt.Sprintf("Creating aTLS Validator for %s", conf.GetAttestationConfig().GetVariant()))
|
||||||
validator, err := choose.Validator(attConfig, warnLogger{cmd: cmd, log: c.log})
|
validator, err := choose.Validator(attConfig, warnLogger{cmd: cmd, log: c.log})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating aTLS validator: %w", err)
|
return fmt.Errorf("creating aTLS validator: %w", err)
|
||||||
|
@ -186,7 +185,7 @@ func (c *verifyCmd) verify(cmd *cobra.Command, verifyClient verifyClient, factor
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("generating random nonce: %w", err)
|
return fmt.Errorf("generating random nonce: %w", err)
|
||||||
}
|
}
|
||||||
c.log.Debugf("Generated random nonce: %x", nonce)
|
c.log.Debug(fmt.Sprintf("Generated random nonce: %x", nonce))
|
||||||
|
|
||||||
rawAttestationDoc, err := verifyClient.Verify(
|
rawAttestationDoc, err := verifyClient.Verify(
|
||||||
cmd.Context(),
|
cmd.Context(),
|
||||||
|
@ -385,7 +384,7 @@ type constellationVerifier struct {
|
||||||
func (v *constellationVerifier) Verify(
|
func (v *constellationVerifier) Verify(
|
||||||
ctx context.Context, endpoint string, req *verifyproto.GetAttestationRequest, validator atls.Validator,
|
ctx context.Context, endpoint string, req *verifyproto.GetAttestationRequest, validator atls.Validator,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
v.log.Debugf("Dialing endpoint: %q", endpoint)
|
v.log.Debug(fmt.Sprintf("Dialing endpoint: %q", endpoint))
|
||||||
conn, err := v.dialer.DialInsecure(ctx, endpoint)
|
conn, err := v.dialer.DialInsecure(ctx, endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("dialing init server: %w", err)
|
return "", fmt.Errorf("dialing init server: %w", err)
|
||||||
|
@ -394,13 +393,13 @@ func (v *constellationVerifier) Verify(
|
||||||
|
|
||||||
client := verifyproto.NewAPIClient(conn)
|
client := verifyproto.NewAPIClient(conn)
|
||||||
|
|
||||||
v.log.Debugf("Sending attestation request")
|
v.log.Debug("Sending attestation request")
|
||||||
resp, err := client.GetAttestation(ctx, req)
|
resp, err := client.GetAttestation(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("getting attestation: %w", err)
|
return "", fmt.Errorf("getting attestation: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.log.Debugf("Verifying attestation")
|
v.log.Debug("Verifying attestation")
|
||||||
signedData, err := validator.Validate(ctx, resp.Attestation, req.Nonce)
|
signedData, err := validator.Validate(ctx, resp.Attestation, req.Nonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("validating attestation: %w", err)
|
return "", fmt.Errorf("validating attestation: %w", err)
|
||||||
|
|
|
@ -25,7 +25,6 @@ go_library(
|
||||||
"//internal/cloud/qemu",
|
"//internal/cloud/qemu",
|
||||||
"//internal/logger",
|
"//internal/logger",
|
||||||
"@com_github_spf13_afero//:afero",
|
"@com_github_spf13_afero//:afero",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,12 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/deploy"
|
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/deploy"
|
||||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/info"
|
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/info"
|
||||||
|
@ -46,11 +46,11 @@ func main() {
|
||||||
verbosity := flag.Int("v", 0, logger.CmdLineVerbosityDescription)
|
verbosity := flag.Int("v", 0, logger.CmdLineVerbosityDescription)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
log := logger.New(logger.JSONLog, logger.VerbosityFromInt(*verbosity))
|
log := logger.NewJSONLogger(logger.VerbosityFromInt(*verbosity))
|
||||||
fs := afero.NewOsFs()
|
fs := afero.NewOsFs()
|
||||||
streamer := streamer.New(fs)
|
streamer := streamer.New(fs)
|
||||||
filetransferer := filetransfer.New(log.Named("filetransfer"), streamer, filetransfer.DontShowProgress)
|
filetransferer := filetransfer.New(log.WithGroup("filetransfer"), streamer, filetransfer.DontShowProgress)
|
||||||
serviceManager := deploy.NewServiceManager(log.Named("serviceManager"))
|
serviceManager := deploy.NewServiceManager(log.WithGroup("serviceManager"))
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -64,21 +64,24 @@ func main() {
|
||||||
case platform.AWS:
|
case platform.AWS:
|
||||||
meta, err := awscloud.New(ctx)
|
meta, err := awscloud.New(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to initialize AWS metadata")
|
log.With(slog.Any("error", err)).Error("Failed to initialize AWS metadata")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fetcher = cloudprovider.New(meta)
|
fetcher = cloudprovider.New(meta)
|
||||||
|
|
||||||
case platform.Azure:
|
case platform.Azure:
|
||||||
meta, err := azurecloud.New(ctx)
|
meta, err := azurecloud.New(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to initialize Azure metadata")
|
log.With(slog.Any("error", err)).Error("Failed to initialize Azure metadata")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fetcher = cloudprovider.New(meta)
|
fetcher = cloudprovider.New(meta)
|
||||||
|
|
||||||
case platform.GCP:
|
case platform.GCP:
|
||||||
meta, err := gcpcloud.New(ctx)
|
meta, err := gcpcloud.New(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to initialize GCP metadata")
|
log.With(slog.Any("error", err)).Error("Failed to initialize GCP metadata")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer meta.Close()
|
defer meta.Close()
|
||||||
fetcher = cloudprovider.New(meta)
|
fetcher = cloudprovider.New(meta)
|
||||||
|
@ -86,26 +89,27 @@ func main() {
|
||||||
case platform.OpenStack:
|
case platform.OpenStack:
|
||||||
meta, err := openstackcloud.New(ctx)
|
meta, err := openstackcloud.New(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to initialize OpenStack metadata")
|
log.With(slog.Any("error", err)).Error("Failed to initialize OpenStack metadata")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fetcher = cloudprovider.New(meta)
|
fetcher = cloudprovider.New(meta)
|
||||||
case platform.QEMU:
|
case platform.QEMU:
|
||||||
fetcher = cloudprovider.New(qemucloud.New())
|
fetcher = cloudprovider.New(qemucloud.New())
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Errorf("Unknown / unimplemented cloud provider CONSTEL_CSP=%v. Using fallback", csp)
|
log.Error(fmt.Sprintf("Unknown / unimplemented cloud provider CONSTEL_CSP=%v. Using fallback", csp))
|
||||||
fetcher = fallback.NewFallbackFetcher()
|
fetcher = fallback.NewFallbackFetcher()
|
||||||
}
|
}
|
||||||
|
|
||||||
infoMap := info.NewMap()
|
infoMap := info.NewMap()
|
||||||
infoMap.RegisterOnReceiveTrigger(
|
infoMap.RegisterOnReceiveTrigger(
|
||||||
logcollector.NewStartTrigger(ctx, wg, platform.FromString(csp), fetcher, log.Named("logcollector")),
|
logcollector.NewStartTrigger(ctx, wg, platform.FromString(csp), fetcher, log.WithGroup("logcollector")),
|
||||||
)
|
)
|
||||||
|
|
||||||
download := deploy.New(log.Named("download"), &net.Dialer{}, serviceManager, filetransferer, infoMap)
|
download := deploy.New(log.WithGroup("download"), &net.Dialer{}, serviceManager, filetransferer, infoMap)
|
||||||
|
|
||||||
sched := metadata.NewScheduler(log.Named("scheduler"), fetcher, download)
|
sched := metadata.NewScheduler(log.WithGroup("scheduler"), fetcher, download)
|
||||||
serv := server.New(log.Named("server"), serviceManager, filetransferer, infoMap)
|
serv := server.New(log.WithGroup("server"), serviceManager, filetransferer, infoMap)
|
||||||
|
|
||||||
writeDebugBanner(log)
|
writeDebugBanner(log)
|
||||||
|
|
||||||
|
@ -114,14 +118,14 @@ func main() {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeDebugBanner(log *logger.Logger) {
|
func writeDebugBanner(log *slog.Logger) {
|
||||||
tty, err := os.OpenFile("/dev/ttyS0", os.O_WRONLY, os.ModeAppend)
|
tty, err := os.OpenFile("/dev/ttyS0", os.O_WRONLY, os.ModeAppend)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Errorf("Unable to open /dev/ttyS0 for printing banner")
|
log.With(slog.Any("error", err)).Error("Unable to open /dev/ttyS0 for printing banner")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer tty.Close()
|
defer tty.Close()
|
||||||
if _, err := fmt.Fprint(tty, debugBanner); err != nil {
|
if _, err := fmt.Fprint(tty, debugBanner); err != nil {
|
||||||
log.With(zap.Error(err)).Errorf("Unable to print to /dev/ttyS0")
|
log.With(slog.Any("error", err)).Error("Unable to print to /dev/ttyS0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -60,7 +61,7 @@ func runDeploy(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log := logger.New(logger.PlainLog, logger.VerbosityFromInt(verbosity))
|
log := logger.NewTextLogger(logger.VerbosityFromInt(verbosity))
|
||||||
force, err := cmd.Flags().GetBool("force")
|
force, err := cmd.Flags().GetBool("force")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getting force flag: %w", err)
|
return fmt.Errorf("getting force flag: %w", err)
|
||||||
|
@ -83,7 +84,7 @@ func runDeploy(cmd *cobra.Command, _ []string) error {
|
||||||
|
|
||||||
func deploy(cmd *cobra.Command, fileHandler file.Handler, constellationConfig *config.Config,
|
func deploy(cmd *cobra.Command, fileHandler file.Handler, constellationConfig *config.Config,
|
||||||
transfer fileTransferer,
|
transfer fileTransferer,
|
||||||
log *logger.Logger,
|
log *slog.Logger,
|
||||||
) error {
|
) error {
|
||||||
binDir, err := cmd.Flags().GetString("bindir")
|
binDir, err := cmd.Flags().GetString("bindir")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -99,13 +100,13 @@ func deploy(cmd *cobra.Command, fileHandler file.Handler, constellationConfig *c
|
||||||
}
|
}
|
||||||
|
|
||||||
if constellationConfig.IsReleaseImage() {
|
if constellationConfig.IsReleaseImage() {
|
||||||
log.Infof("WARNING: Constellation image does not look like a debug image. Are you using a debug image?")
|
log.Info("WARNING: Constellation image does not look like a debug image. Are you using a debug image?")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !constellationConfig.IsDebugCluster() {
|
if !constellationConfig.IsDebugCluster() {
|
||||||
log.Infof("WARNING: The Constellation config has debugCluster set to false.")
|
log.Info("WARNING: The Constellation config has debugCluster set to false.")
|
||||||
log.Infof("cdbg will likely not work unless you manually adjust the firewall / load balancing rules.")
|
log.Info("cdbg will likely not work unless you manually adjust the firewall / load balancing rules.")
|
||||||
log.Infof("If you create the cluster with a debug image, you should also set debugCluster to true.")
|
log.Info("If you create the cluster with a debug image, you should also set debugCluster to true.")
|
||||||
}
|
}
|
||||||
|
|
||||||
ips, err := cmd.Flags().GetStringSlice("ips")
|
ips, err := cmd.Flags().GetStringSlice("ips")
|
||||||
|
@ -171,14 +172,14 @@ type deployOnEndpointInput struct {
|
||||||
files []filetransfer.FileStat
|
files []filetransfer.FileStat
|
||||||
infos map[string]string
|
infos map[string]string
|
||||||
transfer fileTransferer
|
transfer fileTransferer
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// deployOnEndpoint deploys a custom built bootstrapper binary to a debugd endpoint.
|
// deployOnEndpoint deploys a custom built bootstrapper binary to a debugd endpoint.
|
||||||
func deployOnEndpoint(ctx context.Context, in deployOnEndpointInput) error {
|
func deployOnEndpoint(ctx context.Context, in deployOnEndpointInput) error {
|
||||||
ctx, cancel := context.WithTimeout(ctx, deployEndpointTimeout)
|
ctx, cancel := context.WithTimeout(ctx, deployEndpointTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
in.log.Infof("Deploying on %v", in.debugdEndpoint)
|
in.log.Info(fmt.Sprintf("Deploying on %v", in.debugdEndpoint))
|
||||||
|
|
||||||
client, closeAndWaitFn, err := newDebugdClient(ctx, in.debugdEndpoint, in.log)
|
client, closeAndWaitFn, err := newDebugdClient(ctx, in.debugdEndpoint, in.log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -201,13 +202,13 @@ func deployOnEndpoint(ctx context.Context, in deployOnEndpointInput) error {
|
||||||
type closeAndWait func()
|
type closeAndWait func()
|
||||||
|
|
||||||
// newDebugdClient creates a new gRPC client for the debugd service and logs the connection state changes.
|
// newDebugdClient creates a new gRPC client for the debugd service and logs the connection state changes.
|
||||||
func newDebugdClient(ctx context.Context, ip string, log *logger.Logger) (pb.DebugdClient, closeAndWait, error) {
|
func newDebugdClient(ctx context.Context, ip string, log *slog.Logger) (pb.DebugdClient, closeAndWait, error) {
|
||||||
conn, err := grpc.DialContext(
|
conn, err := grpc.DialContext(
|
||||||
ctx,
|
ctx,
|
||||||
net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort)),
|
net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort)),
|
||||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
log.GetClientUnaryInterceptor(),
|
logger.GetClientUnaryInterceptor(log),
|
||||||
log.GetClientStreamInterceptor(),
|
logger.GetClientStreamInterceptor(log),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("connecting to other instance via gRPC: %w", err)
|
return nil, nil, fmt.Errorf("connecting to other instance via gRPC: %w", err)
|
||||||
|
@ -221,8 +222,8 @@ func newDebugdClient(ctx context.Context, ip string, log *logger.Logger) (pb.Deb
|
||||||
return pb.NewDebugdClient(conn), closeAndWait, nil
|
return pb.NewDebugdClient(conn), closeAndWait, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setInfo(ctx context.Context, log *logger.Logger, client pb.DebugdClient, infos map[string]string) error {
|
func setInfo(ctx context.Context, log *slog.Logger, client pb.DebugdClient, infos map[string]string) error {
|
||||||
log.Infof("Setting info with length %d", len(infos))
|
log.Info(fmt.Sprintf("Setting info with length %d", len(infos)))
|
||||||
|
|
||||||
var infosPb []*pb.Info
|
var infosPb []*pb.Info
|
||||||
for key, value := range infos {
|
for key, value := range infos {
|
||||||
|
@ -238,17 +239,17 @@ func setInfo(ctx context.Context, log *logger.Logger, client pb.DebugdClient, in
|
||||||
|
|
||||||
switch status.Status {
|
switch status.Status {
|
||||||
case pb.SetInfoStatus_SET_INFO_SUCCESS:
|
case pb.SetInfoStatus_SET_INFO_SUCCESS:
|
||||||
log.Infof("Info set")
|
log.Info("Info set")
|
||||||
case pb.SetInfoStatus_SET_INFO_ALREADY_SET:
|
case pb.SetInfoStatus_SET_INFO_ALREADY_SET:
|
||||||
log.Infof("Info already set")
|
log.Info("Info already set")
|
||||||
default:
|
default:
|
||||||
log.Warnf("Unknown status %v", status.Status)
|
log.Warn(fmt.Sprintf("Unknown status %v", status.Status))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func uploadFiles(ctx context.Context, client pb.DebugdClient, in deployOnEndpointInput) error {
|
func uploadFiles(ctx context.Context, client pb.DebugdClient, in deployOnEndpointInput) error {
|
||||||
in.log.Infof("Uploading files")
|
in.log.Info("Uploading files")
|
||||||
|
|
||||||
stream, err := client.UploadFiles(ctx, grpc.WaitForReady(true))
|
stream, err := client.UploadFiles(ctx, grpc.WaitForReady(true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -266,9 +267,9 @@ func uploadFiles(ctx context.Context, client pb.DebugdClient, in deployOnEndpoin
|
||||||
}
|
}
|
||||||
switch uploadResponse.Status {
|
switch uploadResponse.Status {
|
||||||
case pb.UploadFilesStatus_UPLOAD_FILES_SUCCESS:
|
case pb.UploadFilesStatus_UPLOAD_FILES_SUCCESS:
|
||||||
in.log.Infof("Upload successful")
|
in.log.Info("Upload successful")
|
||||||
case pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_FINISHED:
|
case pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_FINISHED:
|
||||||
in.log.Infof("Files already uploaded")
|
in.log.Info("Files already uploaded")
|
||||||
case pb.UploadFilesStatus_UPLOAD_FILES_UPLOAD_FAILED:
|
case pb.UploadFilesStatus_UPLOAD_FILES_UPLOAD_FAILED:
|
||||||
return fmt.Errorf("uploading files to %v failed: %v", in.debugdEndpoint, uploadResponse)
|
return fmt.Errorf("uploading files to %v failed: %v", in.debugdEndpoint, uploadResponse)
|
||||||
case pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_STARTED:
|
case pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_STARTED:
|
||||||
|
|
|
@ -16,12 +16,10 @@ go_library(
|
||||||
"//debugd/internal/filetransfer",
|
"//debugd/internal/filetransfer",
|
||||||
"//debugd/service",
|
"//debugd/service",
|
||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/logger",
|
|
||||||
"@com_github_coreos_go_systemd_v22//dbus",
|
"@com_github_coreos_go_systemd_v22//dbus",
|
||||||
"@com_github_spf13_afero//:afero",
|
"@com_github_spf13_afero//:afero",
|
||||||
"@org_golang_google_grpc//:go_default_library",
|
"@org_golang_google_grpc//:go_default_library",
|
||||||
"@org_golang_google_grpc//credentials/insecure",
|
"@org_golang_google_grpc//credentials/insecure",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -11,21 +11,20 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer"
|
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer"
|
||||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Download downloads a bootstrapper from a given debugd instance.
|
// Download downloads a bootstrapper from a given debugd instance.
|
||||||
type Download struct {
|
type Download struct {
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
dialer NetDialer
|
dialer NetDialer
|
||||||
transfer fileTransferer
|
transfer fileTransferer
|
||||||
serviceManager serviceManager
|
serviceManager serviceManager
|
||||||
|
@ -33,7 +32,7 @@ type Download struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Download.
|
// New creates a new Download.
|
||||||
func New(log *logger.Logger, dialer NetDialer, serviceManager serviceManager,
|
func New(log *slog.Logger, dialer NetDialer, serviceManager serviceManager,
|
||||||
transfer fileTransferer, info infoSetter,
|
transfer fileTransferer, info infoSetter,
|
||||||
) *Download {
|
) *Download {
|
||||||
return &Download{
|
return &Download{
|
||||||
|
@ -51,7 +50,7 @@ func (d *Download) DownloadInfo(ctx context.Context, ip string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log := d.log.With(zap.String("ip", ip))
|
log := d.log.With(slog.String("ip", ip))
|
||||||
serverAddr := net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort))
|
serverAddr := net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort))
|
||||||
|
|
||||||
client, closer, err := d.newClient(ctx, serverAddr, log)
|
client, closer, err := d.newClient(ctx, serverAddr, log)
|
||||||
|
@ -60,19 +59,19 @@ func (d *Download) DownloadInfo(ctx context.Context, ip string) error {
|
||||||
}
|
}
|
||||||
defer closer.Close()
|
defer closer.Close()
|
||||||
|
|
||||||
log.Infof("Trying to download info")
|
log.Info("Trying to download info")
|
||||||
resp, err := client.GetInfo(ctx, &pb.GetInfoRequest{})
|
resp, err := client.GetInfo(ctx, &pb.GetInfoRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getting info from other instance: %w", err)
|
return fmt.Errorf("getting info from other instance: %w", err)
|
||||||
}
|
}
|
||||||
log.Infof("Successfully downloaded info")
|
log.Info("Successfully downloaded info")
|
||||||
|
|
||||||
return d.info.SetProto(resp.Info)
|
return d.info.SetProto(resp.Info)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadDeployment will open a new grpc connection to another instance, attempting to download files from that instance.
|
// DownloadDeployment will open a new grpc connection to another instance, attempting to download files from that instance.
|
||||||
func (d *Download) DownloadDeployment(ctx context.Context, ip string) error {
|
func (d *Download) DownloadDeployment(ctx context.Context, ip string) error {
|
||||||
log := d.log.With(zap.String("ip", ip))
|
log := d.log.With(slog.String("ip", ip))
|
||||||
serverAddr := net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort))
|
serverAddr := net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort))
|
||||||
|
|
||||||
client, closer, err := d.newClient(ctx, serverAddr, log)
|
client, closer, err := d.newClient(ctx, serverAddr, log)
|
||||||
|
@ -81,7 +80,7 @@ func (d *Download) DownloadDeployment(ctx context.Context, ip string) error {
|
||||||
}
|
}
|
||||||
defer closer.Close()
|
defer closer.Close()
|
||||||
|
|
||||||
log.Infof("Trying to download files")
|
log.Info("Trying to download files")
|
||||||
stream, err := client.DownloadFiles(ctx, &pb.DownloadFilesRequest{})
|
stream, err := client.DownloadFiles(ctx, &pb.DownloadFilesRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("starting file download from other instance: %w", err)
|
return fmt.Errorf("starting file download from other instance: %w", err)
|
||||||
|
@ -90,15 +89,15 @@ func (d *Download) DownloadDeployment(ctx context.Context, ip string) error {
|
||||||
err = d.transfer.RecvFiles(stream)
|
err = d.transfer.RecvFiles(stream)
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
d.log.Infof("Downloading files succeeded")
|
d.log.Info("Downloading files succeeded")
|
||||||
case errors.Is(err, filetransfer.ErrReceiveRunning):
|
case errors.Is(err, filetransfer.ErrReceiveRunning):
|
||||||
d.log.Warnf("Download already in progress")
|
d.log.Warn("Download already in progress")
|
||||||
return err
|
return err
|
||||||
case errors.Is(err, filetransfer.ErrReceiveFinished):
|
case errors.Is(err, filetransfer.ErrReceiveFinished):
|
||||||
d.log.Warnf("Download already finished")
|
d.log.Warn("Download already finished")
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
d.log.With(zap.Error(err)).Errorf("Downloading files failed")
|
d.log.With(slog.Any("error", err)).Error("Downloading files failed")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,15 +110,15 @@ func (d *Download) DownloadDeployment(ctx context.Context, ip string) error {
|
||||||
ctx, file.OverrideServiceUnit, file.TargetPath,
|
ctx, file.OverrideServiceUnit, file.TargetPath,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
// continue on error to allow other units to be overridden
|
// continue on error to allow other units to be overridden
|
||||||
d.log.With(zap.Error(err)).Errorf("Failed to override service unit %s", file.OverrideServiceUnit)
|
d.log.With(slog.Any("error", err)).Error(fmt.Sprintf("Failed to override service unit %s", file.OverrideServiceUnit))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Download) newClient(ctx context.Context, serverAddr string, log *logger.Logger) (pb.DebugdClient, io.Closer, error) {
|
func (d *Download) newClient(ctx context.Context, serverAddr string, log *slog.Logger) (pb.DebugdClient, io.Closer, error) {
|
||||||
log.Infof("Connecting to server")
|
log.Info("Connecting to server")
|
||||||
conn, err := d.dial(ctx, serverAddr)
|
conn, err := d.dial(ctx, serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("connecting to other instance via gRPC: %w", err)
|
return nil, nil, fmt.Errorf("connecting to other instance via gRPC: %w", err)
|
||||||
|
|
|
@ -9,15 +9,14 @@ package deploy
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -60,14 +59,14 @@ type SystemdUnit struct {
|
||||||
|
|
||||||
// ServiceManager receives ServiceManagerRequests and units via channels and performs the requests / creates the unit files.
|
// ServiceManager receives ServiceManagerRequests and units via channels and performs the requests / creates the unit files.
|
||||||
type ServiceManager struct {
|
type ServiceManager struct {
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
dbus dbusClient
|
dbus dbusClient
|
||||||
fs afero.Fs
|
fs afero.Fs
|
||||||
systemdUnitFilewriteLock sync.Mutex
|
systemdUnitFilewriteLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServiceManager creates a new ServiceManager.
|
// NewServiceManager creates a new ServiceManager.
|
||||||
func NewServiceManager(log *logger.Logger) *ServiceManager {
|
func NewServiceManager(log *slog.Logger) *ServiceManager {
|
||||||
fs := afero.NewOsFs()
|
fs := afero.NewOsFs()
|
||||||
return &ServiceManager{
|
return &ServiceManager{
|
||||||
log: log,
|
log: log,
|
||||||
|
@ -102,7 +101,7 @@ type dbusConn interface {
|
||||||
|
|
||||||
// SystemdAction will perform a systemd action on a service unit (start, stop, restart, reload).
|
// SystemdAction will perform a systemd action on a service unit (start, stop, restart, reload).
|
||||||
func (s *ServiceManager) SystemdAction(ctx context.Context, request ServiceManagerRequest) error {
|
func (s *ServiceManager) SystemdAction(ctx context.Context, request ServiceManagerRequest) error {
|
||||||
log := s.log.With(zap.String("unit", request.Unit), zap.String("action", request.Action.String()))
|
log := s.log.With(slog.String("unit", request.Unit), slog.String("action", request.Action.String()))
|
||||||
conn, err := s.dbus.NewSystemConnectionContext(ctx)
|
conn, err := s.dbus.NewSystemConnectionContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("establishing systemd connection: %w", err)
|
return fmt.Errorf("establishing systemd connection: %w", err)
|
||||||
|
@ -127,7 +126,7 @@ func (s *ServiceManager) SystemdAction(ctx context.Context, request ServiceManag
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.Action == Reload {
|
if request.Action == Reload {
|
||||||
log.Infof("daemon-reload succeeded")
|
log.Info("daemon-reload succeeded")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Wait for the action to finish and then check if it was
|
// Wait for the action to finish and then check if it was
|
||||||
|
@ -136,7 +135,7 @@ func (s *ServiceManager) SystemdAction(ctx context.Context, request ServiceManag
|
||||||
|
|
||||||
switch result {
|
switch result {
|
||||||
case "done":
|
case "done":
|
||||||
log.Infof("%s on systemd unit %s succeeded", request.Action, request.Unit)
|
log.Info(fmt.Sprintf("%s on systemd unit %s succeeded", request.Action, request.Unit))
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -146,8 +145,8 @@ func (s *ServiceManager) SystemdAction(ctx context.Context, request ServiceManag
|
||||||
|
|
||||||
// WriteSystemdUnitFile will write a systemd unit to disk.
|
// WriteSystemdUnitFile will write a systemd unit to disk.
|
||||||
func (s *ServiceManager) WriteSystemdUnitFile(ctx context.Context, unit SystemdUnit) error {
|
func (s *ServiceManager) WriteSystemdUnitFile(ctx context.Context, unit SystemdUnit) error {
|
||||||
log := s.log.With(zap.String("unitFile", fmt.Sprintf("%s/%s", systemdUnitFolder, unit.Name)))
|
log := s.log.With(slog.String("unitFile", fmt.Sprintf("%s/%s", systemdUnitFolder, unit.Name)))
|
||||||
log.Infof("Writing systemd unit file")
|
log.Info("Writing systemd unit file")
|
||||||
s.systemdUnitFilewriteLock.Lock()
|
s.systemdUnitFilewriteLock.Lock()
|
||||||
defer s.systemdUnitFilewriteLock.Unlock()
|
defer s.systemdUnitFilewriteLock.Unlock()
|
||||||
if err := afero.WriteFile(s.fs, fmt.Sprintf("%s/%s", systemdUnitFolder, unit.Name), []byte(unit.Contents), 0o644); err != nil {
|
if err := afero.WriteFile(s.fs, fmt.Sprintf("%s/%s", systemdUnitFolder, unit.Name), []byte(unit.Contents), 0o644); err != nil {
|
||||||
|
@ -158,14 +157,14 @@ func (s *ServiceManager) WriteSystemdUnitFile(ctx context.Context, unit SystemdU
|
||||||
return fmt.Errorf("performing systemd daemon-reload: %w", err)
|
return fmt.Errorf("performing systemd daemon-reload: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Wrote systemd unit file and performed daemon-reload")
|
log.Info("Wrote systemd unit file and performed daemon-reload")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OverrideServiceUnitExecStart will override the ExecStart of a systemd unit.
|
// OverrideServiceUnitExecStart will override the ExecStart of a systemd unit.
|
||||||
func (s *ServiceManager) OverrideServiceUnitExecStart(ctx context.Context, unitName, execStart string) error {
|
func (s *ServiceManager) OverrideServiceUnitExecStart(ctx context.Context, unitName, execStart string) error {
|
||||||
log := s.log.With(zap.String("unitFile", fmt.Sprintf("%s/%s", systemdUnitFolder, unitName)))
|
log := s.log.With(slog.String("unitFile", fmt.Sprintf("%s/%s", systemdUnitFolder, unitName)))
|
||||||
log.Infof("Overriding systemd unit file execStart")
|
log.Info("Overriding systemd unit file execStart")
|
||||||
if !systemdUnitNameRegexp.MatchString(unitName) {
|
if !systemdUnitNameRegexp.MatchString(unitName) {
|
||||||
return fmt.Errorf("unit name %q is invalid", unitName)
|
return fmt.Errorf("unit name %q is invalid", unitName)
|
||||||
}
|
}
|
||||||
|
@ -187,13 +186,13 @@ func (s *ServiceManager) OverrideServiceUnitExecStart(ctx context.Context, unitN
|
||||||
// do not return early here
|
// do not return early here
|
||||||
// the "daemon-reload" command may return an unrelated error
|
// the "daemon-reload" command may return an unrelated error
|
||||||
// and there is no way to know if the override was successful
|
// and there is no way to know if the override was successful
|
||||||
log.Warnf("Failed to perform systemd daemon-reload: %v", err)
|
log.Warn(fmt.Sprintf("Failed to perform systemd daemon-reload: %v", err))
|
||||||
}
|
}
|
||||||
if err := s.SystemdAction(ctx, ServiceManagerRequest{Unit: unitName + ".service", Action: Restart}); err != nil {
|
if err := s.SystemdAction(ctx, ServiceManagerRequest{Unit: unitName + ".service", Action: Restart}); err != nil {
|
||||||
log.Warnf("Failed to perform unit restart: %v", err)
|
log.Warn(fmt.Sprintf("Failed to perform unit restart: %v", err))
|
||||||
return fmt.Errorf("performing systemd unit restart: %w", err)
|
return fmt.Errorf("performing systemd unit restart: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Overrode systemd unit file execStart, performed daemon-reload and restarted unit %v", unitName)
|
log.Info(fmt.Sprintf("Overrode systemd unit file execStart, performed daemon-reload and restarted unit %v", unitName))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ go_library(
|
||||||
"//debugd/internal/debugd/info",
|
"//debugd/internal/debugd/info",
|
||||||
"//internal/cloud/cloudprovider",
|
"//internal/cloud/cloudprovider",
|
||||||
"//internal/cloud/metadata",
|
"//internal/cloud/metadata",
|
||||||
"//internal/logger",
|
|
||||||
"//internal/versions",
|
"//internal/versions",
|
||||||
"@com_github_aws_aws_sdk_go_v2_config//:config",
|
"@com_github_aws_aws_sdk_go_v2_config//:config",
|
||||||
"@com_github_aws_aws_sdk_go_v2_service_secretsmanager//:secretsmanager",
|
"@com_github_aws_aws_sdk_go_v2_service_secretsmanager//:secretsmanager",
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -22,7 +23,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/info"
|
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/info"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,60 +36,60 @@ const (
|
||||||
//
|
//
|
||||||
// This requires podman to be installed.
|
// This requires podman to be installed.
|
||||||
func NewStartTrigger(ctx context.Context, wg *sync.WaitGroup, provider cloudprovider.Provider,
|
func NewStartTrigger(ctx context.Context, wg *sync.WaitGroup, provider cloudprovider.Provider,
|
||||||
metadata providerMetadata, logger *logger.Logger,
|
metadata providerMetadata, logger *slog.Logger,
|
||||||
) func(*info.Map) {
|
) func(*info.Map) {
|
||||||
return func(infoMap *info.Map) {
|
return func(infoMap *info.Map) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
logger.Infof("Start trigger running")
|
logger.Info("Start trigger running")
|
||||||
|
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
logger.With("err", err).Errorf("Start trigger canceled")
|
logger.With("err", err).Error("Start trigger canceled")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("Get flags from infos")
|
logger.Info("Get flags from infos")
|
||||||
_, ok, err := infoMap.Get("logcollect")
|
_, ok, err := infoMap.Get("logcollect")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Getting infos: %v", err)
|
logger.Error(fmt.Sprintf("Getting infos: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Infof("Flag 'logcollect' not set")
|
logger.Info("Flag 'logcollect' not set")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cerdsGetter, err := newCloudCredentialGetter(ctx, provider, infoMap)
|
cerdsGetter, err := newCloudCredentialGetter(ctx, provider, infoMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Creating cloud credential getter: %v", err)
|
logger.Error(fmt.Sprintf("Creating cloud credential getter: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("Getting credentials")
|
logger.Info("Getting credentials")
|
||||||
creds, err := cerdsGetter.GetOpensearchCredentials(ctx)
|
creds, err := cerdsGetter.GetOpensearchCredentials(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Getting opensearch credentials: %v", err)
|
logger.Error(fmt.Sprintf("Getting opensearch credentials: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("Getting logstash pipeline template from image %s", versions.LogstashImage)
|
logger.Info(fmt.Sprintf("Getting logstash pipeline template from image %s", versions.LogstashImage))
|
||||||
tmpl, err := getTemplate(ctx, logger, versions.LogstashImage, "/run/logstash/templates/pipeline.conf", "/run/logstash")
|
tmpl, err := getTemplate(ctx, logger, versions.LogstashImage, "/run/logstash/templates/pipeline.conf", "/run/logstash")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Getting logstash pipeline template: %v", err)
|
logger.Error(fmt.Sprintf("Getting logstash pipeline template: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
infoMapM, err := infoMap.GetCopy()
|
infoMapM, err := infoMap.GetCopy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Getting copy of map from info: %v", err)
|
logger.Error(fmt.Sprintf("Getting copy of map from info: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
infoMapM = filterInfoMap(infoMapM)
|
infoMapM = filterInfoMap(infoMapM)
|
||||||
setCloudMetadata(ctx, infoMapM, provider, metadata)
|
setCloudMetadata(ctx, infoMapM, provider, metadata)
|
||||||
|
|
||||||
logger.Infof("Writing logstash pipeline")
|
logger.Info("Writing logstash pipeline")
|
||||||
pipelineConf := logstashConfInput{
|
pipelineConf := logstashConfInput{
|
||||||
Port: 5044,
|
Port: 5044,
|
||||||
Host: openSearchHost,
|
Host: openSearchHost,
|
||||||
|
@ -97,14 +97,14 @@ func NewStartTrigger(ctx context.Context, wg *sync.WaitGroup, provider cloudprov
|
||||||
Credentials: creds,
|
Credentials: creds,
|
||||||
}
|
}
|
||||||
if err := writeTemplate("/run/logstash/pipeline/pipeline.conf", tmpl, pipelineConf); err != nil {
|
if err := writeTemplate("/run/logstash/pipeline/pipeline.conf", tmpl, pipelineConf); err != nil {
|
||||||
logger.Errorf("Writing logstash config: %v", err)
|
logger.Error(fmt.Sprintf("Writing logstash config: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("Getting filebeat config template from image %s", versions.FilebeatImage)
|
logger.Info(fmt.Sprintf("Getting filebeat config template from image %s", versions.FilebeatImage))
|
||||||
tmpl, err = getTemplate(ctx, logger, versions.FilebeatImage, "/run/filebeat/templates/filebeat.yml", "/run/filebeat")
|
tmpl, err = getTemplate(ctx, logger, versions.FilebeatImage, "/run/filebeat/templates/filebeat.yml", "/run/filebeat")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Getting filebeat config template: %v", err)
|
logger.Error(fmt.Sprintf("Getting filebeat config template: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
filebeatConf := filebeatConfInput{
|
filebeatConf := filebeatConfInput{
|
||||||
|
@ -112,26 +112,26 @@ func NewStartTrigger(ctx context.Context, wg *sync.WaitGroup, provider cloudprov
|
||||||
AddCloudMetadata: true,
|
AddCloudMetadata: true,
|
||||||
}
|
}
|
||||||
if err := writeTemplate("/run/filebeat/filebeat.yml", tmpl, filebeatConf); err != nil {
|
if err := writeTemplate("/run/filebeat/filebeat.yml", tmpl, filebeatConf); err != nil {
|
||||||
logger.Errorf("Writing filebeat pipeline: %v", err)
|
logger.Error(fmt.Sprintf("Writing filebeat pipeline: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("Starting log collection pod")
|
logger.Info("Starting log collection pod")
|
||||||
if err := startPod(ctx, logger); err != nil {
|
if err := startPod(ctx, logger); err != nil {
|
||||||
logger.Errorf("Starting log collection: %v", err)
|
logger.Error(fmt.Sprintf("Starting log collection: %v", err))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTemplate(ctx context.Context, logger *logger.Logger, image, templateDir, destDir string) (*template.Template, error) {
|
func getTemplate(ctx context.Context, logger *slog.Logger, image, templateDir, destDir string) (*template.Template, error) {
|
||||||
createContainerArgs := []string{
|
createContainerArgs := []string{
|
||||||
"create",
|
"create",
|
||||||
"--name=template",
|
"--name=template",
|
||||||
image,
|
image,
|
||||||
}
|
}
|
||||||
createContainerCmd := exec.CommandContext(ctx, "podman", createContainerArgs...)
|
createContainerCmd := exec.CommandContext(ctx, "podman", createContainerArgs...)
|
||||||
logger.Infof("Creating template container")
|
logger.Info("Creating template container")
|
||||||
if out, err := createContainerCmd.CombinedOutput(); err != nil {
|
if out, err := createContainerCmd.CombinedOutput(); err != nil {
|
||||||
return nil, fmt.Errorf("creating template container: %w\n%s", err, out)
|
return nil, fmt.Errorf("creating template container: %w\n%s", err, out)
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ func getTemplate(ctx context.Context, logger *logger.Logger, image, templateDir,
|
||||||
destDir,
|
destDir,
|
||||||
}
|
}
|
||||||
copyFromCmd := exec.CommandContext(ctx, "podman", copyFromArgs...)
|
copyFromCmd := exec.CommandContext(ctx, "podman", copyFromArgs...)
|
||||||
logger.Infof("Copying templates")
|
logger.Info("Copying templates")
|
||||||
if out, err := copyFromCmd.CombinedOutput(); err != nil {
|
if out, err := copyFromCmd.CombinedOutput(); err != nil {
|
||||||
return nil, fmt.Errorf("copying templates: %w\n%s", err, out)
|
return nil, fmt.Errorf("copying templates: %w\n%s", err, out)
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ func getTemplate(ctx context.Context, logger *logger.Logger, image, templateDir,
|
||||||
"template",
|
"template",
|
||||||
}
|
}
|
||||||
removeContainerCmd := exec.CommandContext(ctx, "podman", removeContainerArgs...)
|
removeContainerCmd := exec.CommandContext(ctx, "podman", removeContainerArgs...)
|
||||||
logger.Infof("Removing template container")
|
logger.Info("Removing template container")
|
||||||
if out, err := removeContainerCmd.CombinedOutput(); err != nil {
|
if out, err := removeContainerCmd.CombinedOutput(); err != nil {
|
||||||
return nil, fmt.Errorf("removing template container: %w\n%s", err, out)
|
return nil, fmt.Errorf("removing template container: %w\n%s", err, out)
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ func getTemplate(ctx context.Context, logger *logger.Logger, image, templateDir,
|
||||||
return tmpl, nil
|
return tmpl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startPod(ctx context.Context, logger *logger.Logger) error {
|
func startPod(ctx context.Context, logger *slog.Logger) error {
|
||||||
// create a shared pod for filebeat, metricbeat and logstash
|
// create a shared pod for filebeat, metricbeat and logstash
|
||||||
createPodArgs := []string{
|
createPodArgs := []string{
|
||||||
"pod",
|
"pod",
|
||||||
|
@ -177,13 +177,13 @@ func startPod(ctx context.Context, logger *logger.Logger) error {
|
||||||
"logcollection",
|
"logcollection",
|
||||||
}
|
}
|
||||||
createPodCmd := exec.CommandContext(ctx, "podman", createPodArgs...)
|
createPodCmd := exec.CommandContext(ctx, "podman", createPodArgs...)
|
||||||
logger.Infof("Create pod command: %v", createPodCmd.String())
|
logger.Info(fmt.Sprintf("Create pod command: %v", createPodCmd.String()))
|
||||||
if out, err := createPodCmd.CombinedOutput(); err != nil {
|
if out, err := createPodCmd.CombinedOutput(); err != nil {
|
||||||
return fmt.Errorf("failed to create pod: %w; output: %s", err, out)
|
return fmt.Errorf("failed to create pod: %w; output: %s", err, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// start logstash container
|
// start logstash container
|
||||||
logstashLog := newCmdLogger(logger.Named("logstash"))
|
logstashLog := newCmdLogger(logger.WithGroup("logstash"))
|
||||||
runLogstashArgs := []string{
|
runLogstashArgs := []string{
|
||||||
"run",
|
"run",
|
||||||
"--rm",
|
"--rm",
|
||||||
|
@ -194,7 +194,7 @@ func startPod(ctx context.Context, logger *logger.Logger) error {
|
||||||
versions.LogstashImage,
|
versions.LogstashImage,
|
||||||
}
|
}
|
||||||
runLogstashCmd := exec.CommandContext(ctx, "podman", runLogstashArgs...)
|
runLogstashCmd := exec.CommandContext(ctx, "podman", runLogstashArgs...)
|
||||||
logger.Infof("Run logstash command: %v", runLogstashCmd.String())
|
logger.Info(fmt.Sprintf("Run logstash command: %v", runLogstashCmd.String()))
|
||||||
runLogstashCmd.Stdout = logstashLog
|
runLogstashCmd.Stdout = logstashLog
|
||||||
runLogstashCmd.Stderr = logstashLog
|
runLogstashCmd.Stderr = logstashLog
|
||||||
if err := runLogstashCmd.Start(); err != nil {
|
if err := runLogstashCmd.Start(); err != nil {
|
||||||
|
@ -202,7 +202,7 @@ func startPod(ctx context.Context, logger *logger.Logger) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// start filebeat container
|
// start filebeat container
|
||||||
filebeatLog := newCmdLogger(logger.Named("filebeat"))
|
filebeatLog := newCmdLogger(logger.WithGroup("filebeat"))
|
||||||
runFilebeatArgs := []string{
|
runFilebeatArgs := []string{
|
||||||
"run",
|
"run",
|
||||||
"--rm",
|
"--rm",
|
||||||
|
@ -219,7 +219,7 @@ func startPod(ctx context.Context, logger *logger.Logger) error {
|
||||||
versions.FilebeatImage,
|
versions.FilebeatImage,
|
||||||
}
|
}
|
||||||
runFilebeatCmd := exec.CommandContext(ctx, "podman", runFilebeatArgs...)
|
runFilebeatCmd := exec.CommandContext(ctx, "podman", runFilebeatArgs...)
|
||||||
logger.Infof("Run filebeat command: %v", runFilebeatCmd.String())
|
logger.Info(fmt.Sprintf("Run filebeat command: %v", runFilebeatCmd.String()))
|
||||||
runFilebeatCmd.Stdout = filebeatLog
|
runFilebeatCmd.Stdout = filebeatLog
|
||||||
runFilebeatCmd.Stderr = filebeatLog
|
runFilebeatCmd.Stderr = filebeatLog
|
||||||
if err := runFilebeatCmd.Start(); err != nil {
|
if err := runFilebeatCmd.Start(); err != nil {
|
||||||
|
@ -295,16 +295,16 @@ func setCloudMetadata(ctx context.Context, m map[string]string, provider cloudpr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCmdLogger(logger *logger.Logger) io.Writer {
|
func newCmdLogger(logger *slog.Logger) io.Writer {
|
||||||
return &cmdLogger{logger: logger}
|
return &cmdLogger{logger: logger}
|
||||||
}
|
}
|
||||||
|
|
||||||
type cmdLogger struct {
|
type cmdLogger struct {
|
||||||
logger *logger.Logger
|
logger *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cmdLogger) Write(p []byte) (n int, err error) {
|
func (c *cmdLogger) Write(p []byte) (n int, err error) {
|
||||||
c.logger.Infof("%s", p)
|
c.logger.Info(string(p))
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,7 @@ go_library(
|
||||||
],
|
],
|
||||||
importpath = "github.com/edgelesssys/constellation/v2/debugd/internal/debugd/metadata",
|
importpath = "github.com/edgelesssys/constellation/v2/debugd/internal/debugd/metadata",
|
||||||
visibility = ["//debugd:__subpackages__"],
|
visibility = ["//debugd:__subpackages__"],
|
||||||
deps = [
|
deps = ["//debugd/internal/debugd"],
|
||||||
"//debugd/internal/debugd",
|
|
||||||
"//internal/logger",
|
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
|
|
|
@ -8,12 +8,11 @@ package metadata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"log/slog"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd"
|
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fetcher retrieves other debugd IPs from cloud provider metadata.
|
// Fetcher retrieves other debugd IPs from cloud provider metadata.
|
||||||
|
@ -24,7 +23,7 @@ type Fetcher interface {
|
||||||
|
|
||||||
// Scheduler schedules fetching of metadata using timers.
|
// Scheduler schedules fetching of metadata using timers.
|
||||||
type Scheduler struct {
|
type Scheduler struct {
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
fetcher Fetcher
|
fetcher Fetcher
|
||||||
downloader downloader
|
downloader downloader
|
||||||
deploymentDone bool
|
deploymentDone bool
|
||||||
|
@ -33,7 +32,7 @@ type Scheduler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewScheduler returns a new scheduler.
|
// NewScheduler returns a new scheduler.
|
||||||
func NewScheduler(log *logger.Logger, fetcher Fetcher, downloader downloader) *Scheduler {
|
func NewScheduler(log *slog.Logger, fetcher Fetcher, downloader downloader) *Scheduler {
|
||||||
return &Scheduler{
|
return &Scheduler{
|
||||||
log: log,
|
log: log,
|
||||||
fetcher: fetcher,
|
fetcher: fetcher,
|
||||||
|
@ -60,22 +59,22 @@ func (s *Scheduler) Start(ctx context.Context, wg *sync.WaitGroup) {
|
||||||
|
|
||||||
ips, err := s.fetcher.DiscoverDebugdIPs(ctx)
|
ips, err := s.fetcher.DiscoverDebugdIPs(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.With(zap.Error(err)).Warnf("Discovering debugd IPs failed")
|
s.log.With(slog.Any("error", err)).Warn("Discovering debugd IPs failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
lbip, err := s.fetcher.DiscoverLoadBalancerIP(ctx)
|
lbip, err := s.fetcher.DiscoverLoadBalancerIP(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.With(zap.Error(err)).Warnf("Discovering load balancer IP failed")
|
s.log.With(slog.Any("error", err)).Warn("Discovering load balancer IP failed")
|
||||||
} else {
|
} else {
|
||||||
ips = append(ips, lbip)
|
ips = append(ips, lbip)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
s.log.With(zap.Error(err)).Warnf("No debugd IPs discovered")
|
s.log.With(slog.Any("error", err)).Warn("No debugd IPs discovered")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
s.log.With(zap.Strings("ips", ips)).Infof("Discovered instances")
|
s.log.With(slog.Any("ips", ips)).Info("Discovered instances")
|
||||||
s.download(ctx, ips)
|
s.download(ctx, ips)
|
||||||
if s.deploymentDone && s.infoDone {
|
if s.deploymentDone && s.infoDone {
|
||||||
return
|
return
|
||||||
|
@ -90,8 +89,8 @@ func (s *Scheduler) download(ctx context.Context, ips []string) {
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
if !s.deploymentDone {
|
if !s.deploymentDone {
|
||||||
if err := s.downloader.DownloadDeployment(ctx, ip); err != nil {
|
if err := s.downloader.DownloadDeployment(ctx, ip); err != nil {
|
||||||
s.log.With(zap.Error(err), zap.String("peer", ip)).
|
s.log.With(slog.Any("error", err), slog.String("peer", ip)).
|
||||||
Warnf("Downloading deployment from %s: %s", ip, err)
|
Warn("Downloading deployment from %s: %s", ip, err)
|
||||||
} else {
|
} else {
|
||||||
s.deploymentDone = true
|
s.deploymentDone = true
|
||||||
}
|
}
|
||||||
|
@ -99,8 +98,8 @@ func (s *Scheduler) download(ctx context.Context, ips []string) {
|
||||||
|
|
||||||
if !s.infoDone {
|
if !s.infoDone {
|
||||||
if err := s.downloader.DownloadInfo(ctx, ip); err != nil {
|
if err := s.downloader.DownloadInfo(ctx, ip); err != nil {
|
||||||
s.log.With(zap.Error(err), zap.String("peer", ip)).
|
s.log.With(slog.Any("error", err), slog.String("peer", ip)).
|
||||||
Warnf("Downloading info from %s: %s", ip, err)
|
Warn("Downloading info from %s: %s", ip, err)
|
||||||
} else {
|
} else {
|
||||||
s.infoDone = true
|
s.infoDone = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ go_library(
|
||||||
"//internal/logger",
|
"//internal/logger",
|
||||||
"@org_golang_google_grpc//:go_default_library",
|
"@org_golang_google_grpc//:go_default_library",
|
||||||
"@org_golang_google_grpc//keepalive",
|
"@org_golang_google_grpc//keepalive",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,9 @@ package server
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -21,13 +23,12 @@ import (
|
||||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"go.uber.org/zap"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/keepalive"
|
"google.golang.org/grpc/keepalive"
|
||||||
)
|
)
|
||||||
|
|
||||||
type debugdServer struct {
|
type debugdServer struct {
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
serviceManager serviceManager
|
serviceManager serviceManager
|
||||||
transfer fileTransferer
|
transfer fileTransferer
|
||||||
info *info.Map
|
info *info.Map
|
||||||
|
@ -36,7 +37,7 @@ type debugdServer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new debugdServer according to the gRPC spec.
|
// New creates a new debugdServer according to the gRPC spec.
|
||||||
func New(log *logger.Logger, serviceManager serviceManager, transfer fileTransferer, infos *info.Map) pb.DebugdServer {
|
func New(log *slog.Logger, serviceManager serviceManager, transfer fileTransferer, infos *info.Map) pb.DebugdServer {
|
||||||
return &debugdServer{
|
return &debugdServer{
|
||||||
log: log,
|
log: log,
|
||||||
serviceManager: serviceManager,
|
serviceManager: serviceManager,
|
||||||
|
@ -47,25 +48,25 @@ func New(log *logger.Logger, serviceManager serviceManager, transfer fileTransfe
|
||||||
|
|
||||||
// SetInfo sets the info of the debugd instance.
|
// SetInfo sets the info of the debugd instance.
|
||||||
func (s *debugdServer) SetInfo(_ context.Context, req *pb.SetInfoRequest) (*pb.SetInfoResponse, error) {
|
func (s *debugdServer) SetInfo(_ context.Context, req *pb.SetInfoRequest) (*pb.SetInfoResponse, error) {
|
||||||
s.log.Infof("Received SetInfo request")
|
s.log.Info("Received SetInfo request")
|
||||||
|
|
||||||
if len(req.Info) == 0 {
|
if len(req.Info) == 0 {
|
||||||
s.log.Infof("Info is empty")
|
s.log.Info("Info is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
setProtoErr := s.info.SetProto(req.Info)
|
setProtoErr := s.info.SetProto(req.Info)
|
||||||
if errors.Is(setProtoErr, info.ErrInfoAlreadySet) {
|
if errors.Is(setProtoErr, info.ErrInfoAlreadySet) {
|
||||||
s.log.Warnf("Setting info failed (already set)")
|
s.log.Warn("Setting info failed (already set)")
|
||||||
return &pb.SetInfoResponse{
|
return &pb.SetInfoResponse{
|
||||||
Status: pb.SetInfoStatus_SET_INFO_ALREADY_SET,
|
Status: pb.SetInfoStatus_SET_INFO_ALREADY_SET,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if setProtoErr != nil {
|
if setProtoErr != nil {
|
||||||
s.log.With(zap.Error(setProtoErr)).Errorf("Setting info failed")
|
s.log.With(slog.Any("error", setProtoErr)).Error("Setting info failed")
|
||||||
return nil, setProtoErr
|
return nil, setProtoErr
|
||||||
}
|
}
|
||||||
s.log.Infof("Info set")
|
s.log.Info("Info set")
|
||||||
|
|
||||||
return &pb.SetInfoResponse{
|
return &pb.SetInfoResponse{
|
||||||
Status: pb.SetInfoStatus_SET_INFO_SUCCESS,
|
Status: pb.SetInfoStatus_SET_INFO_SUCCESS,
|
||||||
|
@ -74,7 +75,7 @@ func (s *debugdServer) SetInfo(_ context.Context, req *pb.SetInfoRequest) (*pb.S
|
||||||
|
|
||||||
// GetInfo returns the info of the debugd instance.
|
// GetInfo returns the info of the debugd instance.
|
||||||
func (s *debugdServer) GetInfo(_ context.Context, _ *pb.GetInfoRequest) (*pb.GetInfoResponse, error) {
|
func (s *debugdServer) GetInfo(_ context.Context, _ *pb.GetInfoRequest) (*pb.GetInfoResponse, error) {
|
||||||
s.log.Infof("Received GetInfo request")
|
s.log.Info("Received GetInfo request")
|
||||||
|
|
||||||
info, err := s.info.GetProto()
|
info, err := s.info.GetProto()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -86,23 +87,23 @@ func (s *debugdServer) GetInfo(_ context.Context, _ *pb.GetInfoRequest) (*pb.Get
|
||||||
|
|
||||||
// UploadFiles receives a stream of files (each consisting of a header and a stream of chunks) and writes them to the filesystem.
|
// UploadFiles receives a stream of files (each consisting of a header and a stream of chunks) and writes them to the filesystem.
|
||||||
func (s *debugdServer) UploadFiles(stream pb.Debugd_UploadFilesServer) error {
|
func (s *debugdServer) UploadFiles(stream pb.Debugd_UploadFilesServer) error {
|
||||||
s.log.Infof("Received UploadFiles request")
|
s.log.Info("Received UploadFiles request")
|
||||||
err := s.transfer.RecvFiles(stream)
|
err := s.transfer.RecvFiles(stream)
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
s.log.Infof("Uploading files succeeded")
|
s.log.Info("Uploading files succeeded")
|
||||||
case errors.Is(err, filetransfer.ErrReceiveRunning):
|
case errors.Is(err, filetransfer.ErrReceiveRunning):
|
||||||
s.log.Warnf("Upload already in progress")
|
s.log.Warn("Upload already in progress")
|
||||||
return stream.SendAndClose(&pb.UploadFilesResponse{
|
return stream.SendAndClose(&pb.UploadFilesResponse{
|
||||||
Status: pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_STARTED,
|
Status: pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_STARTED,
|
||||||
})
|
})
|
||||||
case errors.Is(err, filetransfer.ErrReceiveFinished):
|
case errors.Is(err, filetransfer.ErrReceiveFinished):
|
||||||
s.log.Warnf("Upload already finished")
|
s.log.Warn("Upload already finished")
|
||||||
return stream.SendAndClose(&pb.UploadFilesResponse{
|
return stream.SendAndClose(&pb.UploadFilesResponse{
|
||||||
Status: pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_FINISHED,
|
Status: pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_FINISHED,
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
s.log.With(zap.Error(err)).Errorf("Uploading files failed")
|
s.log.With(slog.Any("error", err)).Error("Uploading files failed")
|
||||||
return stream.SendAndClose(&pb.UploadFilesResponse{
|
return stream.SendAndClose(&pb.UploadFilesResponse{
|
||||||
Status: pb.UploadFilesStatus_UPLOAD_FILES_UPLOAD_FAILED,
|
Status: pb.UploadFilesStatus_UPLOAD_FILES_UPLOAD_FAILED,
|
||||||
})
|
})
|
||||||
|
@ -120,7 +121,7 @@ func (s *debugdServer) UploadFiles(stream pb.Debugd_UploadFilesServer) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if overrideUnitErr != nil {
|
if overrideUnitErr != nil {
|
||||||
s.log.With(zap.Error(overrideUnitErr)).Errorf("Overriding service units failed")
|
s.log.With(slog.Any("error", overrideUnitErr)).Error("Overriding service units failed")
|
||||||
return stream.SendAndClose(&pb.UploadFilesResponse{
|
return stream.SendAndClose(&pb.UploadFilesResponse{
|
||||||
Status: pb.UploadFilesStatus_UPLOAD_FILES_START_FAILED,
|
Status: pb.UploadFilesStatus_UPLOAD_FILES_START_FAILED,
|
||||||
})
|
})
|
||||||
|
@ -132,13 +133,13 @@ func (s *debugdServer) UploadFiles(stream pb.Debugd_UploadFilesServer) error {
|
||||||
|
|
||||||
// DownloadFiles streams the previously received files to other instances.
|
// DownloadFiles streams the previously received files to other instances.
|
||||||
func (s *debugdServer) DownloadFiles(_ *pb.DownloadFilesRequest, stream pb.Debugd_DownloadFilesServer) error {
|
func (s *debugdServer) DownloadFiles(_ *pb.DownloadFilesRequest, stream pb.Debugd_DownloadFilesServer) error {
|
||||||
s.log.Infof("Sending files to other instance")
|
s.log.Info("Sending files to other instance")
|
||||||
return s.transfer.SendFiles(stream)
|
return s.transfer.SendFiles(stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadSystemServiceUnits receives systemd service units, writes them to a service file and schedules a daemon-reload.
|
// UploadSystemServiceUnits receives systemd service units, writes them to a service file and schedules a daemon-reload.
|
||||||
func (s *debugdServer) UploadSystemServiceUnits(ctx context.Context, in *pb.UploadSystemdServiceUnitsRequest) (*pb.UploadSystemdServiceUnitsResponse, error) {
|
func (s *debugdServer) UploadSystemServiceUnits(ctx context.Context, in *pb.UploadSystemdServiceUnitsRequest) (*pb.UploadSystemdServiceUnitsResponse, error) {
|
||||||
s.log.Infof("Uploading systemd service units")
|
s.log.Info("Uploading systemd service units")
|
||||||
for _, unit := range in.Units {
|
for _, unit := range in.Units {
|
||||||
if err := s.serviceManager.WriteSystemdUnitFile(ctx, deploy.SystemdUnit{Name: unit.Name, Contents: unit.Contents}); err != nil {
|
if err := s.serviceManager.WriteSystemdUnitFile(ctx, deploy.SystemdUnit{Name: unit.Name, Contents: unit.Contents}); err != nil {
|
||||||
return &pb.UploadSystemdServiceUnitsResponse{Status: pb.UploadSystemdServiceUnitsStatus_UPLOAD_SYSTEMD_SERVICE_UNITS_FAILURE}, nil
|
return &pb.UploadSystemdServiceUnitsResponse{Status: pb.UploadSystemdServiceUnitsStatus_UPLOAD_SYSTEMD_SERVICE_UNITS_FAILURE}, nil
|
||||||
|
@ -149,25 +150,26 @@ func (s *debugdServer) UploadSystemServiceUnits(ctx context.Context, in *pb.Uplo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start will start the gRPC server as goroutine.
|
// Start will start the gRPC server as goroutine.
|
||||||
func Start(log *logger.Logger, wg *sync.WaitGroup, serv pb.DebugdServer) {
|
func Start(log *slog.Logger, wg *sync.WaitGroup, serv pb.DebugdServer) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
grpcLog := log.Named("gRPC")
|
grpcLog := log.WithGroup("gRPC")
|
||||||
grpcLog.WithIncreasedLevel(zap.WarnLevel).ReplaceGRPCLogger()
|
logger.ReplaceGRPCLogger(slog.New(logger.NewLevelHandler(slog.LevelWarn, grpcLog.Handler())))
|
||||||
|
|
||||||
grpcServer := grpc.NewServer(
|
grpcServer := grpc.NewServer(
|
||||||
grpcLog.GetServerStreamInterceptor(),
|
logger.GetServerStreamInterceptor(grpcLog),
|
||||||
grpcLog.GetServerUnaryInterceptor(),
|
logger.GetServerUnaryInterceptor(grpcLog),
|
||||||
grpc.KeepaliveParams(keepalive.ServerParameters{Time: 15 * time.Second}),
|
grpc.KeepaliveParams(keepalive.ServerParameters{Time: 15 * time.Second}),
|
||||||
)
|
)
|
||||||
pb.RegisterDebugdServer(grpcServer, serv)
|
pb.RegisterDebugdServer(grpcServer, serv)
|
||||||
lis, err := net.Listen("tcp", net.JoinHostPort("0.0.0.0", strconv.Itoa(constants.DebugdPort)))
|
lis, err := net.Listen("tcp", net.JoinHostPort("0.0.0.0", strconv.Itoa(constants.DebugdPort)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Listening failed")
|
log.With(slog.Any("error", err)).Error("Listening failed")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
log.Infof("gRPC server is waiting for connections")
|
log.Info("gRPC server is waiting for connections")
|
||||||
grpcServer.Serve(lis)
|
grpcServer.Serve(lis)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,6 @@ go_library(
|
||||||
"//debugd/internal/debugd",
|
"//debugd/internal/debugd",
|
||||||
"//debugd/internal/filetransfer/streamer",
|
"//debugd/internal/filetransfer/streamer",
|
||||||
"//debugd/service",
|
"//debugd/service",
|
||||||
"//internal/logger",
|
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -10,16 +10,16 @@ package filetransfer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"log/slog"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd"
|
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd"
|
||||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer/streamer"
|
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer/streamer"
|
||||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// RecvFilesStream is a stream that receives FileTransferMessages.
|
// RecvFilesStream is a stream that receives FileTransferMessages.
|
||||||
|
@ -35,7 +35,7 @@ type SendFilesStream interface {
|
||||||
// FileTransferer manages sending and receiving of files.
|
// FileTransferer manages sending and receiving of files.
|
||||||
type FileTransferer struct {
|
type FileTransferer struct {
|
||||||
fileMux sync.RWMutex
|
fileMux sync.RWMutex
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
receiveStarted bool
|
receiveStarted bool
|
||||||
receiveFinished atomic.Bool
|
receiveFinished atomic.Bool
|
||||||
files []FileStat
|
files []FileStat
|
||||||
|
@ -44,7 +44,7 @@ type FileTransferer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new FileTransferer.
|
// New creates a new FileTransferer.
|
||||||
func New(log *logger.Logger, streamer streamReadWriter, showProgress bool) *FileTransferer {
|
func New(log *slog.Logger, streamer streamReadWriter, showProgress bool) *FileTransferer {
|
||||||
return &FileTransferer{
|
return &FileTransferer{
|
||||||
log: log,
|
log: log,
|
||||||
streamer: streamer,
|
streamer: streamer,
|
||||||
|
@ -146,7 +146,7 @@ func (s *FileTransferer) handleFileRecv(stream RecvFilesStream) (bool, error) {
|
||||||
if header == nil {
|
if header == nil {
|
||||||
return false, errors.New("first message must be a header message")
|
return false, errors.New("first message must be a header message")
|
||||||
}
|
}
|
||||||
s.log.Infof("Starting file receive of %q", header.TargetPath)
|
s.log.Info(fmt.Sprintf("Starting file receive of %q", header.TargetPath))
|
||||||
s.addFile(FileStat{
|
s.addFile(FileStat{
|
||||||
SourcePath: header.TargetPath,
|
SourcePath: header.TargetPath,
|
||||||
TargetPath: header.TargetPath,
|
TargetPath: header.TargetPath,
|
||||||
|
@ -160,10 +160,10 @@ func (s *FileTransferer) handleFileRecv(stream RecvFilesStream) (bool, error) {
|
||||||
})
|
})
|
||||||
recvChunkStream := &recvChunkStream{stream: stream}
|
recvChunkStream := &recvChunkStream{stream: stream}
|
||||||
if err := s.streamer.WriteStream(header.TargetPath, recvChunkStream, s.showProgress); err != nil {
|
if err := s.streamer.WriteStream(header.TargetPath, recvChunkStream, s.showProgress); err != nil {
|
||||||
s.log.With(zap.Error(err)).Errorf("Receive of file %q failed", header.TargetPath)
|
s.log.With(slog.Any("error", err)).Error(fmt.Sprintf("Receive of file %q failed", header.TargetPath))
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
s.log.Infof("Finished file receive of %q", header.TargetPath)
|
s.log.Info(fmt.Sprintf("Finished file receive of %q", header.TargetPath))
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,57 +21,67 @@ It is also recommended to use golangci-lint (and [gofumpt](https://github.com/mv
|
||||||
|
|
||||||
## Logging
|
## Logging
|
||||||
|
|
||||||
We use a [custom subset](/internal/logger/) of [zap](https://pkg.go.dev/go.uber.org/zap) to provide logging for Constellation’s services and components.
|
We use [slog](https://pkg.go.dev/log/slog) for logging.
|
||||||
Usage instructions can be found in the package documentation.
|
Usage instructions can be found in the package documentation.
|
||||||
|
|
||||||
Certain components may further specify a subset of the logger for their use. For example, the CLI has a debug-only logger, restricting the use of the logger to only `Debugf()`.
|
Certain components may further specify a subset of the logger for their use. For example, the CLI has a debug-only logger, restricting the use of the logger to only `Debug()`.
|
||||||
|
|
||||||
Further we try to adhere to the following guidelines:
|
Further we try to adhere to the following guidelines:
|
||||||
|
|
||||||
* Do not log potentially sensitive information, e.g. variables that contain keys, secrets or otherwise protected information.
|
* Do not log potentially sensitive information, e.g. variables that contain keys, secrets or otherwise protected information.
|
||||||
|
|
||||||
|
* Create a text or JSON logger using the helper functions in the `logger` package. These create a `slog.Logger` with useful defaults.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```Go
|
||||||
|
log := logger.NewTextLogger(slog.LevelDebug)
|
||||||
|
log.Debug("A debug message")
|
||||||
|
```
|
||||||
|
|
||||||
* Start log messages in uppercase and end without a punctuation mark. Exclamation, question marks, or ellipsis may be used where appropriate.
|
* Start log messages in uppercase and end without a punctuation mark. Exclamation, question marks, or ellipsis may be used where appropriate.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```Go
|
```Go
|
||||||
log.Infof("This is a log message")
|
log.Info("This is a log message")
|
||||||
log.Infof("Waiting to do something...")
|
log.Info("Waiting to do something...")
|
||||||
log.Error("A critical error occurred!")
|
log.Error("A critical error occurred!")
|
||||||
```
|
```
|
||||||
|
|
||||||
* Use the `With()` method to add structured context to your log messages. The context tags should be easily searchable to allow for easy log filtering. Try to keep consistent tag naming!
|
* Use additional arguments to add structured context to your log messages. The context tags should be easily searchable to allow for easy log filtering. Try to keep consistent tag naming!
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```Go
|
```Go
|
||||||
log.With(zap.Error(someError), zap.String("ip", "192.0.2.1")).Errorf("Connecting to IP failed")
|
log.Error("Connecting to IP failed", "error", someError, "ip", "192.0.2.1")
|
||||||
```
|
```
|
||||||
|
|
||||||
* Log messages may use format strings to produce human readable messages. However, the information should also be present as structured context fields if it might be valuable for debugging purposes.
|
* Log messages may use format strings to produce human readable messages. However, the information should also be present as structured context fields if it might be valuable for debugging purposes. So, instead of writing
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```Go
|
```Go
|
||||||
log.Infof("Starting server on %s:%s", addr, port)
|
log.Info(fmt.Sprintf("Starting server on %s:%s", addr, port))
|
||||||
```
|
```
|
||||||
|
|
||||||
* Usage of the `Fatalf()` method should be constrained to the main package of an application only!
|
You should write
|
||||||
|
|
||||||
|
```Go
|
||||||
|
log.Info("Starting server", "addr", addr, "port", port)
|
||||||
|
```
|
||||||
|
|
||||||
* Use log levels to configure how detailed the logs of you application should be.
|
* Use log levels to configure how detailed the logs of you application should be.
|
||||||
|
|
||||||
* `Debugf()` for log low level and detailed information. This may include variable dumps, but should not disclose sensitive information, e.g. keys or secret tokens.
|
* `Debug()` for log low level and detailed information. This may include variable dumps, but should not disclose sensitive information, e.g. keys or secret tokens.
|
||||||
* `Infof()` for general information.
|
* `Info()` for general information.
|
||||||
* `Warnf()` for information that may indicate unwanted behavior, but is not an application error. Commonly used by retry loops.
|
* `Warn()` for information that may indicate unwanted behavior, but is not an application error. Commonly used by retry loops.
|
||||||
* `Errorf()` to log information about any errors that occurred.
|
* `Error()` to log information about any errors that occurred.
|
||||||
* `Fatalf()` to log information about any errors that occurred and then exit the program. Should only be used in the main package of an application.
|
|
||||||
|
|
||||||
* Loggers passed to subpackages of an application may use the `Named()` method for better understanding of where a message originated.
|
* Loggers passed to subpackages of an application may use the `WithGroup()` method for better understanding of where a message originated.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```Go
|
```Go
|
||||||
grpcServer, err := server.New(log.Named("server"))
|
grpcServer, err := server.New(log.WithGroup("server"))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Nested Go modules
|
## Nested Go modules
|
||||||
|
|
|
@ -30,7 +30,6 @@ go_library(
|
||||||
"//internal/logger",
|
"//internal/logger",
|
||||||
"//internal/role",
|
"//internal/role",
|
||||||
"@com_github_spf13_afero//:afero",
|
"@com_github_spf13_afero//:afero",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -35,7 +37,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -51,18 +52,20 @@ func main() {
|
||||||
verbosity := flag.Int("v", 0, logger.CmdLineVerbosityDescription)
|
verbosity := flag.Int("v", 0, logger.CmdLineVerbosityDescription)
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
log := logger.New(logger.JSONLog, logger.VerbosityFromInt(*verbosity))
|
log := logger.NewJSONLogger(logger.VerbosityFromInt(*verbosity))
|
||||||
log.With(zap.String("version", constants.BinaryVersion().String()), zap.String("cloudProvider", *csp)).
|
log.With(slog.String("version", constants.BinaryVersion().String()), slog.String("cloudProvider", *csp)).
|
||||||
Infof("Starting disk-mapper")
|
Info("Starting disk-mapper")
|
||||||
|
|
||||||
// set up quote issuer for aTLS connections
|
// set up quote issuer for aTLS connections
|
||||||
attestVariant, err := variant.FromString(os.Getenv(constants.AttestationVariant))
|
attestVariant, err := variant.FromString(os.Getenv(constants.AttestationVariant))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to parse attestation variant")
|
log.With(slog.Any("error", err)).Error("Failed to parse attestation variant")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
issuer, err := choose.Issuer(attestVariant, log)
|
issuer, err := choose.Issuer(attestVariant, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to select issuer")
|
log.With(slog.Any("error", err)).Error("Failed to select issuer")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up metadata API
|
// set up metadata API
|
||||||
|
@ -74,31 +77,37 @@ func main() {
|
||||||
// using udev rules, a symlink for our disk is created at /dev/sdb
|
// using udev rules, a symlink for our disk is created at /dev/sdb
|
||||||
diskPath, err = filepath.EvalSymlinks(awsStateDiskPath)
|
diskPath, err = filepath.EvalSymlinks(awsStateDiskPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Unable to resolve Azure state disk path")
|
log.With(slog.Any("error", err)).Error("Unable to resolve Azure state disk path")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
metadataClient, err = awscloud.New(context.Background())
|
metadataClient, err = awscloud.New(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to set up AWS metadata client")
|
log.With(slog.Any("error", err)).Error("Failed to set up AWS metadata client")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
case cloudprovider.Azure:
|
case cloudprovider.Azure:
|
||||||
diskPath, err = filepath.EvalSymlinks(azureStateDiskPath)
|
diskPath, err = filepath.EvalSymlinks(azureStateDiskPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Unable to resolve Azure state disk path")
|
log.With(slog.Any("error", err)).Error("Unable to resolve Azure state disk path")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
metadataClient, err = azurecloud.New(context.Background())
|
metadataClient, err = azurecloud.New(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to set up Azure metadata client")
|
log.With(slog.Any("error", err)).Error("Failed to set up Azure metadata client")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
case cloudprovider.GCP:
|
case cloudprovider.GCP:
|
||||||
diskPath, err = filepath.EvalSymlinks(gcpStateDiskPath)
|
diskPath, err = filepath.EvalSymlinks(gcpStateDiskPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Unable to resolve GCP state disk path")
|
log.With(slog.Any("error", err)).Error("Unable to resolve GCP state disk path")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
gcpMeta, err := gcpcloud.New(context.Background())
|
gcpMeta, err := gcpcloud.New(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to create GCP metadata client")
|
log.With(slog.Any("error", err)).Error(("Failed to create GCP metadata client"))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer gcpMeta.Close()
|
defer gcpMeta.Close()
|
||||||
metadataClient = gcpMeta
|
metadataClient = gcpMeta
|
||||||
|
@ -107,7 +116,8 @@ func main() {
|
||||||
diskPath = openstackStateDiskPath
|
diskPath = openstackStateDiskPath
|
||||||
metadataClient, err = openstack.New(context.Background())
|
metadataClient, err = openstack.New(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to create OpenStack metadata client")
|
log.With(slog.Any("error", err)).Error(("Failed to create OpenStack metadata client"))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
case cloudprovider.QEMU:
|
case cloudprovider.QEMU:
|
||||||
|
@ -115,13 +125,15 @@ func main() {
|
||||||
metadataClient = qemucloud.New()
|
metadataClient = qemucloud.New()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Fatalf("CSP %s is not supported by Constellation", *csp)
|
log.Error(fmt.Sprintf("CSP %s is not supported by Constellation", *csp))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize device mapper
|
// initialize device mapper
|
||||||
mapper, free, err := diskencryption.New(diskPath, log)
|
mapper, free, err := diskencryption.New(diskPath, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to initialize device mapper")
|
log.With(slog.Any("error", err)).Error(("Failed to initialize device mapper"))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer free()
|
defer free()
|
||||||
|
|
||||||
|
@ -133,7 +145,7 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setupManger := setup.New(
|
setupManger := setup.New(
|
||||||
log.Named("setupManager"),
|
log.WithGroup("setupManager"),
|
||||||
*csp,
|
*csp,
|
||||||
diskPath,
|
diskPath,
|
||||||
afero.Afero{Fs: afero.NewOsFs()},
|
afero.Afero{Fs: afero.NewOsFs()},
|
||||||
|
@ -143,7 +155,8 @@ func main() {
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := setupManger.LogDevices(); err != nil {
|
if err := setupManger.LogDevices(); err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to log devices")
|
log.With(slog.Any("error", err)).Error(("Failed to log devices"))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare the state disk
|
// prepare the state disk
|
||||||
|
@ -152,21 +165,22 @@ func main() {
|
||||||
var self metadata.InstanceMetadata
|
var self metadata.InstanceMetadata
|
||||||
self, err = metadataClient.Self(context.Background())
|
self, err = metadataClient.Self(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to get self metadata")
|
log.With(slog.Any("error", err)).Error(("Failed to get self metadata"))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
rejoinClient := rejoinclient.New(
|
rejoinClient := rejoinclient.New(
|
||||||
dialer.New(issuer, nil, &net.Dialer{}),
|
dialer.New(issuer, nil, &net.Dialer{}),
|
||||||
self,
|
self,
|
||||||
metadataClient,
|
metadataClient,
|
||||||
log.Named("rejoinClient"),
|
log.WithGroup("rejoinClient"),
|
||||||
)
|
)
|
||||||
|
|
||||||
// set up recovery server if control-plane node
|
// set up recovery server if control-plane node
|
||||||
var recoveryServer setup.RecoveryServer
|
var recoveryServer setup.RecoveryServer
|
||||||
if self.Role == role.ControlPlane {
|
if self.Role == role.ControlPlane {
|
||||||
recoveryServer = recoveryserver.New(issuer, kmssetup.KMS, log.Named("recoveryServer"))
|
recoveryServer = recoveryserver.New(issuer, kmssetup.KMS, log.WithGroup("recoveryServer"))
|
||||||
} else {
|
} else {
|
||||||
recoveryServer = recoveryserver.NewStub(log.Named("recoveryServer"))
|
recoveryServer = recoveryserver.NewStub(log.WithGroup("recoveryServer"))
|
||||||
}
|
}
|
||||||
|
|
||||||
err = setupManger.PrepareExistingDisk(setup.NewNodeRecoverer(recoveryServer, rejoinClient))
|
err = setupManger.PrepareExistingDisk(setup.NewNodeRecoverer(recoveryServer, rejoinClient))
|
||||||
|
@ -174,6 +188,7 @@ func main() {
|
||||||
err = setupManger.PrepareNewDisk()
|
err = setupManger.PrepareNewDisk()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to prepare state disk")
|
log.With(slog.Any("error", err)).Error(("Failed to prepare state disk"))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,5 @@ go_library(
|
||||||
srcs = ["diskencryption.go"],
|
srcs = ["diskencryption.go"],
|
||||||
importpath = "github.com/edgelesssys/constellation/v2/disk-mapper/internal/diskencryption",
|
importpath = "github.com/edgelesssys/constellation/v2/disk-mapper/internal/diskencryption",
|
||||||
visibility = ["//disk-mapper:__subpackages__"],
|
visibility = ["//disk-mapper:__subpackages__"],
|
||||||
deps = [
|
deps = ["//internal/cryptsetup"],
|
||||||
"//internal/cryptsetup",
|
|
||||||
"//internal/logger",
|
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,22 +15,21 @@ package diskencryption
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cryptsetup"
|
"github.com/edgelesssys/constellation/v2/internal/cryptsetup"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DiskEncryption handles actions for formatting and mapping crypt devices.
|
// DiskEncryption handles actions for formatting and mapping crypt devices.
|
||||||
type DiskEncryption struct {
|
type DiskEncryption struct {
|
||||||
device cryptDevice
|
device cryptDevice
|
||||||
devicePath string
|
devicePath string
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new crypt device for the device at path.
|
// New creates a new crypt device for the device at path.
|
||||||
func New(path string, log *logger.Logger) (*DiskEncryption, func(), error) {
|
func New(path string, log *slog.Logger) (*DiskEncryption, func(), error) {
|
||||||
device := cryptsetup.New()
|
device := cryptsetup.New()
|
||||||
_, err := device.Init(path)
|
_, err := device.Init(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -101,7 +100,7 @@ func (d *DiskEncryption) UnmapDisk(target string) error {
|
||||||
func (d *DiskEncryption) Wipe(blockWipeSize int) error {
|
func (d *DiskEncryption) Wipe(blockWipeSize int) error {
|
||||||
logProgress := func(size, offset uint64) {
|
logProgress := func(size, offset uint64) {
|
||||||
prog := (float64(offset) / float64(size)) * 100
|
prog := (float64(offset) / float64(size)) * 100
|
||||||
d.log.With(zap.String("progress", fmt.Sprintf("%.2f%%", prog))).Infof("Wiping disk")
|
d.log.With(slog.String("progress", fmt.Sprintf("%.2f%%", prog))).Info("Wiping disk")
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
@ -109,7 +108,7 @@ func (d *DiskEncryption) Wipe(blockWipeSize int) error {
|
||||||
if err := d.device.Wipe("integrity", blockWipeSize, 0, logProgress, 30*time.Second); err != nil {
|
if err := d.device.Wipe("integrity", blockWipeSize, 0, logProgress, 30*time.Second); err != nil {
|
||||||
return fmt.Errorf("wiping disk: %w", err)
|
return fmt.Errorf("wiping disk: %w", err)
|
||||||
}
|
}
|
||||||
d.log.With(zap.Duration("duration", time.Since(start))).Infof("Wiping disk successful")
|
d.log.With(slog.Duration("duration", time.Since(start))).Info("Wiping disk successful")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ go_library(
|
||||||
"@org_golang_google_grpc//:go_default_library",
|
"@org_golang_google_grpc//:go_default_library",
|
||||||
"@org_golang_google_grpc//codes",
|
"@org_golang_google_grpc//codes",
|
||||||
"@org_golang_google_grpc//status",
|
"@org_golang_google_grpc//status",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ package recoveryserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
@ -27,7 +28,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/grpc/grpclog"
|
"github.com/edgelesssys/constellation/v2/internal/grpc/grpclog"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/kms/kms"
|
"github.com/edgelesssys/constellation/v2/internal/kms/kms"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"go.uber.org/zap"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
|
@ -45,13 +45,13 @@ type RecoveryServer struct {
|
||||||
grpcServer server
|
grpcServer server
|
||||||
factory kmsFactory
|
factory kmsFactory
|
||||||
|
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
|
|
||||||
recoverproto.UnimplementedAPIServer
|
recoverproto.UnimplementedAPIServer
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new RecoveryServer.
|
// New returns a new RecoveryServer.
|
||||||
func New(issuer atls.Issuer, factory kmsFactory, log *logger.Logger) *RecoveryServer {
|
func New(issuer atls.Issuer, factory kmsFactory, log *slog.Logger) *RecoveryServer {
|
||||||
server := &RecoveryServer{
|
server := &RecoveryServer{
|
||||||
log: log,
|
log: log,
|
||||||
factory: factory,
|
factory: factory,
|
||||||
|
@ -59,7 +59,7 @@ func New(issuer atls.Issuer, factory kmsFactory, log *logger.Logger) *RecoverySe
|
||||||
|
|
||||||
grpcServer := grpc.NewServer(
|
grpcServer := grpc.NewServer(
|
||||||
grpc.Creds(atlscredentials.New(issuer, nil)),
|
grpc.Creds(atlscredentials.New(issuer, nil)),
|
||||||
log.Named("gRPC").GetServerStreamInterceptor(),
|
logger.GetServerStreamInterceptor(log.WithGroup("gRPC")),
|
||||||
)
|
)
|
||||||
recoverproto.RegisterAPIServer(grpcServer, server)
|
recoverproto.RegisterAPIServer(grpcServer, server)
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ func New(issuer atls.Issuer, factory kmsFactory, log *logger.Logger) *RecoverySe
|
||||||
// The server will shut down when the call is successful and the keys are returned.
|
// The server will shut down when the call is successful and the keys are returned.
|
||||||
// Additionally, the server can be shutdown by canceling the context.
|
// Additionally, the server can be shutdown by canceling the context.
|
||||||
func (s *RecoveryServer) Serve(ctx context.Context, listener net.Listener, diskUUID string) (diskKey, measurementSecret []byte, err error) {
|
func (s *RecoveryServer) Serve(ctx context.Context, listener net.Listener, diskUUID string) (diskKey, measurementSecret []byte, err error) {
|
||||||
s.log.Infof("Starting RecoveryServer")
|
s.log.Info("Starting RecoveryServer")
|
||||||
s.diskUUID = diskUUID
|
s.diskUUID = diskUUID
|
||||||
recoveryDone := make(chan struct{}, 1)
|
recoveryDone := make(chan struct{}, 1)
|
||||||
var serveErr error
|
var serveErr error
|
||||||
|
@ -89,7 +89,7 @@ func (s *RecoveryServer) Serve(ctx context.Context, listener net.Listener, diskU
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
s.log.Infof("Context canceled, shutting down server")
|
s.log.Info("Context canceled, shutting down server")
|
||||||
s.grpcServer.GracefulStop()
|
s.grpcServer.GracefulStop()
|
||||||
return nil, nil, ctx.Err()
|
return nil, nil, ctx.Err()
|
||||||
case <-recoveryDone:
|
case <-recoveryDone:
|
||||||
|
@ -105,9 +105,9 @@ func (s *RecoveryServer) Serve(ctx context.Context, listener net.Listener, diskU
|
||||||
func (s *RecoveryServer) Recover(ctx context.Context, req *recoverproto.RecoverMessage) (*recoverproto.RecoverResponse, error) {
|
func (s *RecoveryServer) Recover(ctx context.Context, req *recoverproto.RecoverMessage) (*recoverproto.RecoverResponse, error) {
|
||||||
s.mux.Lock()
|
s.mux.Lock()
|
||||||
defer s.mux.Unlock()
|
defer s.mux.Unlock()
|
||||||
log := s.log.With(zap.String("peer", grpclog.PeerAddrFromContext(ctx)))
|
log := s.log.With(slog.String("peer", grpclog.PeerAddrFromContext(ctx)))
|
||||||
|
|
||||||
log.Infof("Received recover call")
|
log.Info("Received recover call")
|
||||||
|
|
||||||
cloudKms, err := s.factory(ctx, req.StorageUri, req.KmsUri)
|
cloudKms, err := s.factory(ctx, req.StorageUri, req.KmsUri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -124,7 +124,7 @@ func (s *RecoveryServer) Recover(ctx context.Context, req *recoverproto.RecoverM
|
||||||
}
|
}
|
||||||
s.stateDiskKey = stateDiskKey
|
s.stateDiskKey = stateDiskKey
|
||||||
s.measurementSecret = measurementSecret
|
s.measurementSecret = measurementSecret
|
||||||
log.Infof("Received state disk key and measurement secret, shutting down server")
|
log.Info("Received state disk key and measurement secret, shutting down server")
|
||||||
|
|
||||||
go s.grpcServer.GracefulStop()
|
go s.grpcServer.GracefulStop()
|
||||||
return &recoverproto.RecoverResponse{}, nil
|
return &recoverproto.RecoverResponse{}, nil
|
||||||
|
@ -132,18 +132,18 @@ func (s *RecoveryServer) Recover(ctx context.Context, req *recoverproto.RecoverM
|
||||||
|
|
||||||
// StubServer implements the RecoveryServer interface but does not actually start a server.
|
// StubServer implements the RecoveryServer interface but does not actually start a server.
|
||||||
type StubServer struct {
|
type StubServer struct {
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStub returns a new stubbed RecoveryServer.
|
// NewStub returns a new stubbed RecoveryServer.
|
||||||
// We use this to avoid having to start a server for worker nodes, since they don't require manual recovery.
|
// We use this to avoid having to start a server for worker nodes, since they don't require manual recovery.
|
||||||
func NewStub(log *logger.Logger) *StubServer {
|
func NewStub(log *slog.Logger) *StubServer {
|
||||||
return &StubServer{log: log}
|
return &StubServer{log: log}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve waits until the context is canceled and returns nil.
|
// Serve waits until the context is canceled and returns nil.
|
||||||
func (s *StubServer) Serve(ctx context.Context, _ net.Listener, _ string) ([]byte, []byte, error) {
|
func (s *StubServer) Serve(ctx context.Context, _ net.Listener, _ string) ([]byte, []byte, error) {
|
||||||
s.log.Infof("Running as worker node, skipping recovery server")
|
s.log.Info("Running as worker node, skipping recovery server")
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
return nil, nil, ctx.Err()
|
return nil, nil, ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,10 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//internal/cloud/metadata",
|
"//internal/cloud/metadata",
|
||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/logger",
|
|
||||||
"//internal/role",
|
"//internal/role",
|
||||||
"//joinservice/joinproto",
|
"//joinservice/joinproto",
|
||||||
"@io_k8s_utils//clock",
|
"@io_k8s_utils//clock",
|
||||||
"@org_golang_google_grpc//:go_default_library",
|
"@org_golang_google_grpc//:go_default_library",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -15,16 +15,15 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/edgelesssys/constellation/v2/joinservice/joinproto"
|
"github.com/edgelesssys/constellation/v2/joinservice/joinproto"
|
||||||
"go.uber.org/zap"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"k8s.io/utils/clock"
|
"k8s.io/utils/clock"
|
||||||
)
|
)
|
||||||
|
@ -47,12 +46,12 @@ type RejoinClient struct {
|
||||||
dialer grpcDialer
|
dialer grpcDialer
|
||||||
metadataAPI metadataAPI
|
metadataAPI metadataAPI
|
||||||
|
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new RejoinClient.
|
// New returns a new RejoinClient.
|
||||||
func New(dial grpcDialer, nodeInfo metadata.InstanceMetadata,
|
func New(dial grpcDialer, nodeInfo metadata.InstanceMetadata,
|
||||||
meta metadataAPI, log *logger.Logger,
|
meta metadataAPI, log *slog.Logger,
|
||||||
) *RejoinClient {
|
) *RejoinClient {
|
||||||
return &RejoinClient{
|
return &RejoinClient{
|
||||||
nodeInfo: nodeInfo,
|
nodeInfo: nodeInfo,
|
||||||
|
@ -70,22 +69,22 @@ func New(dial grpcDialer, nodeInfo metadata.InstanceMetadata,
|
||||||
// from the metadata API and send rejoin requests to them.
|
// from the metadata API and send rejoin requests to them.
|
||||||
// The function returns after a successful rejoin request has been performed.
|
// The function returns after a successful rejoin request has been performed.
|
||||||
func (c *RejoinClient) Start(ctx context.Context, diskUUID string) (diskKey, measurementSecret []byte) {
|
func (c *RejoinClient) Start(ctx context.Context, diskUUID string) (diskKey, measurementSecret []byte) {
|
||||||
c.log.Infof("Starting RejoinClient")
|
c.log.Info("Starting RejoinClient")
|
||||||
c.diskUUID = diskUUID
|
c.diskUUID = diskUUID
|
||||||
ticker := c.clock.NewTicker(c.interval)
|
ticker := c.clock.NewTicker(c.interval)
|
||||||
|
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
defer c.log.Infof("RejoinClient stopped")
|
defer c.log.Info("RejoinClient stopped")
|
||||||
|
|
||||||
for {
|
for {
|
||||||
endpoints, err := c.getJoinEndpoints()
|
endpoints, err := c.getJoinEndpoints()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.With(zap.Error(err)).Errorf("Failed to get control-plane endpoints")
|
c.log.With(slog.Any("error", err)).Error("Failed to get control-plane endpoints")
|
||||||
} else {
|
} else {
|
||||||
c.log.With(zap.Strings("endpoints", endpoints)).Infof("Received list with JoinService endpoints")
|
c.log.With(slog.Any("endpoints", endpoints)).Info("Received list with JoinService endpoints")
|
||||||
diskKey, measurementSecret, err = c.tryRejoinWithAvailableServices(ctx, endpoints)
|
diskKey, measurementSecret, err = c.tryRejoinWithAvailableServices(ctx, endpoints)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.log.Infof("Successfully retrieved rejoin ticket")
|
c.log.Info("Successfully retrieved rejoin ticket")
|
||||||
return diskKey, measurementSecret
|
return diskKey, measurementSecret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,12 +100,12 @@ func (c *RejoinClient) Start(ctx context.Context, diskUUID string) (diskKey, mea
|
||||||
// tryRejoinWithAvailableServices tries sending rejoin requests to the available endpoints.
|
// tryRejoinWithAvailableServices tries sending rejoin requests to the available endpoints.
|
||||||
func (c *RejoinClient) tryRejoinWithAvailableServices(ctx context.Context, endpoints []string) (diskKey, measurementSecret []byte, err error) {
|
func (c *RejoinClient) tryRejoinWithAvailableServices(ctx context.Context, endpoints []string) (diskKey, measurementSecret []byte, err error) {
|
||||||
for _, endpoint := range endpoints {
|
for _, endpoint := range endpoints {
|
||||||
c.log.With(zap.String("endpoint", endpoint)).Infof("Requesting rejoin ticket")
|
c.log.With(slog.String("endpoint", endpoint)).Info("Requesting rejoin ticket")
|
||||||
rejoinTicket, err := c.requestRejoinTicket(endpoint)
|
rejoinTicket, err := c.requestRejoinTicket(endpoint)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return rejoinTicket.StateDiskKey, rejoinTicket.MeasurementSecret, nil
|
return rejoinTicket.StateDiskKey, rejoinTicket.MeasurementSecret, nil
|
||||||
}
|
}
|
||||||
c.log.With(zap.Error(err), zap.String("endpoint", endpoint)).Warnf("Failed to rejoin on endpoint")
|
c.log.With(slog.Any("error", err), slog.String("endpoint", endpoint)).Warn("Failed to rejoin on endpoint")
|
||||||
|
|
||||||
// stop requesting additional endpoints if the context is done
|
// stop requesting additional endpoints if the context is done
|
||||||
select {
|
select {
|
||||||
|
@ -115,7 +114,7 @@ func (c *RejoinClient) tryRejoinWithAvailableServices(ctx context.Context, endpo
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.log.Errorf("Failed to rejoin on all endpoints")
|
c.log.Error("Failed to rejoin on all endpoints")
|
||||||
return nil, nil, errors.New("failed to join on all endpoints")
|
return nil, nil, errors.New("failed to join on all endpoints")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,8 @@ go_library(
|
||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/crypto",
|
"//internal/crypto",
|
||||||
"//internal/file",
|
"//internal/file",
|
||||||
"//internal/logger",
|
|
||||||
"//internal/nodestate",
|
"//internal/nodestate",
|
||||||
"@com_github_spf13_afero//:afero",
|
"@com_github_spf13_afero//:afero",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -31,10 +32,8 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/crypto"
|
"github.com/edgelesssys/constellation/v2/internal/crypto"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/nodestate"
|
"github.com/edgelesssys/constellation/v2/internal/nodestate"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -49,7 +48,7 @@ const (
|
||||||
|
|
||||||
// Manager handles formatting, mapping, mounting and unmounting of state disks.
|
// Manager handles formatting, mapping, mounting and unmounting of state disks.
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
csp string
|
csp string
|
||||||
diskPath string
|
diskPath string
|
||||||
fs afero.Afero
|
fs afero.Afero
|
||||||
|
@ -60,7 +59,7 @@ type Manager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New initializes a SetupManager with the given parameters.
|
// New initializes a SetupManager with the given parameters.
|
||||||
func New(log *logger.Logger, csp string, diskPath string, fs afero.Afero,
|
func New(log *slog.Logger, csp string, diskPath string, fs afero.Afero,
|
||||||
mapper DeviceMapper, mounter Mounter, openDevice vtpm.TPMOpenFunc,
|
mapper DeviceMapper, mounter Mounter, openDevice vtpm.TPMOpenFunc,
|
||||||
) *Manager {
|
) *Manager {
|
||||||
return &Manager{
|
return &Manager{
|
||||||
|
@ -82,7 +81,7 @@ func (s *Manager) PrepareExistingDisk(recover RecoveryDoer) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.log.With(zap.String("uuid", uuid)).Infof("Preparing existing state disk")
|
s.log.With(slog.String("uuid", uuid)).Info("Preparing existing state disk")
|
||||||
endpoint := net.JoinHostPort("0.0.0.0", strconv.Itoa(constants.RecoveryPort))
|
endpoint := net.JoinHostPort("0.0.0.0", strconv.Itoa(constants.RecoveryPort))
|
||||||
|
|
||||||
passphrase, measurementSecret, err := recover.Do(uuid, endpoint)
|
passphrase, measurementSecret, err := recover.Do(uuid, endpoint)
|
||||||
|
@ -128,7 +127,7 @@ func (s *Manager) PrepareExistingDisk(recover RecoveryDoer) error {
|
||||||
// PrepareNewDisk prepares an instances state disk by formatting the disk as a LUKS device using a random passphrase.
|
// PrepareNewDisk prepares an instances state disk by formatting the disk as a LUKS device using a random passphrase.
|
||||||
func (s *Manager) PrepareNewDisk() error {
|
func (s *Manager) PrepareNewDisk() error {
|
||||||
uuid, _ := s.mapper.DiskUUID()
|
uuid, _ := s.mapper.DiskUUID()
|
||||||
s.log.With(zap.String("uuid", uuid)).Infof("Preparing new state disk")
|
s.log.With(slog.String("uuid", uuid)).Info("Preparing new state disk")
|
||||||
|
|
||||||
// generate and save temporary passphrase
|
// generate and save temporary passphrase
|
||||||
passphrase := make([]byte, crypto.RNGLengthDefault)
|
passphrase := make([]byte, crypto.RNGLengthDefault)
|
||||||
|
@ -192,12 +191,12 @@ func (s *Manager) LogDevices() error {
|
||||||
devices = append(devices, fileInfo)
|
devices = append(devices, fileInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.log.Infof("List of all available block devices and partitions:")
|
s.log.Info("List of all available block devices and partitions:")
|
||||||
for _, device := range devices {
|
for _, device := range devices {
|
||||||
var stat syscall.Statfs_t
|
var stat syscall.Statfs_t
|
||||||
dev := "/dev/" + device.Name()
|
dev := "/dev/" + device.Name()
|
||||||
if err := syscall.Statfs(dev, &stat); err != nil {
|
if err := syscall.Statfs(dev, &stat); err != nil {
|
||||||
s.log.With(zap.Error(err)).Errorf("failed to statfs %s", dev)
|
s.log.With(slog.Any("error", err)).Error(fmt.Sprintf("failed to statfs %s", dev))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +205,7 @@ func (s *Manager) LogDevices() error {
|
||||||
free := stat.Bfree * uint64(stat.Bsize)
|
free := stat.Bfree * uint64(stat.Bsize)
|
||||||
avail := stat.Bavail * uint64(stat.Bsize)
|
avail := stat.Bavail * uint64(stat.Bsize)
|
||||||
|
|
||||||
s.log.Infof(
|
s.log.Info(fmt.Sprintf(
|
||||||
"Name: %-15s, Size: %-10d, Mode: %s, ModTime: %s, Size = %-10d, Free = %-10d, Available = %-10d\n",
|
"Name: %-15s, Size: %-10d, Mode: %s, ModTime: %s, Size = %-10d, Free = %-10d, Available = %-10d\n",
|
||||||
dev,
|
dev,
|
||||||
device.Size(),
|
device.Size(),
|
||||||
|
@ -214,7 +213,7 @@ func (s *Manager) LogDevices() error {
|
||||||
device.ModTime(),
|
device.ModTime(),
|
||||||
size,
|
size,
|
||||||
free,
|
free,
|
||||||
avail)
|
avail))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ go_test(
|
||||||
"@com_github_stretchr_testify//require",
|
"@com_github_stretchr_testify//require",
|
||||||
"@io_bazel_rules_go//go/runfiles:go_default_library",
|
"@io_bazel_rules_go//go/runfiles:go_default_library",
|
||||||
"@org_uber_go_goleak//:goleak",
|
"@org_uber_go_goleak//:goleak",
|
||||||
"@org_uber_go_zap//zapcore",
|
|
||||||
],
|
],
|
||||||
"@io_bazel_rules_go//go/platform:linux": [
|
"@io_bazel_rules_go//go/platform:linux": [
|
||||||
"//disk-mapper/internal/diskencryption",
|
"//disk-mapper/internal/diskencryption",
|
||||||
|
@ -42,7 +41,6 @@ go_test(
|
||||||
"@com_github_stretchr_testify//require",
|
"@com_github_stretchr_testify//require",
|
||||||
"@io_bazel_rules_go//go/runfiles:go_default_library",
|
"@io_bazel_rules_go//go/runfiles:go_default_library",
|
||||||
"@org_uber_go_goleak//:goleak",
|
"@org_uber_go_goleak//:goleak",
|
||||||
"@org_uber_go_zap//zapcore",
|
|
||||||
],
|
],
|
||||||
"//conditions:default": [],
|
"//conditions:default": [],
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -10,13 +10,13 @@ package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/disk-mapper/internal/diskencryption"
|
"github.com/edgelesssys/constellation/v2/disk-mapper/internal/diskencryption"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/martinjungblut/go-cryptsetup"
|
"github.com/martinjungblut/go-cryptsetup"
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkMapper(b *testing.B) {
|
func BenchmarkMapper(b *testing.B) {
|
||||||
|
@ -39,7 +39,7 @@ func BenchmarkMapper(b *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
passphrase := "benchmark"
|
passphrase := "benchmark"
|
||||||
mapper, free, err := diskencryption.New(testPath, logger.New(logger.PlainLog, zapcore.InfoLevel))
|
mapper, free, err := diskencryption.New(testPath, logger.NewTextLogger(slog.LevelInfo))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal("Failed to create mapper:", err)
|
b.Fatal("Failed to create mapper:", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -103,7 +104,7 @@ func TestMapper(t *testing.T) {
|
||||||
require.NoError(setup(1), "failed to setup test disk")
|
require.NoError(setup(1), "failed to setup test disk")
|
||||||
defer func() { require.NoError(teardown(), "failed to delete test disk") }()
|
defer func() { require.NoError(teardown(), "failed to delete test disk") }()
|
||||||
|
|
||||||
mapper, free, err := diskencryption.New(devicePath, logger.NewTest(t))
|
mapper, free, err := diskencryption.New(devicePath, logger.NewTextLogger(slog.LevelInfo))
|
||||||
require.NoError(err, "failed to initialize crypt device")
|
require.NoError(err, "failed to initialize crypt device")
|
||||||
defer free()
|
defer free()
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ func servicesVersion(t *testing.T) (semver.Semver, error) {
|
||||||
settings := cli.New()
|
settings := cli.New()
|
||||||
settings.KubeConfig = "constellation-admin.conf"
|
settings.KubeConfig = "constellation-admin.conf"
|
||||||
actionConfig := &action.Configuration{}
|
actionConfig := &action.Configuration{}
|
||||||
if err := actionConfig.Init(settings.RESTClientGetter(), constants.HelmNamespace, "secret", log.Infof); err != nil {
|
if err := actionConfig.Init(settings.RESTClientGetter(), constants.HelmNamespace, "secret", log.Info); err != nil {
|
||||||
return semver.Semver{}, fmt.Errorf("initializing config: %w", err)
|
return semver.Semver{}, fmt.Errorf("initializing config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,6 @@ go_library(
|
||||||
"//internal/grpc/dialer",
|
"//internal/grpc/dialer",
|
||||||
"//internal/logger",
|
"//internal/logger",
|
||||||
"//joinservice/joinproto",
|
"//joinservice/joinproto",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
"@org_uber_go_zap//zapcore",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,9 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||||
|
@ -20,13 +22,10 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/grpc/dialer"
|
"github.com/edgelesssys/constellation/v2/internal/grpc/dialer"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/edgelesssys/constellation/v2/joinservice/joinproto"
|
"github.com/edgelesssys/constellation/v2/joinservice/joinproto"
|
||||||
"go.uber.org/zap"
|
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log := logger.New(logger.JSONLog, zapcore.DebugLevel)
|
log := logger.NewJSONLogger(slog.LevelDebug)
|
||||||
defer log.Sync()
|
|
||||||
|
|
||||||
jsEndpoint := flag.String("js-endpoint", "", "Join service endpoint to use.")
|
jsEndpoint := flag.String("js-endpoint", "", "Join service endpoint to use.")
|
||||||
csp := flag.String("csp", "", "Cloud service provider to use.")
|
csp := flag.String("csp", "", "Cloud service provider to use.")
|
||||||
|
@ -38,13 +37,13 @@ func main() {
|
||||||
)
|
)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
log.With(
|
log.With(
|
||||||
zap.String("js-endpoint", *jsEndpoint),
|
slog.String("js-endpoint", *jsEndpoint),
|
||||||
zap.String("csp", *csp),
|
slog.String("csp", *csp),
|
||||||
zap.String("variant", *attVariant),
|
slog.String("variant", *attVariant),
|
||||||
).Infof("Running tests with flags")
|
).Info("Running tests with flags")
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
fn func(attVariant, csp, jsEndpoint string, log *logger.Logger) error
|
fn func(attVariant, csp, jsEndpoint string, log *slog.Logger) error
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
"JoinFromUnattestedNode": {
|
"JoinFromUnattestedNode": {
|
||||||
|
@ -58,44 +57,45 @@ func main() {
|
||||||
TestCases: make(map[string]testCaseOutput),
|
TestCases: make(map[string]testCaseOutput),
|
||||||
}
|
}
|
||||||
for name, tc := range testCases {
|
for name, tc := range testCases {
|
||||||
log.With(zap.String("testcase", name)).Infof("Running testcase")
|
log.With(slog.String("testcase", name)).Info("Running testcase")
|
||||||
|
|
||||||
err := tc.fn(*attVariant, *csp, *jsEndpoint, log)
|
err := tc.fn(*attVariant, *csp, *jsEndpoint, log)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case err == nil && tc.wantErr:
|
case err == nil && tc.wantErr:
|
||||||
log.With(zap.Error(err), zap.String("testcase", name)).Errorf("Test case failed: Expected error but got none")
|
log.With(slog.Any("error", err), slog.String("testcase", name)).Error("Test case failed: Expected error but got none")
|
||||||
testOutput.TestCases[name] = testCaseOutput{
|
testOutput.TestCases[name] = testCaseOutput{
|
||||||
Passed: false,
|
Passed: false,
|
||||||
Message: "Expected error but got none",
|
Message: "Expected error but got none",
|
||||||
}
|
}
|
||||||
allPassed = false
|
allPassed = false
|
||||||
case !tc.wantErr && err != nil:
|
case !tc.wantErr && err != nil:
|
||||||
log.With(zap.Error(err), zap.String("testcase", name)).Errorf("Test case failed: Got unexpected error")
|
log.With(slog.Any("error", err), slog.String("testcase", name)).Error("Test case failed: Got unexpected error")
|
||||||
testOutput.TestCases[name] = testCaseOutput{
|
testOutput.TestCases[name] = testCaseOutput{
|
||||||
Passed: false,
|
Passed: false,
|
||||||
Message: fmt.Sprintf("Got unexpected error: %s", err),
|
Message: fmt.Sprintf("Got unexpected error: %s", err),
|
||||||
}
|
}
|
||||||
allPassed = false
|
allPassed = false
|
||||||
case tc.wantErr && err != nil:
|
case tc.wantErr && err != nil:
|
||||||
log.With(zap.String("testcase", name)).Infof("Test case succeeded")
|
log.With(slog.String("testcase", name)).Info("Test case succeeded")
|
||||||
testOutput.TestCases[name] = testCaseOutput{
|
testOutput.TestCases[name] = testCaseOutput{
|
||||||
Passed: true,
|
Passed: true,
|
||||||
Message: fmt.Sprintf("Got expected error: %s", err),
|
Message: fmt.Sprintf("Got expected error: %s", err),
|
||||||
}
|
}
|
||||||
case !tc.wantErr && err == nil:
|
case !tc.wantErr && err == nil:
|
||||||
log.With(zap.String("testcase", name)).Infof("Test case succeeded")
|
log.With(slog.String("testcase", name)).Info("Test case succeeded")
|
||||||
testOutput.TestCases[name] = testCaseOutput{
|
testOutput.TestCases[name] = testCaseOutput{
|
||||||
Passed: true,
|
Passed: true,
|
||||||
Message: "No error, as expected",
|
Message: "No error, as expected",
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
log.With(zap.String("testcase", name)).Fatalf("invalid result")
|
log.With(slog.String("testcase", name)).Error("invalid result")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testOutput.AllPassed = allPassed
|
testOutput.AllPassed = allPassed
|
||||||
log.With(zap.Any("result", testOutput)).Infof("Test completed")
|
log.With(slog.Any("result", testOutput)).Info("Test completed")
|
||||||
}
|
}
|
||||||
|
|
||||||
type testOutput struct {
|
type testOutput struct {
|
||||||
|
@ -110,7 +110,7 @@ type testCaseOutput struct {
|
||||||
|
|
||||||
// JoinFromUnattestedNode simulates a join request from a Node that uses a stub issuer
|
// JoinFromUnattestedNode simulates a join request from a Node that uses a stub issuer
|
||||||
// and thus cannot be attested correctly.
|
// and thus cannot be attested correctly.
|
||||||
func JoinFromUnattestedNode(attVariant, csp, jsEndpoint string, log *logger.Logger) error {
|
func JoinFromUnattestedNode(attVariant, csp, jsEndpoint string, log *slog.Logger) error {
|
||||||
joiner, err := newMaliciousJoiner(attVariant, csp, jsEndpoint, log)
|
joiner, err := newMaliciousJoiner(attVariant, csp, jsEndpoint, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating malicious joiner: %w", err)
|
return fmt.Errorf("creating malicious joiner: %w", err)
|
||||||
|
@ -125,7 +125,7 @@ func JoinFromUnattestedNode(attVariant, csp, jsEndpoint string, log *logger.Logg
|
||||||
|
|
||||||
// newMaliciousJoiner creates a new malicious joiner, i.e. a simulated node that issues
|
// newMaliciousJoiner creates a new malicious joiner, i.e. a simulated node that issues
|
||||||
// an invalid join request.
|
// an invalid join request.
|
||||||
func newMaliciousJoiner(attVariant, csp, endpoint string, log *logger.Logger) (*maliciousJoiner, error) {
|
func newMaliciousJoiner(attVariant, csp, endpoint string, log *slog.Logger) (*maliciousJoiner, error) {
|
||||||
var attVariantOid variant.Variant
|
var attVariantOid variant.Variant
|
||||||
var err error
|
var err error
|
||||||
if strings.EqualFold(attVariant, "default") {
|
if strings.EqualFold(attVariant, "default") {
|
||||||
|
@ -149,30 +149,30 @@ func newMaliciousJoiner(attVariant, csp, endpoint string, log *logger.Logger) (*
|
||||||
// maliciousJoiner simulates a malicious node joining a cluster.
|
// maliciousJoiner simulates a malicious node joining a cluster.
|
||||||
type maliciousJoiner struct {
|
type maliciousJoiner struct {
|
||||||
endpoint string
|
endpoint string
|
||||||
logger *logger.Logger
|
logger *slog.Logger
|
||||||
dialer *dialer.Dialer
|
dialer *dialer.Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
// join issues a join request to the join service endpoint.
|
// join issues a join request to the join service endpoint.
|
||||||
func (j *maliciousJoiner) join(ctx context.Context) (*joinproto.IssueJoinTicketResponse, error) {
|
func (j *maliciousJoiner) join(ctx context.Context) (*joinproto.IssueJoinTicketResponse, error) {
|
||||||
j.logger.Debugf("Dialing join service endpoint %s", j.endpoint)
|
j.logger.Debug(fmt.Sprintf("Dialing join service endpoint %s", j.endpoint))
|
||||||
conn, err := j.dialer.Dial(ctx, j.endpoint)
|
conn, err := j.dialer.Dial(ctx, j.endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("dialing join service endpoint: %w", err)
|
return nil, fmt.Errorf("dialing join service endpoint: %w", err)
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
j.logger.Debugf("Successfully dialed join service endpoint %s", j.endpoint)
|
j.logger.Debug(fmt.Sprintf("Successfully dialed join service endpoint %s", j.endpoint))
|
||||||
|
|
||||||
protoClient := joinproto.NewAPIClient(conn)
|
protoClient := joinproto.NewAPIClient(conn)
|
||||||
|
|
||||||
j.logger.Debugf("Issuing join ticket")
|
j.logger.Debug("Issuing join ticket")
|
||||||
req := &joinproto.IssueJoinTicketRequest{
|
req := &joinproto.IssueJoinTicketRequest{
|
||||||
DiskUuid: "",
|
DiskUuid: "",
|
||||||
CertificateRequest: []byte{},
|
CertificateRequest: []byte{},
|
||||||
IsControlPlane: false,
|
IsControlPlane: false,
|
||||||
}
|
}
|
||||||
res, err := protoClient.IssueJoinTicket(ctx, req)
|
res, err := protoClient.IssueJoinTicket(ctx, req)
|
||||||
j.logger.Debugf("Got join ticket response: %+v", res)
|
j.logger.Debug(fmt.Sprintf("Got join ticket response: %+v", res))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("issuing join ticket: %w", err)
|
return nil, fmt.Errorf("issuing join ticket: %w", err)
|
||||||
}
|
}
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -126,7 +126,6 @@ require (
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.10
|
go.etcd.io/etcd/client/pkg/v3 v3.5.10
|
||||||
go.etcd.io/etcd/client/v3 v3.5.10
|
go.etcd.io/etcd/client/v3 v3.5.10
|
||||||
go.uber.org/goleak v1.3.0
|
go.uber.org/goleak v1.3.0
|
||||||
go.uber.org/zap v1.26.0
|
|
||||||
golang.org/x/crypto v0.17.0
|
golang.org/x/crypto v0.17.0
|
||||||
golang.org/x/exp v0.0.0-20231219180239-dc181d75b848
|
golang.org/x/exp v0.0.0-20231219180239-dc181d75b848
|
||||||
golang.org/x/mod v0.14.0
|
golang.org/x/mod v0.14.0
|
||||||
|
@ -153,6 +152,8 @@ require (
|
||||||
sigs.k8s.io/yaml v1.4.0
|
sigs.k8s.io/yaml v1.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require go.uber.org/zap v1.26.0 // indirect
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.110.8 // indirect
|
cloud.google.com/go v0.110.8 // indirect
|
||||||
cloud.google.com/go/iam v1.1.2 // indirect
|
cloud.google.com/go/iam v1.1.2 // indirect
|
||||||
|
|
|
@ -18,7 +18,6 @@ go_library(
|
||||||
"//internal/logger",
|
"//internal/logger",
|
||||||
"@com_github_bazelbuild_buildtools//build",
|
"@com_github_bazelbuild_buildtools//build",
|
||||||
"@com_github_spf13_cobra//:cobra",
|
"@com_github_spf13_cobra//:cobra",
|
||||||
"@org_uber_go_zap//zapcore",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/bazelfiles"
|
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/bazelfiles"
|
||||||
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/issues"
|
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/issues"
|
||||||
|
@ -16,7 +18,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/rules"
|
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/rules"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newCheckCmd() *cobra.Command {
|
func newCheckCmd() *cobra.Command {
|
||||||
|
@ -38,15 +39,15 @@ func runCheck(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
|
|
||||||
filesHelper, err := bazelfiles.New()
|
filesHelper, err := bazelfiles.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Searching for Bazel files in the current WORKSPACE and all subdirectories...")
|
log.Debug("Searching for Bazel files in the current WORKSPACE and all subdirectories...")
|
||||||
bazelFiles, err := filesHelper.FindFiles()
|
bazelFiles, err := filesHelper.FindFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -55,10 +56,10 @@ func runCheck(cmd *cobra.Command, _ []string) error {
|
||||||
var mirrorCheck mirrorChecker
|
var mirrorCheck mirrorChecker
|
||||||
switch {
|
switch {
|
||||||
case flags.mirrorUnauthenticated:
|
case flags.mirrorUnauthenticated:
|
||||||
log.Debugf("Checking consistency of all referenced CAS objects without authentication.")
|
log.Debug("Checking consistency of all referenced CAS objects without authentication.")
|
||||||
mirrorCheck = mirror.NewUnauthenticated(flags.mirrorBaseURL, mirror.Run, log)
|
mirrorCheck = mirror.NewUnauthenticated(flags.mirrorBaseURL, mirror.Run, log)
|
||||||
case flags.mirror:
|
case flags.mirror:
|
||||||
log.Debugf("Checking consistency of all referenced CAS objects using AWS S3.")
|
log.Debug("Checking consistency of all referenced CAS objects using AWS S3.")
|
||||||
mirrorCheck, err = mirror.New(cmd.Context(), flags.region, flags.bucket, flags.mirrorBaseURL, mirror.Run, log)
|
mirrorCheck, err = mirror.New(cmd.Context(), flags.region, flags.bucket, flags.mirrorBaseURL, mirror.Run, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -78,17 +79,17 @@ func runCheck(cmd *cobra.Command, _ []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(iss) > 0 {
|
if len(iss) > 0 {
|
||||||
log.Infof("Found issues in rules")
|
log.Info("Found issues in rules")
|
||||||
iss.Report(cmd.OutOrStdout())
|
iss.Report(cmd.OutOrStdout())
|
||||||
return errors.New("found issues in rules")
|
return errors.New("found issues in rules")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("No issues found 🦭")
|
log.Info("No issues found 🦭")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirrorCheck mirrorChecker, bazelFile bazelfiles.BazelFile, log *logger.Logger) (issByFile issues.ByFile, err error) {
|
func checkBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirrorCheck mirrorChecker, bazelFile bazelfiles.BazelFile, log *slog.Logger) (issByFile issues.ByFile, err error) {
|
||||||
log.Debugf("Checking file: %s", bazelFile.RelPath)
|
log.Debug(fmt.Sprintf("Checking file: %s", bazelFile.RelPath))
|
||||||
issByFile = issues.NewByFile()
|
issByFile = issues.NewByFile()
|
||||||
buildfile, err := fileHelper.LoadFile(bazelFile)
|
buildfile, err := fileHelper.LoadFile(bazelFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -96,12 +97,12 @@ func checkBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirrorCh
|
||||||
}
|
}
|
||||||
found := rules.Rules(buildfile, rules.SupportedRules)
|
found := rules.Rules(buildfile, rules.SupportedRules)
|
||||||
if len(found) == 0 {
|
if len(found) == 0 {
|
||||||
log.Debugf("No rules found in file: %s", bazelFile.RelPath)
|
log.Debug(fmt.Sprintf("No rules found in file: %s", bazelFile.RelPath))
|
||||||
return issByFile, nil
|
return issByFile, nil
|
||||||
}
|
}
|
||||||
log.Debugf("Found %d rules in file: %s", len(found), bazelFile.RelPath)
|
log.Debug(fmt.Sprintf("Found %d rules in file: %s", len(found), bazelFile.RelPath))
|
||||||
for _, rule := range found {
|
for _, rule := range found {
|
||||||
log.Debugf("Checking rule: %s", rule.Name())
|
log.Debug(fmt.Sprintf("Checking rule: %s", rule.Name()))
|
||||||
// check if the rule is a valid pinned dependency rule (has all required attributes)
|
// check if the rule is a valid pinned dependency rule (has all required attributes)
|
||||||
if issues := rules.ValidatePinned(rule); len(issues) > 0 {
|
if issues := rules.ValidatePinned(rule); len(issues) > 0 {
|
||||||
issByFile.Add(rule.Name(), issues...)
|
issByFile.Add(rule.Name(), issues...)
|
||||||
|
@ -130,7 +131,7 @@ type checkFlags struct {
|
||||||
region string
|
region string
|
||||||
bucket string
|
bucket string
|
||||||
mirrorBaseURL string
|
mirrorBaseURL string
|
||||||
logLevel zapcore.Level
|
logLevel slog.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCheckFlags(cmd *cobra.Command) (checkFlags, error) {
|
func parseCheckFlags(cmd *cobra.Command) (checkFlags, error) {
|
||||||
|
@ -146,9 +147,9 @@ func parseCheckFlags(cmd *cobra.Command) (checkFlags, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return checkFlags{}, err
|
return checkFlags{}, err
|
||||||
}
|
}
|
||||||
logLevel := zapcore.InfoLevel
|
logLevel := slog.LevelInfo
|
||||||
if verbose {
|
if verbose {
|
||||||
logLevel = zapcore.DebugLevel
|
logLevel = slog.LevelDebug
|
||||||
}
|
}
|
||||||
region, err := cmd.Flags().GetString("region")
|
region, err := cmd.Flags().GetString("region")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -9,6 +9,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
"github.com/bazelbuild/buildtools/build"
|
"github.com/bazelbuild/buildtools/build"
|
||||||
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/bazelfiles"
|
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/bazelfiles"
|
||||||
|
@ -17,7 +19,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/rules"
|
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/rules"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newFixCmd() *cobra.Command {
|
func newFixCmd() *cobra.Command {
|
||||||
|
@ -38,15 +39,15 @@ func runFix(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
|
|
||||||
fileHelper, err := bazelfiles.New()
|
fileHelper, err := bazelfiles.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Searching for Bazel files in the current WORKSPACE and all subdirectories...")
|
log.Debug("Searching for Bazel files in the current WORKSPACE and all subdirectories...")
|
||||||
bazelFiles, err := fileHelper.FindFiles()
|
bazelFiles, err := fileHelper.FindFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -55,10 +56,10 @@ func runFix(cmd *cobra.Command, _ []string) error {
|
||||||
var mirrorUpload mirrorUploader
|
var mirrorUpload mirrorUploader
|
||||||
switch {
|
switch {
|
||||||
case flags.unauthenticated:
|
case flags.unauthenticated:
|
||||||
log.Warnf("Fixing rules without authentication for AWS S3. If artifacts are not yet mirrored, this will fail.")
|
log.Warn("Fixing rules without authentication for AWS S3. If artifacts are not yet mirrored, this will fail.")
|
||||||
mirrorUpload = mirror.NewUnauthenticated(flags.mirrorBaseURL, flags.dryRun, log)
|
mirrorUpload = mirror.NewUnauthenticated(flags.mirrorBaseURL, flags.dryRun, log)
|
||||||
default:
|
default:
|
||||||
log.Debugf("Fixing rules with authentication for AWS S3.")
|
log.Debug("Fixing rules with authentication for AWS S3.")
|
||||||
mirrorUpload, err = mirror.New(cmd.Context(), flags.region, flags.bucket, flags.mirrorBaseURL, flags.dryRun, log)
|
mirrorUpload, err = mirror.New(cmd.Context(), flags.region, flags.bucket, flags.mirrorBaseURL, flags.dryRun, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -76,29 +77,29 @@ func runFix(cmd *cobra.Command, _ []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(issues) > 0 {
|
if len(issues) > 0 {
|
||||||
log.Warnf("Found %d unfixable issues in rules", len(issues))
|
log.Warn(fmt.Sprintf("Found %d unfixable issues in rules", len(issues)))
|
||||||
issues.Report(cmd.OutOrStdout())
|
issues.Report(cmd.OutOrStdout())
|
||||||
return errors.New("found issues in rules")
|
return errors.New("found issues in rules")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("No unfixable issues found")
|
log.Info("No unfixable issues found")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fixBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirrorUpload mirrorUploader, bazelFile bazelfiles.BazelFile, dryRun bool, log *logger.Logger) (iss issues.ByFile, err error) {
|
func fixBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirrorUpload mirrorUploader, bazelFile bazelfiles.BazelFile, dryRun bool, log *slog.Logger) (iss issues.ByFile, err error) {
|
||||||
iss = issues.NewByFile()
|
iss = issues.NewByFile()
|
||||||
var changed bool // true if any rule in this file was changed
|
var changed bool // true if any rule in this file was changed
|
||||||
log.Infof("Checking file: %s", bazelFile.RelPath)
|
log.Info(fmt.Sprintf("Checking file: %s", bazelFile.RelPath))
|
||||||
buildfile, err := fileHelper.LoadFile(bazelFile)
|
buildfile, err := fileHelper.LoadFile(bazelFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return iss, err
|
return iss, err
|
||||||
}
|
}
|
||||||
found := rules.Rules(buildfile, rules.SupportedRules)
|
found := rules.Rules(buildfile, rules.SupportedRules)
|
||||||
if len(found) == 0 {
|
if len(found) == 0 {
|
||||||
log.Debugf("No rules found in file: %s", bazelFile.RelPath)
|
log.Debug(fmt.Sprintf("No rules found in file: %s", bazelFile.RelPath))
|
||||||
return iss, nil
|
return iss, nil
|
||||||
}
|
}
|
||||||
log.Debugf("Found %d rules in file: %s", len(found), bazelFile.RelPath)
|
log.Debug(fmt.Sprintf("Found %d rules in file: %s", len(found), bazelFile.RelPath))
|
||||||
for _, rule := range found {
|
for _, rule := range found {
|
||||||
changedRule, ruleIssues := fixRule(ctx, mirrorUpload, rule, log)
|
changedRule, ruleIssues := fixRule(ctx, mirrorUpload, rule, log)
|
||||||
if len(ruleIssues) > 0 {
|
if len(ruleIssues) > 0 {
|
||||||
|
@ -108,11 +109,11 @@ func fixBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirrorUplo
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(iss) > 0 {
|
if len(iss) > 0 {
|
||||||
log.Warnf("File %s has issues. Not saving!", bazelFile.RelPath)
|
log.Warn(fmt.Sprintf("File %s has issues. Not saving!", bazelFile.RelPath))
|
||||||
return iss, nil
|
return iss, nil
|
||||||
}
|
}
|
||||||
if !changed {
|
if !changed {
|
||||||
log.Debugf("No changes to file: %s", bazelFile.RelPath)
|
log.Debug(fmt.Sprintf("No changes to file: %s", bazelFile.RelPath))
|
||||||
return iss, nil
|
return iss, nil
|
||||||
}
|
}
|
||||||
if dryRun {
|
if dryRun {
|
||||||
|
@ -120,10 +121,10 @@ func fixBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirrorUplo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return iss, err
|
return iss, err
|
||||||
}
|
}
|
||||||
log.Infof("Dry run: would save updated file %s with diff:\n%s", bazelFile.RelPath, diff)
|
log.Info(fmt.Sprintf("Dry run: would save updated file %s with diff:\n%s", bazelFile.RelPath, diff))
|
||||||
return iss, nil
|
return iss, nil
|
||||||
}
|
}
|
||||||
log.Infof("Saving updated file: %s", bazelFile.RelPath)
|
log.Info(fmt.Sprintf("Saving updated file: %s", bazelFile.RelPath))
|
||||||
if err := fileHelper.WriteFile(bazelFile, buildfile); err != nil {
|
if err := fileHelper.WriteFile(bazelFile, buildfile); err != nil {
|
||||||
return iss, err
|
return iss, err
|
||||||
}
|
}
|
||||||
|
@ -131,7 +132,7 @@ func fixBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirrorUplo
|
||||||
return iss, nil
|
return iss, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func learnHashForRule(ctx context.Context, mirrorUpload mirrorUploader, rule *build.Rule, log *logger.Logger) error {
|
func learnHashForRule(ctx context.Context, mirrorUpload mirrorUploader, rule *build.Rule, log *slog.Logger) error {
|
||||||
upstreamURLs, err := rules.UpstreamURLs(rule)
|
upstreamURLs, err := rules.UpstreamURLs(rule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -141,12 +142,12 @@ func learnHashForRule(ctx context.Context, mirrorUpload mirrorUploader, rule *bu
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rules.SetHash(rule, learnedHash)
|
rules.SetHash(rule, learnedHash)
|
||||||
log.Debugf("Learned hash for rule %s: %s", rule.Name(), learnedHash)
|
log.Debug(fmt.Sprintf("Learned hash for rule %s: %s", rule.Name(), learnedHash))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fixRule(ctx context.Context, mirrorUpload mirrorUploader, rule *build.Rule, log *logger.Logger) (changed bool, iss []error) {
|
func fixRule(ctx context.Context, mirrorUpload mirrorUploader, rule *build.Rule, log *slog.Logger) (changed bool, iss []error) {
|
||||||
log.Debugf("Fixing rule: %s", rule.Name())
|
log.Debug(fmt.Sprintf("Fixing rule: %s", rule.Name()))
|
||||||
|
|
||||||
// try to learn the hash
|
// try to learn the hash
|
||||||
if hash, err := rules.GetHash(rule); err != nil || hash == "" {
|
if hash, err := rules.GetHash(rule); err != nil || hash == "" {
|
||||||
|
@ -182,14 +183,14 @@ func fixRule(ctx context.Context, mirrorUpload mirrorUploader, rule *build.Rule,
|
||||||
}
|
}
|
||||||
|
|
||||||
if checkErr := mirrorUpload.Check(ctx, expectedHash); checkErr != nil {
|
if checkErr := mirrorUpload.Check(ctx, expectedHash); checkErr != nil {
|
||||||
log.Infof("Artifact %s with hash %s is not yet mirrored. Uploading...", rule.Name(), expectedHash)
|
log.Info(fmt.Sprintf("Artifact %s with hash %s is not yet mirrored. Uploading...", rule.Name(), expectedHash))
|
||||||
if uploadErr := mirrorUpload.Mirror(ctx, expectedHash, rules.GetURLs(rule)); uploadErr != nil {
|
if uploadErr := mirrorUpload.Mirror(ctx, expectedHash, rules.GetURLs(rule)); uploadErr != nil {
|
||||||
// don't try to fix the rule if the upload failed
|
// don't try to fix the rule if the upload failed
|
||||||
iss = append(iss, uploadErr)
|
iss = append(iss, uploadErr)
|
||||||
return changed, iss
|
return changed, iss
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Infof("Artifact %s with hash %s was already uploaded before. Adding to rule...", rule.Name(), expectedHash)
|
log.Info(fmt.Sprintf("Artifact %s with hash %s was already uploaded before. Adding to rule...", rule.Name(), expectedHash))
|
||||||
}
|
}
|
||||||
|
|
||||||
// now the artifact is mirrored (if it wasn't already) and we can fix the rule
|
// now the artifact is mirrored (if it wasn't already) and we can fix the rule
|
||||||
|
@ -211,7 +212,7 @@ type fixFlags struct {
|
||||||
region string
|
region string
|
||||||
bucket string
|
bucket string
|
||||||
mirrorBaseURL string
|
mirrorBaseURL string
|
||||||
logLevel zapcore.Level
|
logLevel slog.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFixFlags(cmd *cobra.Command) (fixFlags, error) {
|
func parseFixFlags(cmd *cobra.Command) (fixFlags, error) {
|
||||||
|
@ -227,9 +228,9 @@ func parseFixFlags(cmd *cobra.Command) (fixFlags, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fixFlags{}, err
|
return fixFlags{}, err
|
||||||
}
|
}
|
||||||
logLevel := zapcore.InfoLevel
|
logLevel := slog.LevelInfo
|
||||||
if verbose {
|
if verbose {
|
||||||
logLevel = zapcore.DebugLevel
|
logLevel = slog.LevelDebug
|
||||||
}
|
}
|
||||||
region, err := cmd.Flags().GetString("region")
|
region, err := cmd.Flags().GetString("region")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -7,7 +7,6 @@ go_library(
|
||||||
importpath = "github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/mirror",
|
importpath = "github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/mirror",
|
||||||
visibility = ["//hack/bazel-deps-mirror:__subpackages__"],
|
visibility = ["//hack/bazel-deps-mirror:__subpackages__"],
|
||||||
deps = [
|
deps = [
|
||||||
"//internal/logger",
|
|
||||||
"@com_github_aws_aws_sdk_go_v2_config//:config",
|
"@com_github_aws_aws_sdk_go_v2_config//:config",
|
||||||
"@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager",
|
"@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager",
|
||||||
"@com_github_aws_aws_sdk_go_v2_service_s3//:s3",
|
"@com_github_aws_aws_sdk_go_v2_service_s3//:s3",
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
@ -23,7 +24,6 @@ import (
|
||||||
s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
|
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Maintainer can upload and download files to and from a CAS mirror.
|
// Maintainer can upload and download files to and from a CAS mirror.
|
||||||
|
@ -39,11 +39,11 @@ type Maintainer struct {
|
||||||
unauthenticated bool
|
unauthenticated bool
|
||||||
dryRun bool
|
dryRun bool
|
||||||
|
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUnauthenticated creates a new Maintainer that dose not require authentication can only download files from a CAS mirror.
|
// NewUnauthenticated creates a new Maintainer that dose not require authentication can only download files from a CAS mirror.
|
||||||
func NewUnauthenticated(mirrorBaseURL string, dryRun bool, log *logger.Logger) *Maintainer {
|
func NewUnauthenticated(mirrorBaseURL string, dryRun bool, log *slog.Logger) *Maintainer {
|
||||||
return &Maintainer{
|
return &Maintainer{
|
||||||
httpClient: http.DefaultClient,
|
httpClient: http.DefaultClient,
|
||||||
mirrorBaseURL: mirrorBaseURL,
|
mirrorBaseURL: mirrorBaseURL,
|
||||||
|
@ -54,7 +54,7 @@ func NewUnauthenticated(mirrorBaseURL string, dryRun bool, log *logger.Logger) *
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Maintainer that can upload and download files to and from a CAS mirror.
|
// New creates a new Maintainer that can upload and download files to and from a CAS mirror.
|
||||||
func New(ctx context.Context, region, bucket, mirrorBaseURL string, dryRun bool, log *logger.Logger) (*Maintainer, error) {
|
func New(ctx context.Context, region, bucket, mirrorBaseURL string, dryRun bool, log *slog.Logger) (*Maintainer, error) {
|
||||||
cfg, err := awsconfig.LoadDefaultConfig(ctx, awsconfig.WithRegion(region))
|
cfg, err := awsconfig.LoadDefaultConfig(ctx, awsconfig.WithRegion(region))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -95,17 +95,17 @@ func (m *Maintainer) Mirror(ctx context.Context, hash string, urls []string) err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, url := range urls {
|
for _, url := range urls {
|
||||||
m.log.Debugf("Mirroring file with hash %v from %q", hash, url)
|
m.log.Debug(fmt.Sprintf("Mirroring file with hash %v from %q", hash, url))
|
||||||
body, err := m.downloadFromUpstream(ctx, url)
|
body, err := m.downloadFromUpstream(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.log.Debugf("Failed to download file from %q: %v", url, err)
|
m.log.Debug(fmt.Sprintf("Failed to download file from %q: %v", url, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
defer body.Close()
|
defer body.Close()
|
||||||
streamedHash := sha256.New()
|
streamedHash := sha256.New()
|
||||||
tee := io.TeeReader(body, streamedHash)
|
tee := io.TeeReader(body, streamedHash)
|
||||||
if err := m.put(ctx, hash, tee); err != nil {
|
if err := m.put(ctx, hash, tee); err != nil {
|
||||||
m.log.Warnf("Failed to stream file from upstream %q to mirror: %v.. Trying next url.", url, err)
|
m.log.Warn(fmt.Sprintf("Failed to stream file from upstream %q to mirror: %v.. Trying next url.", url, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
actualHash := hex.EncodeToString(streamedHash.Sum(nil))
|
actualHash := hex.EncodeToString(streamedHash.Sum(nil))
|
||||||
|
@ -117,7 +117,7 @@ func (m *Maintainer) Mirror(ctx context.Context, hash string, urls []string) err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.log.Debugf("File uploaded successfully to mirror from %q as %q", url, pubURL)
|
m.log.Debug(fmt.Sprintf("File uploaded successfully to mirror from %q as %q", url, pubURL))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("failed to download / reupload file with hash %v from any of the urls: %v", hash, urls)
|
return fmt.Errorf("failed to download / reupload file with hash %v from any of the urls: %v", hash, urls)
|
||||||
|
@ -126,19 +126,19 @@ func (m *Maintainer) Mirror(ctx context.Context, hash string, urls []string) err
|
||||||
// Learn downloads a file from one of the existing (non-mirror) urls, hashes it and returns the hash.
|
// Learn downloads a file from one of the existing (non-mirror) urls, hashes it and returns the hash.
|
||||||
func (m *Maintainer) Learn(ctx context.Context, urls []string) (string, error) {
|
func (m *Maintainer) Learn(ctx context.Context, urls []string) (string, error) {
|
||||||
for _, url := range urls {
|
for _, url := range urls {
|
||||||
m.log.Debugf("Learning new hash from %q", url)
|
m.log.Debug(fmt.Sprintf("Learning new hash from %q", url))
|
||||||
body, err := m.downloadFromUpstream(ctx, url)
|
body, err := m.downloadFromUpstream(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.log.Debugf("Failed to download file from %q: %v", url, err)
|
m.log.Debug(fmt.Sprintf("Failed to download file from %q: %v", url, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
defer body.Close()
|
defer body.Close()
|
||||||
streamedHash := sha256.New()
|
streamedHash := sha256.New()
|
||||||
if _, err := io.Copy(streamedHash, body); err != nil {
|
if _, err := io.Copy(streamedHash, body); err != nil {
|
||||||
m.log.Debugf("Failed to stream file from %q: %v", url, err)
|
m.log.Debug(fmt.Sprintf("Failed to stream file from %q: %v", url, err))
|
||||||
}
|
}
|
||||||
learnedHash := hex.EncodeToString(streamedHash.Sum(nil))
|
learnedHash := hex.EncodeToString(streamedHash.Sum(nil))
|
||||||
m.log.Debugf("File successfully downloaded from %q with %q", url, learnedHash)
|
m.log.Debug(fmt.Sprintf("File successfully downloaded from %q with %q", url, learnedHash))
|
||||||
return learnedHash, nil
|
return learnedHash, nil
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("failed to download file / learn hash from any of the urls: %v", urls)
|
return "", fmt.Errorf("failed to download file / learn hash from any of the urls: %v", urls)
|
||||||
|
@ -146,7 +146,7 @@ func (m *Maintainer) Learn(ctx context.Context, urls []string) (string, error) {
|
||||||
|
|
||||||
// Check checks if a file is present and has the correct hash in the CAS mirror.
|
// Check checks if a file is present and has the correct hash in the CAS mirror.
|
||||||
func (m *Maintainer) Check(ctx context.Context, expectedHash string) error {
|
func (m *Maintainer) Check(ctx context.Context, expectedHash string) error {
|
||||||
m.log.Debugf("Checking consistency of object with hash %v", expectedHash)
|
m.log.Debug(fmt.Sprintf("Checking consistency of object with hash %v", expectedHash))
|
||||||
if m.unauthenticated {
|
if m.unauthenticated {
|
||||||
return m.checkUnauthenticated(ctx, expectedHash)
|
return m.checkUnauthenticated(ctx, expectedHash)
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ func (m *Maintainer) Check(ctx context.Context, expectedHash string) error {
|
||||||
// It uses the authenticated CAS s3 endpoint to download the file metadata.
|
// It uses the authenticated CAS s3 endpoint to download the file metadata.
|
||||||
func (m *Maintainer) checkAuthenticated(ctx context.Context, expectedHash string) error {
|
func (m *Maintainer) checkAuthenticated(ctx context.Context, expectedHash string) error {
|
||||||
key := path.Join(keyBase, expectedHash)
|
key := path.Join(keyBase, expectedHash)
|
||||||
m.log.Debugf("Check: s3 getObjectAttributes {Bucket: %v, Key: %v}", m.bucket, key)
|
m.log.Debug(fmt.Sprintf("Check: s3 getObjectAttributes {Bucket: %v, Key: %v}", m.bucket, key))
|
||||||
attributes, err := m.objectStorageClient.GetObjectAttributes(ctx, &s3.GetObjectAttributesInput{
|
attributes, err := m.objectStorageClient.GetObjectAttributes(ctx, &s3.GetObjectAttributesInput{
|
||||||
Bucket: &m.bucket,
|
Bucket: &m.bucket,
|
||||||
Key: &key,
|
Key: &key,
|
||||||
|
@ -174,7 +174,7 @@ func (m *Maintainer) checkAuthenticated(ctx context.Context, expectedHash string
|
||||||
// checksums are not guaranteed to be present
|
// checksums are not guaranteed to be present
|
||||||
// and if present, they are only meaningful for single part objects
|
// and if present, they are only meaningful for single part objects
|
||||||
// fallback if checksum cannot be verified from attributes
|
// fallback if checksum cannot be verified from attributes
|
||||||
m.log.Debugf("S3 object attributes cannot be used to verify key %v. Falling back to download.", key)
|
m.log.Debug(fmt.Sprintf("S3 object attributes cannot be used to verify key %v. Falling back to download.", key))
|
||||||
return m.checkUnauthenticated(ctx, expectedHash)
|
return m.checkUnauthenticated(ctx, expectedHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ func (m *Maintainer) checkUnauthenticated(ctx context.Context, expectedHash stri
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.log.Debugf("Check: http get {Url: %v}", pubURL)
|
m.log.Debug(fmt.Sprintf("Check: http get {Url: %v}", pubURL))
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, pubURL, http.NoBody)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, pubURL, http.NoBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -221,10 +221,10 @@ func (m *Maintainer) put(ctx context.Context, hash string, data io.Reader) error
|
||||||
|
|
||||||
key := path.Join(keyBase, hash)
|
key := path.Join(keyBase, hash)
|
||||||
if m.dryRun {
|
if m.dryRun {
|
||||||
m.log.Debugf("DryRun: s3 put object {Bucket: %v, Key: %v}", m.bucket, key)
|
m.log.Debug(fmt.Sprintf("DryRun: s3 put object {Bucket: %v, Key: %v}", m.bucket, key))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
m.log.Debugf("Uploading object with hash %v to s3://%v/%v", hash, m.bucket, key)
|
m.log.Debug(fmt.Sprintf("Uploading object with hash %v to s3://%v/%v", hash, m.bucket, key))
|
||||||
_, err := m.uploadClient.Upload(ctx, &s3.PutObjectInput{
|
_, err := m.uploadClient.Upload(ctx, &s3.PutObjectInput{
|
||||||
Bucket: &m.bucket,
|
Bucket: &m.bucket,
|
||||||
Key: &key,
|
Key: &key,
|
||||||
|
|
|
@ -9,6 +9,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
"github.com/bazelbuild/buildtools/build"
|
"github.com/bazelbuild/buildtools/build"
|
||||||
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/bazelfiles"
|
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/bazelfiles"
|
||||||
|
@ -17,7 +19,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/rules"
|
"github.com/edgelesssys/constellation/v2/hack/bazel-deps-mirror/internal/rules"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newUpgradeCmd() *cobra.Command {
|
func newUpgradeCmd() *cobra.Command {
|
||||||
|
@ -38,15 +39,15 @@ func runUpgrade(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
|
|
||||||
fileHelper, err := bazelfiles.New()
|
fileHelper, err := bazelfiles.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Searching for Bazel files in the current WORKSPACE and all subdirectories...")
|
log.Debug("Searching for Bazel files in the current WORKSPACE and all subdirectories...")
|
||||||
bazelFiles, err := fileHelper.FindFiles()
|
bazelFiles, err := fileHelper.FindFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -55,10 +56,10 @@ func runUpgrade(cmd *cobra.Command, _ []string) error {
|
||||||
var mirrorUpload mirrorUploader
|
var mirrorUpload mirrorUploader
|
||||||
switch {
|
switch {
|
||||||
case flags.unauthenticated:
|
case flags.unauthenticated:
|
||||||
log.Warnf("Upgrading rules without authentication for AWS S3. If artifacts are not yet mirrored, this will fail.")
|
log.Warn("Upgrading rules without authentication for AWS S3. If artifacts are not yet mirrored, this will fail.")
|
||||||
mirrorUpload = mirror.NewUnauthenticated(flags.mirrorBaseURL, flags.dryRun, log)
|
mirrorUpload = mirror.NewUnauthenticated(flags.mirrorBaseURL, flags.dryRun, log)
|
||||||
default:
|
default:
|
||||||
log.Debugf("Upgrading rules with authentication for AWS S3.")
|
log.Debug("Upgrading rules with authentication for AWS S3.")
|
||||||
mirrorUpload, err = mirror.New(cmd.Context(), flags.region, flags.bucket, flags.mirrorBaseURL, flags.dryRun, log)
|
mirrorUpload, err = mirror.New(cmd.Context(), flags.region, flags.bucket, flags.mirrorBaseURL, flags.dryRun, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -76,29 +77,29 @@ func runUpgrade(cmd *cobra.Command, _ []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(issues) > 0 {
|
if len(issues) > 0 {
|
||||||
log.Warnf("Found %d issues in rules", len(issues))
|
log.Warn(fmt.Sprintf("Found %d issues in rules", len(issues)))
|
||||||
issues.Report(cmd.OutOrStdout())
|
issues.Report(cmd.OutOrStdout())
|
||||||
return errors.New("found issues in rules")
|
return errors.New("found issues in rules")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("No issues found")
|
log.Info("No issues found")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func upgradeBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirrorUpload mirrorUploader, bazelFile bazelfiles.BazelFile, dryRun bool, log *logger.Logger) (iss issues.ByFile, err error) {
|
func upgradeBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirrorUpload mirrorUploader, bazelFile bazelfiles.BazelFile, dryRun bool, log *slog.Logger) (iss issues.ByFile, err error) {
|
||||||
iss = issues.NewByFile()
|
iss = issues.NewByFile()
|
||||||
var changed bool // true if any rule in this file was changed
|
var changed bool // true if any rule in this file was changed
|
||||||
log.Infof("Checking file: %s", bazelFile.RelPath)
|
log.Info(fmt.Sprintf("Checking file: %s", bazelFile.RelPath))
|
||||||
buildfile, err := fileHelper.LoadFile(bazelFile)
|
buildfile, err := fileHelper.LoadFile(bazelFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return iss, err
|
return iss, err
|
||||||
}
|
}
|
||||||
found := rules.Rules(buildfile, rules.SupportedRules)
|
found := rules.Rules(buildfile, rules.SupportedRules)
|
||||||
if len(found) == 0 {
|
if len(found) == 0 {
|
||||||
log.Debugf("No rules found in file: %s", bazelFile.RelPath)
|
log.Debug(fmt.Sprintf("No rules found in file: %s", bazelFile.RelPath))
|
||||||
return iss, nil
|
return iss, nil
|
||||||
}
|
}
|
||||||
log.Debugf("Found %d rules in file: %s", len(found), bazelFile.RelPath)
|
log.Debug(fmt.Sprintf("Found %d rules in file: %s", len(found), bazelFile.RelPath))
|
||||||
for _, rule := range found {
|
for _, rule := range found {
|
||||||
changedRule, ruleIssues := upgradeRule(ctx, mirrorUpload, rule, log)
|
changedRule, ruleIssues := upgradeRule(ctx, mirrorUpload, rule, log)
|
||||||
if len(ruleIssues) > 0 {
|
if len(ruleIssues) > 0 {
|
||||||
|
@ -108,11 +109,11 @@ func upgradeBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirror
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(iss) > 0 {
|
if len(iss) > 0 {
|
||||||
log.Warnf("File %s has issues. Not saving!", bazelFile.RelPath)
|
log.Warn(fmt.Sprintf("File %s has issues. Not saving!", bazelFile.RelPath))
|
||||||
return iss, nil
|
return iss, nil
|
||||||
}
|
}
|
||||||
if !changed {
|
if !changed {
|
||||||
log.Debugf("No changes to file: %s", bazelFile.RelPath)
|
log.Debug(fmt.Sprintf("No changes to file: %s", bazelFile.RelPath))
|
||||||
return iss, nil
|
return iss, nil
|
||||||
}
|
}
|
||||||
if dryRun {
|
if dryRun {
|
||||||
|
@ -120,10 +121,10 @@ func upgradeBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirror
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return iss, err
|
return iss, err
|
||||||
}
|
}
|
||||||
log.Infof("Dry run: would save updated file %s with diff:\n%s", bazelFile.RelPath, diff)
|
log.Info(fmt.Sprintf("Dry run: would save updated file %s with diff:\n%s", bazelFile.RelPath, diff))
|
||||||
return iss, nil
|
return iss, nil
|
||||||
}
|
}
|
||||||
log.Infof("Saving updated file: %s", bazelFile.RelPath)
|
log.Info(fmt.Sprintf("Saving updated file: %s", bazelFile.RelPath))
|
||||||
if err := fileHelper.WriteFile(bazelFile, buildfile); err != nil {
|
if err := fileHelper.WriteFile(bazelFile, buildfile); err != nil {
|
||||||
return iss, err
|
return iss, err
|
||||||
}
|
}
|
||||||
|
@ -131,12 +132,12 @@ func upgradeBazelFile(ctx context.Context, fileHelper *bazelfiles.Helper, mirror
|
||||||
return iss, nil
|
return iss, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func upgradeRule(ctx context.Context, mirrorUpload mirrorUploader, rule *build.Rule, log *logger.Logger) (changed bool, iss []error) {
|
func upgradeRule(ctx context.Context, mirrorUpload mirrorUploader, rule *build.Rule, log *slog.Logger) (changed bool, iss []error) {
|
||||||
log.Debugf("Upgrading rule: %s", rule.Name())
|
log.Debug(fmt.Sprintf("Upgrading rule: %s", rule.Name()))
|
||||||
|
|
||||||
upstreamURLs, err := rules.UpstreamURLs(rule)
|
upstreamURLs, err := rules.UpstreamURLs(rule)
|
||||||
if errors.Is(err, rules.ErrNoUpstreamURL) {
|
if errors.Is(err, rules.ErrNoUpstreamURL) {
|
||||||
log.Debugf("Rule has no upstream URL. Skipping.")
|
log.Debug("Rule has no upstream URL. Skipping.")
|
||||||
return false, nil
|
return false, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
iss = append(iss, err)
|
iss = append(iss, err)
|
||||||
|
@ -152,7 +153,7 @@ func upgradeRule(ctx context.Context, mirrorUpload mirrorUploader, rule *build.R
|
||||||
|
|
||||||
existingHash, err := rules.GetHash(rule)
|
existingHash, err := rules.GetHash(rule)
|
||||||
if err == nil && learnedHash == existingHash {
|
if err == nil && learnedHash == existingHash {
|
||||||
log.Debugf("Rule already upgraded. Skipping.")
|
log.Debug("Rule already upgraded. Skipping.")
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +178,7 @@ type upgradeFlags struct {
|
||||||
region string
|
region string
|
||||||
bucket string
|
bucket string
|
||||||
mirrorBaseURL string
|
mirrorBaseURL string
|
||||||
logLevel zapcore.Level
|
logLevel slog.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseUpgradeFlags(cmd *cobra.Command) (upgradeFlags, error) {
|
func parseUpgradeFlags(cmd *cobra.Command) (upgradeFlags, error) {
|
||||||
|
@ -193,9 +194,9 @@ func parseUpgradeFlags(cmd *cobra.Command) (upgradeFlags, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return upgradeFlags{}, err
|
return upgradeFlags{}, err
|
||||||
}
|
}
|
||||||
logLevel := zapcore.InfoLevel
|
logLevel := slog.LevelInfo
|
||||||
if verbose {
|
if verbose {
|
||||||
logLevel = zapcore.DebugLevel
|
logLevel = slog.LevelDebug
|
||||||
}
|
}
|
||||||
region, err := cmd.Flags().GetString("region")
|
region, err := cmd.Flags().GetString("region")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -10,7 +10,6 @@ go_library(
|
||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/logger",
|
"//internal/logger",
|
||||||
"//internal/versions",
|
"//internal/versions",
|
||||||
"@org_uber_go_zap//zapcore",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,14 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
|
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -25,18 +27,21 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log := logger.New(logger.PlainLog, zapcore.DebugLevel)
|
log := logger.NewTextLogger(slog.LevelDebug)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *refFlag == "" {
|
if *refFlag == "" {
|
||||||
log.Fatalf("ref must be set")
|
log.Error("ref must be set")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if *streamFlag == "" {
|
if *streamFlag == "" {
|
||||||
log.Fatalf("stream must be set")
|
log.Error("stream must be set")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if *versionFlag == "" {
|
if *versionFlag == "" {
|
||||||
log.Fatalf("version must be set")
|
log.Error("version must be set")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
cliInfo := versionsapi.CLIInfo{
|
cliInfo := versionsapi.CLIInfo{
|
||||||
|
@ -52,15 +57,18 @@ func main() {
|
||||||
|
|
||||||
c, cclose, err := versionsapi.NewClient(ctx, "eu-central-1", "cdn-constellation-backend", constants.CDNDefaultDistributionID, false, log)
|
c, cclose, err := versionsapi.NewClient(ctx, "eu-central-1", "cdn-constellation-backend", constants.CDNDefaultDistributionID, false, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("creating s3 client: %w", err)
|
log.Error(fmt.Sprintf("creating s3 client: %s", err))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := cclose(ctx); err != nil {
|
if err := cclose(ctx); err != nil {
|
||||||
log.Fatalf("invalidating cache: %w", err)
|
log.Error(fmt.Sprintf("invalidating cache: %s", err))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := c.UpdateCLIInfo(ctx, cliInfo); err != nil {
|
if err := c.UpdateCLIInfo(ctx, cliInfo); err != nil {
|
||||||
log.Fatalf("updating cli info: %w", err)
|
log.Error(fmt.Sprintf("updating cli info: %s", err))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ go_library(
|
||||||
"//hack/oci-pin/internal/sums",
|
"//hack/oci-pin/internal/sums",
|
||||||
"//internal/logger",
|
"//internal/logger",
|
||||||
"@com_github_spf13_cobra//:cobra",
|
"@com_github_spf13_cobra//:cobra",
|
||||||
"@org_uber_go_zap//zapcore",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -16,7 +17,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/hack/oci-pin/internal/inject"
|
"github.com/edgelesssys/constellation/v2/hack/oci-pin/internal/inject"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newCodegenCmd() *cobra.Command {
|
func newCodegenCmd() *cobra.Command {
|
||||||
|
@ -44,15 +44,15 @@ func runCodegen(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
|
|
||||||
registry, prefix, name, tag, err := splitRepoTag(flags.imageRepoTag)
|
registry, prefix, name, tag, err := splitRepoTag(flags.imageRepoTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("splitting OCI image reference %q: %w", flags.imageRepoTag, err)
|
return fmt.Errorf("splitting OCI image reference %q: %w", flags.imageRepoTag, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Generating Go code for OCI image %s.", name)
|
log.Debug(fmt.Sprintf("Generating Go code for OCI image %s.", name))
|
||||||
|
|
||||||
ociIndexPath := filepath.Join(flags.ociPath, "index.json")
|
ociIndexPath := filepath.Join(flags.ociPath, "index.json")
|
||||||
index, err := os.Open(ociIndexPath)
|
index, err := os.Open(ociIndexPath)
|
||||||
|
@ -78,7 +78,7 @@ func runCodegen(cmd *cobra.Command, _ []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("OCI image digest: %s", digest)
|
log.Debug(fmt.Sprintf("OCI image digest: %s", digest))
|
||||||
|
|
||||||
if err := inject.Render(out, inject.PinningValues{
|
if err := inject.Render(out, inject.PinningValues{
|
||||||
Package: flags.pkg,
|
Package: flags.pkg,
|
||||||
|
@ -92,7 +92,7 @@ func runCodegen(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("rendering Go code: %w", err)
|
return fmt.Errorf("rendering Go code: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Go code created at %q 🤖", flags.output)
|
log.Debug(fmt.Sprintf("Go code created at %q 🤖", flags.output))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ type codegenFlags struct {
|
||||||
pkg string
|
pkg string
|
||||||
identifier string
|
identifier string
|
||||||
imageRepoTag string
|
imageRepoTag string
|
||||||
logLevel zapcore.Level
|
logLevel slog.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCodegenFlags(cmd *cobra.Command) (codegenFlags, error) {
|
func parseCodegenFlags(cmd *cobra.Command) (codegenFlags, error) {
|
||||||
|
@ -137,9 +137,9 @@ func parseCodegenFlags(cmd *cobra.Command) (codegenFlags, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return codegenFlags{}, err
|
return codegenFlags{}, err
|
||||||
}
|
}
|
||||||
logLevel := zapcore.InfoLevel
|
logLevel := slog.LevelInfo
|
||||||
if verbose {
|
if verbose {
|
||||||
logLevel = zapcore.DebugLevel
|
logLevel = slog.LevelDebug
|
||||||
}
|
}
|
||||||
|
|
||||||
return codegenFlags{
|
return codegenFlags{
|
||||||
|
|
|
@ -8,12 +8,12 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/hack/oci-pin/internal/sums"
|
"github.com/edgelesssys/constellation/v2/hack/oci-pin/internal/sums"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newMergeCmd() *cobra.Command {
|
func newMergeCmd() *cobra.Command {
|
||||||
|
@ -35,10 +35,10 @@ func runMerge(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
|
|
||||||
log.Debugf("Merging sum file from %q into %q.", flags.inputs, flags.output)
|
log.Debug(fmt.Sprintf("Merging sum file from %q into %q.", flags.inputs, flags.output))
|
||||||
|
|
||||||
var out io.Writer
|
var out io.Writer
|
||||||
if flags.output == "-" {
|
if flags.output == "-" {
|
||||||
|
@ -61,7 +61,7 @@ func runMerge(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("creating merged sum file: %w", err)
|
return fmt.Errorf("creating merged sum file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Sum file created at %q 🤖", flags.output)
|
log.Debug(fmt.Sprintf("Sum file created at %q 🤖", flags.output))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ func parseInput(input string) ([]sums.PinnedImageReference, error) {
|
||||||
type mergeFlags struct {
|
type mergeFlags struct {
|
||||||
inputs []string
|
inputs []string
|
||||||
output string
|
output string
|
||||||
logLevel zapcore.Level
|
logLevel slog.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseMergeFlags(cmd *cobra.Command) (mergeFlags, error) {
|
func parseMergeFlags(cmd *cobra.Command) (mergeFlags, error) {
|
||||||
|
@ -109,9 +109,9 @@ func parseMergeFlags(cmd *cobra.Command) (mergeFlags, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mergeFlags{}, err
|
return mergeFlags{}, err
|
||||||
}
|
}
|
||||||
logLevel := zapcore.InfoLevel
|
logLevel := slog.LevelInfo
|
||||||
if verbose {
|
if verbose {
|
||||||
logLevel = zapcore.DebugLevel
|
logLevel = slog.LevelDebug
|
||||||
}
|
}
|
||||||
|
|
||||||
return mergeFlags{
|
return mergeFlags{
|
||||||
|
|
|
@ -8,6 +8,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -16,7 +17,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/hack/oci-pin/internal/sums"
|
"github.com/edgelesssys/constellation/v2/hack/oci-pin/internal/sums"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newSumCmd() *cobra.Command {
|
func newSumCmd() *cobra.Command {
|
||||||
|
@ -41,15 +41,15 @@ func runSum(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
|
|
||||||
registry, prefix, name, tag, err := splitRepoTag(flags.imageRepoTag)
|
registry, prefix, name, tag, err := splitRepoTag(flags.imageRepoTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("splitting repo tag: %w", err)
|
return fmt.Errorf("splitting repo tag: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Generating sum file for OCI image %s.", name)
|
log.Debug(fmt.Sprintf("Generating sum file for OCI image %s.", name))
|
||||||
|
|
||||||
ociIndexPath := filepath.Join(flags.ociPath, "index.json")
|
ociIndexPath := filepath.Join(flags.ociPath, "index.json")
|
||||||
index, err := os.Open(ociIndexPath)
|
index, err := os.Open(ociIndexPath)
|
||||||
|
@ -75,7 +75,7 @@ func runSum(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("extracting OCI image digest: %w", err)
|
return fmt.Errorf("extracting OCI image digest: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("OCI image digest: %s", digest)
|
log.Debug(fmt.Sprintf("OCI image digest: %s", digest))
|
||||||
|
|
||||||
refs := []sums.PinnedImageReference{
|
refs := []sums.PinnedImageReference{
|
||||||
{
|
{
|
||||||
|
@ -91,7 +91,7 @@ func runSum(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("creating sum file: %w", err)
|
return fmt.Errorf("creating sum file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Sum file created at %q 🤖", flags.output)
|
log.Debug(fmt.Sprintf("Sum file created at %q 🤖", flags.output))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ type sumFlags struct {
|
||||||
ociPath string
|
ociPath string
|
||||||
output string
|
output string
|
||||||
imageRepoTag string
|
imageRepoTag string
|
||||||
logLevel zapcore.Level
|
logLevel slog.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSumFlags(cmd *cobra.Command) (sumFlags, error) {
|
func parseSumFlags(cmd *cobra.Command) (sumFlags, error) {
|
||||||
|
@ -126,9 +126,9 @@ func parseSumFlags(cmd *cobra.Command) (sumFlags, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sumFlags{}, err
|
return sumFlags{}, err
|
||||||
}
|
}
|
||||||
logLevel := zapcore.InfoLevel
|
logLevel := slog.LevelInfo
|
||||||
if verbose {
|
if verbose {
|
||||||
logLevel = zapcore.DebugLevel
|
logLevel = slog.LevelDebug
|
||||||
}
|
}
|
||||||
|
|
||||||
return sumFlags{
|
return sumFlags{
|
||||||
|
|
|
@ -17,8 +17,6 @@ go_library(
|
||||||
"//hack/qemu-metadata-api/virtwrapper",
|
"//hack/qemu-metadata-api/virtwrapper",
|
||||||
"//internal/logger",
|
"//internal/logger",
|
||||||
"@org_libvirt_go_libvirt//:libvirt",
|
"@org_libvirt_go_libvirt//:libvirt",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
"@org_uber_go_zap//zapcore",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,12 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/server"
|
"github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/server"
|
||||||
"github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper"
|
"github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"go.uber.org/zap"
|
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
"libvirt.org/go/libvirt"
|
"libvirt.org/go/libvirt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,16 +26,18 @@ func main() {
|
||||||
initSecretHash := flag.String("initsecrethash", "", "brcypt hash of the init secret")
|
initSecretHash := flag.String("initsecrethash", "", "brcypt hash of the init secret")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
log := logger.New(logger.JSONLog, zapcore.InfoLevel)
|
log := logger.NewJSONLogger(slog.LevelInfo)
|
||||||
|
|
||||||
conn, err := libvirt.NewConnect(*libvirtURI)
|
conn, err := libvirt.NewConnect(*libvirtURI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to connect to libvirt")
|
log.With(slog.Any("error", err)).Error("Failed to connect to libvirt")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
serv := server.New(log, *targetNetwork, *initSecretHash, &virtwrapper.Connect{Conn: conn})
|
serv := server.New(log, *targetNetwork, *initSecretHash, &virtwrapper.Connect{Conn: conn})
|
||||||
if err := serv.ListenAndServe(*bindPort); err != nil {
|
if err := serv.ListenAndServe(*bindPort); err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to serve")
|
log.With(slog.Any("error", err)).Error("Failed to serve")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,7 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//hack/qemu-metadata-api/virtwrapper",
|
"//hack/qemu-metadata-api/virtwrapper",
|
||||||
"//internal/cloud/metadata",
|
"//internal/cloud/metadata",
|
||||||
"//internal/logger",
|
|
||||||
"//internal/role",
|
"//internal/role",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -9,27 +9,26 @@ package server
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper"
|
"github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api/virtwrapper"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server that provides QEMU metadata.
|
// Server that provides QEMU metadata.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
log *logger.Logger
|
log *slog.Logger
|
||||||
virt virConnect
|
virt virConnect
|
||||||
network string
|
network string
|
||||||
initSecretHashVal []byte
|
initSecretHashVal []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Server.
|
// New creates a new Server.
|
||||||
func New(log *logger.Logger, network, initSecretHash string, conn virConnect) *Server {
|
func New(log *slog.Logger, network, initSecretHash string, conn virConnect) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
log: log,
|
log: log,
|
||||||
virt: conn,
|
virt: conn,
|
||||||
|
@ -55,25 +54,25 @@ func (s *Server) ListenAndServe(port string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.log.Infof("Starting QEMU metadata API on %s", lis.Addr())
|
s.log.Info(fmt.Sprintf("Starting QEMU metadata API on %s", lis.Addr()))
|
||||||
return server.Serve(lis)
|
return server.Serve(lis)
|
||||||
}
|
}
|
||||||
|
|
||||||
// listSelf returns peer information about the instance issuing the request.
|
// listSelf returns peer information about the instance issuing the request.
|
||||||
func (s *Server) listSelf(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) listSelf(w http.ResponseWriter, r *http.Request) {
|
||||||
log := s.log.With(zap.String("peer", r.RemoteAddr))
|
log := s.log.With(slog.String("peer", r.RemoteAddr))
|
||||||
log.Infof("Serving GET request for /self")
|
log.Info("Serving GET request for /self")
|
||||||
|
|
||||||
remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
|
remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Errorf("Failed to parse remote address")
|
log.With(slog.Any("error", err)).Error("Failed to parse remote address")
|
||||||
http.Error(w, fmt.Sprintf("Failed to parse remote address: %s\n", err), http.StatusInternalServerError)
|
http.Error(w, fmt.Sprintf("Failed to parse remote address: %s\n", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peers, err := s.listAll()
|
peers, err := s.listAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Errorf("Failed to list peer metadata")
|
log.With(slog.Any("error", err)).Error("Failed to list peer metadata")
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -85,23 +84,23 @@ func (s *Server) listSelf(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Infof("Request successful")
|
log.Info("Request successful")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Errorf("Failed to find peer in active leases")
|
log.Error("Failed to find peer in active leases")
|
||||||
http.Error(w, "No matching peer found", http.StatusNotFound)
|
http.Error(w, "No matching peer found", http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
// listPeers returns a list of all active peers.
|
// listPeers returns a list of all active peers.
|
||||||
func (s *Server) listPeers(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) listPeers(w http.ResponseWriter, r *http.Request) {
|
||||||
log := s.log.With(zap.String("peer", r.RemoteAddr))
|
log := s.log.With(slog.String("peer", r.RemoteAddr))
|
||||||
log.Infof("Serving GET request for /peers")
|
log.Info("Serving GET request for /peers")
|
||||||
|
|
||||||
peers, err := s.listAll()
|
peers, err := s.listAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Errorf("Failed to list peer metadata")
|
log.With(slog.Any("error", err)).Error("Failed to list peer metadata")
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -111,38 +110,38 @@ func (s *Server) listPeers(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Infof("Request successful")
|
log.Info("Request successful")
|
||||||
}
|
}
|
||||||
|
|
||||||
// initSecretHash returns the hash of the init secret.
|
// initSecretHash returns the hash of the init secret.
|
||||||
func (s *Server) initSecretHash(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) initSecretHash(w http.ResponseWriter, r *http.Request) {
|
||||||
log := s.log.With(zap.String("initSecretHash", r.RemoteAddr))
|
log := s.log.With(slog.String("initSecretHash", r.RemoteAddr))
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
log.With(zap.String("method", r.Method)).Errorf("Invalid method for /initSecretHash")
|
log.With(slog.String("method", r.Method)).Error("Invalid method for /initSecretHash")
|
||||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Infof("Serving GET request for /initsecrethash")
|
log.Info("Serving GET request for /initsecrethash")
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
w.Header().Set("Content-Type", "text/plain")
|
||||||
_, err := w.Write(s.initSecretHashVal)
|
_, err := w.Write(s.initSecretHashVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Errorf("Failed to write init secret hash")
|
log.With(slog.Any("error", err)).Error("Failed to write init secret hash")
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Infof("Request successful")
|
log.Info("Request successful")
|
||||||
}
|
}
|
||||||
|
|
||||||
// getEndpoint returns the IP address of the first control-plane instance.
|
// getEndpoint returns the IP address of the first control-plane instance.
|
||||||
// This allows us to fake a load balancer for QEMU instances.
|
// This allows us to fake a load balancer for QEMU instances.
|
||||||
func (s *Server) getEndpoint(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) getEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
log := s.log.With(zap.String("peer", r.RemoteAddr))
|
log := s.log.With(slog.String("peer", r.RemoteAddr))
|
||||||
log.Infof("Serving GET request for /endpoint")
|
log.Info("Serving GET request for /endpoint")
|
||||||
|
|
||||||
net, err := s.virt.LookupNetworkByName(s.network)
|
net, err := s.virt.LookupNetworkByName(s.network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Errorf("Failed to lookup network")
|
log.With(slog.Any("error", err)).Error("Failed to lookup network")
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -150,7 +149,7 @@ func (s *Server) getEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
leases, err := net.GetDHCPLeases()
|
leases, err := net.GetDHCPLeases()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Errorf("Failed to get DHCP leases")
|
log.With(slog.Any("error", err)).Error("Failed to get DHCP leases")
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,12 +161,12 @@ func (s *Server) getEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Infof("Request successful")
|
log.Info("Request successful")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Errorf("Failed to find control-plane peer in active leases")
|
log.Error("Failed to find control-plane peer in active leases")
|
||||||
http.Error(w, "No matching peer found", http.StatusNotFound)
|
http.Error(w, "No matching peer found", http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,5 @@ go_library(
|
||||||
"//internal/osimage/nop",
|
"//internal/osimage/nop",
|
||||||
"//internal/osimage/uplosi",
|
"//internal/osimage/uplosi",
|
||||||
"@com_github_spf13_cobra//:cobra",
|
"@com_github_spf13_cobra//:cobra",
|
||||||
"@org_uber_go_zap//zapcore",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,20 +8,20 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"log/slog"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
|
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type s3Flags struct {
|
type s3Flags struct {
|
||||||
region string
|
region string
|
||||||
bucket string
|
bucket string
|
||||||
distributionID string
|
distributionID string
|
||||||
logLevel zapcore.Level
|
logLevel slog.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseS3Flags(cmd *cobra.Command) (s3Flags, error) {
|
func parseS3Flags(cmd *cobra.Command) (s3Flags, error) {
|
||||||
|
@ -41,9 +41,9 @@ func parseS3Flags(cmd *cobra.Command) (s3Flags, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return s3Flags{}, err
|
return s3Flags{}, err
|
||||||
}
|
}
|
||||||
logLevel := zapcore.InfoLevel
|
logLevel := slog.LevelInfo
|
||||||
if verbose {
|
if verbose {
|
||||||
logLevel = zapcore.DebugLevel
|
logLevel = slog.LevelDebug
|
||||||
}
|
}
|
||||||
|
|
||||||
return s3Flags{
|
return s3Flags{
|
||||||
|
@ -84,7 +84,7 @@ func parseUploadMeasurementsFlags(cmd *cobra.Command) (measurementsFlags, error)
|
||||||
|
|
||||||
type mergeMeasurementsFlags struct {
|
type mergeMeasurementsFlags struct {
|
||||||
out string
|
out string
|
||||||
logLevel zapcore.Level
|
logLevel slog.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseMergeMeasurementsFlags(cmd *cobra.Command) (mergeMeasurementsFlags, error) {
|
func parseMergeMeasurementsFlags(cmd *cobra.Command) (mergeMeasurementsFlags, error) {
|
||||||
|
@ -96,9 +96,9 @@ func parseMergeMeasurementsFlags(cmd *cobra.Command) (mergeMeasurementsFlags, er
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mergeMeasurementsFlags{}, err
|
return mergeMeasurementsFlags{}, err
|
||||||
}
|
}
|
||||||
logLevel := zapcore.InfoLevel
|
logLevel := slog.LevelInfo
|
||||||
if verbose {
|
if verbose {
|
||||||
logLevel = zapcore.DebugLevel
|
logLevel = slog.LevelDebug
|
||||||
}
|
}
|
||||||
|
|
||||||
return mergeMeasurementsFlags{
|
return mergeMeasurementsFlags{
|
||||||
|
@ -112,7 +112,7 @@ type envelopeMeasurementsFlags struct {
|
||||||
csp cloudprovider.Provider
|
csp cloudprovider.Provider
|
||||||
attestationVariant string
|
attestationVariant string
|
||||||
in, out string
|
in, out string
|
||||||
logLevel zapcore.Level
|
logLevel slog.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseEnvelopeMeasurementsFlags(cmd *cobra.Command) (envelopeMeasurementsFlags, error) {
|
func parseEnvelopeMeasurementsFlags(cmd *cobra.Command) (envelopeMeasurementsFlags, error) {
|
||||||
|
@ -148,9 +148,9 @@ func parseEnvelopeMeasurementsFlags(cmd *cobra.Command) (envelopeMeasurementsFla
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return envelopeMeasurementsFlags{}, err
|
return envelopeMeasurementsFlags{}, err
|
||||||
}
|
}
|
||||||
logLevel := zapcore.InfoLevel
|
logLevel := slog.LevelInfo
|
||||||
if verbose {
|
if verbose {
|
||||||
logLevel = zapcore.DebugLevel
|
logLevel = slog.LevelDebug
|
||||||
}
|
}
|
||||||
|
|
||||||
return envelopeMeasurementsFlags{
|
return envelopeMeasurementsFlags{
|
||||||
|
@ -176,7 +176,7 @@ type uplosiFlags struct {
|
||||||
bucket string
|
bucket string
|
||||||
distributionID string
|
distributionID string
|
||||||
|
|
||||||
logLevel zapcore.Level
|
logLevel slog.Level
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseUplosiFlags(cmd *cobra.Command) (uplosiFlags, error) {
|
func parseUplosiFlags(cmd *cobra.Command) (uplosiFlags, error) {
|
||||||
|
@ -271,9 +271,9 @@ func parseUplosiFlags(cmd *cobra.Command) (uplosiFlags, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return uplosiFlags{}, err
|
return uplosiFlags{}, err
|
||||||
}
|
}
|
||||||
logLevel := zapcore.InfoLevel
|
logLevel := slog.LevelInfo
|
||||||
if verbose {
|
if verbose {
|
||||||
logLevel = zapcore.DebugLevel
|
logLevel = slog.LevelDebug
|
||||||
}
|
}
|
||||||
|
|
||||||
return uplosiFlags{
|
return uplosiFlags{
|
||||||
|
|
|
@ -49,8 +49,8 @@ func runInfo(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
info, err := readInfoArgs(args)
|
info, err := readInfoArgs(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -62,7 +62,7 @@ func runInfo(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := uploadCClose(cmd.Context()); err != nil {
|
if err := uploadCClose(cmd.Context()); err != nil {
|
||||||
log.Errorf("closing upload client: %v", err)
|
log.Error(fmt.Sprintf("closing upload client: %v", err))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ func runInfo(cmd *cobra.Command, args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("uploading image info: %w", err)
|
return fmt.Errorf("uploading image info: %w", err)
|
||||||
}
|
}
|
||||||
log.Infof("Uploaded image info to %s", url)
|
log.Info(fmt.Sprintf("Uploaded image info to %s", url))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,8 @@ func runEnvelopeMeasurements(cmd *cobra.Command, _ []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
|
|
||||||
f, err := os.Open(flags.in)
|
f, err := os.Open(flags.in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -97,7 +97,7 @@ func runEnvelopeMeasurements(cmd *cobra.Command, _ []string) error {
|
||||||
if err := json.NewEncoder(out).Encode(enveloped); err != nil {
|
if err := json.NewEncoder(out).Encode(enveloped); err != nil {
|
||||||
return fmt.Errorf("enveloping measurements: writing output file: %w", err)
|
return fmt.Errorf("enveloping measurements: writing output file: %w", err)
|
||||||
}
|
}
|
||||||
log.Infof("Enveloped image measurements")
|
log.Info("Enveloped image measurements")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,8 @@ func runMergeMeasurements(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
|
|
||||||
mergedMeasurements, err := readMeasurementsArgs(args)
|
mergedMeasurements, err := readMeasurementsArgs(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -65,7 +65,7 @@ func runMergeMeasurements(cmd *cobra.Command, args []string) error {
|
||||||
if err := json.NewEncoder(out).Encode(mergedMeasurements); err != nil {
|
if err := json.NewEncoder(out).Encode(mergedMeasurements); err != nil {
|
||||||
return fmt.Errorf("merging measurements: writing output file: %w", err)
|
return fmt.Errorf("merging measurements: writing output file: %w", err)
|
||||||
}
|
}
|
||||||
log.Infof("Merged image measurements")
|
log.Info("Merged image measurements")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,8 @@ func runMeasurementsUpload(cmd *cobra.Command, _ []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
|
|
||||||
uploadC, uploadCClose, err := measurementsuploader.New(cmd.Context(), flags.region, flags.bucket, flags.distributionID, log)
|
uploadC, uploadCClose, err := measurementsuploader.New(cmd.Context(), flags.region, flags.bucket, flags.distributionID, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -61,7 +61,7 @@ func runMeasurementsUpload(cmd *cobra.Command, _ []string) error {
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := uploadCClose(cmd.Context()); err != nil {
|
if err := uploadCClose(cmd.Context()); err != nil {
|
||||||
log.Errorf("closing upload client: %v", err)
|
log.Error("closing upload client: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -80,6 +80,6 @@ func runMeasurementsUpload(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("uploading image info: %w", err)
|
return fmt.Errorf("uploading image info: %w", err)
|
||||||
}
|
}
|
||||||
log.Infof("Uploaded image measurements to %s (and signature to %s)", measurementsURL, signatureURL)
|
log.Info(fmt.Sprintf("Uploaded image measurements to %s (and signature to %s)", measurementsURL, signatureURL))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,8 +58,8 @@ func runUplosi(cmd *cobra.Command, _ []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log := logger.New(logger.PlainLog, flags.logLevel)
|
log := logger.NewTextLogger(flags.logLevel)
|
||||||
log.Debugf("Parsed flags: %+v", flags)
|
log.Debug(fmt.Sprintf("Parsed flags: %+v", flags))
|
||||||
|
|
||||||
archiveC, archiveCClose, err := archive.New(cmd.Context(), flags.region, flags.bucket, flags.distributionID, log)
|
archiveC, archiveCClose, err := archive.New(cmd.Context(), flags.region, flags.bucket, flags.distributionID, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -67,7 +67,7 @@ func runUplosi(cmd *cobra.Command, _ []string) error {
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := archiveCClose(cmd.Context()); err != nil {
|
if err := archiveCClose(cmd.Context()); err != nil {
|
||||||
log.Errorf("closing archive client: %v", err)
|
log.Error(fmt.Sprintf("closing archive client: %v", err))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ go_library(
|
||||||
"//internal/api/fetcher",
|
"//internal/api/fetcher",
|
||||||
"//internal/attestation/variant",
|
"//internal/attestation/variant",
|
||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/logger",
|
|
||||||
"//internal/sigstore",
|
"//internal/sigstore",
|
||||||
"//internal/staticupload",
|
"//internal/staticupload",
|
||||||
"@com_github_aws_aws_sdk_go//aws",
|
"@com_github_aws_aws_sdk_go//aws",
|
||||||
|
|
|
@ -33,7 +33,6 @@ go_library(
|
||||||
"@com_github_aws_aws_sdk_go_v2_service_s3//types",
|
"@com_github_aws_aws_sdk_go_v2_service_s3//types",
|
||||||
"@com_github_spf13_afero//:afero",
|
"@com_github_spf13_afero//:afero",
|
||||||
"@com_github_spf13_cobra//:cobra",
|
"@com_github_spf13_cobra//:cobra",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
|
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
|
||||||
|
@ -16,7 +17,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/staticupload"
|
"github.com/edgelesssys/constellation/v2/internal/staticupload"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// newDeleteCmd creates the delete command.
|
// newDeleteCmd creates the delete command.
|
||||||
|
@ -46,7 +46,7 @@ func newDeleteCmd() *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDelete(cmd *cobra.Command, args []string) (retErr error) {
|
func runDelete(cmd *cobra.Command, args []string) (retErr error) {
|
||||||
log := logger.New(logger.PlainLog, zap.DebugLevel).Named("attestationconfigapi")
|
log := logger.NewTextLogger(slog.LevelDebug).WithGroup("attestationconfigapi")
|
||||||
|
|
||||||
deleteCfg, err := newDeleteConfig(cmd, ([3]string)(args[:3]))
|
deleteCfg, err := newDeleteConfig(cmd, ([3]string)(args[:3]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -89,7 +89,7 @@ func runRecursiveDelete(cmd *cobra.Command, args []string) (retErr error) {
|
||||||
return fmt.Errorf("creating delete config: %w", err)
|
return fmt.Errorf("creating delete config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log := logger.New(logger.PlainLog, zap.DebugLevel).Named("attestationconfigapi")
|
log := logger.NewTextLogger(slog.LevelDebug).WithGroup("attestationconfigapi")
|
||||||
client, closeFn, err := staticupload.New(cmd.Context(), staticupload.Config{
|
client, closeFn, err := staticupload.New(cmd.Context(), staticupload.Config{
|
||||||
Bucket: deleteCfg.bucket,
|
Bucket: deleteCfg.bucket,
|
||||||
Region: deleteCfg.region,
|
Region: deleteCfg.region,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -21,7 +22,6 @@ import (
|
||||||
"github.com/edgelesssys/constellation/v2/internal/verify"
|
"github.com/edgelesssys/constellation/v2/internal/verify"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newUploadCmd() *cobra.Command {
|
func newUploadCmd() *cobra.Command {
|
||||||
|
@ -61,7 +61,7 @@ func envCheck(_ *cobra.Command, _ []string) error {
|
||||||
|
|
||||||
func runUpload(cmd *cobra.Command, args []string) (retErr error) {
|
func runUpload(cmd *cobra.Command, args []string) (retErr error) {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
log := logger.New(logger.PlainLog, zap.DebugLevel).Named("attestationconfigapi")
|
log := logger.NewTextLogger(slog.LevelDebug).WithGroup("attestationconfigapi")
|
||||||
|
|
||||||
uploadCfg, err := newConfig(cmd, ([3]string)(args[:3]))
|
uploadCfg, err := newConfig(cmd, ([3]string)(args[:3]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -110,25 +110,25 @@ func uploadReport(ctx context.Context,
|
||||||
client *attestationconfigapi.Client,
|
client *attestationconfigapi.Client,
|
||||||
cfg uploadConfig,
|
cfg uploadConfig,
|
||||||
fs file.Handler,
|
fs file.Handler,
|
||||||
log *logger.Logger,
|
log *slog.Logger,
|
||||||
) error {
|
) error {
|
||||||
if cfg.kind != snpReport {
|
if cfg.kind != snpReport {
|
||||||
return fmt.Errorf("kind %s not supported", cfg.kind)
|
return fmt.Errorf("kind %s not supported", cfg.kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Reading SNP report from file: %s", cfg.path)
|
log.Info(fmt.Sprintf("Reading SNP report from file: %s", cfg.path))
|
||||||
var report verify.Report
|
var report verify.Report
|
||||||
if err := fs.ReadJSON(cfg.path, &report); err != nil {
|
if err := fs.ReadJSON(cfg.path, &report); err != nil {
|
||||||
return fmt.Errorf("reading snp report: %w", err)
|
return fmt.Errorf("reading snp report: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
inputVersion := convertTCBVersionToSNPVersion(report.SNPReport.LaunchTCB)
|
inputVersion := convertTCBVersionToSNPVersion(report.SNPReport.LaunchTCB)
|
||||||
log.Infof("Input report: %+v", inputVersion)
|
log.Info(fmt.Sprintf("Input report: %+v", inputVersion))
|
||||||
|
|
||||||
latestAPIVersionAPI, err := attestationconfigapi.NewFetcherWithCustomCDNAndCosignKey(cfg.url, cfg.cosignPublicKey).FetchSEVSNPVersionLatest(ctx, attestation)
|
latestAPIVersionAPI, err := attestationconfigapi.NewFetcherWithCustomCDNAndCosignKey(cfg.url, cfg.cosignPublicKey).FetchSEVSNPVersionLatest(ctx, attestation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, attestationconfigapi.ErrNoVersionsFound) {
|
if errors.Is(err, attestationconfigapi.ErrNoVersionsFound) {
|
||||||
log.Infof("No versions found in API, but assuming that we are uploading the first version.")
|
log.Info("No versions found in API, but assuming that we are uploading the first version.")
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("fetching latest version: %w", err)
|
return fmt.Errorf("fetching latest version: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ func uploadReport(ctx context.Context,
|
||||||
latestAPIVersion := latestAPIVersionAPI.SEVSNPVersion
|
latestAPIVersion := latestAPIVersionAPI.SEVSNPVersion
|
||||||
if err := client.UploadSEVSNPVersionLatest(ctx, attestation, inputVersion, latestAPIVersion, cfg.uploadDate, cfg.force); err != nil {
|
if err := client.UploadSEVSNPVersionLatest(ctx, attestation, inputVersion, latestAPIVersion, cfg.uploadDate, cfg.force); err != nil {
|
||||||
if errors.Is(err, attestationconfigapi.ErrNoNewerVersion) {
|
if errors.Is(err, attestationconfigapi.ErrNoNewerVersion) {
|
||||||
log.Infof("Input version: %+v is not newer than latest API version: %+v", inputVersion, latestAPIVersion)
|
log.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v", inputVersion, latestAPIVersion))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("updating latest version: %w", err)
|
return fmt.Errorf("updating latest version: %w", err)
|
||||||
|
|
|
@ -9,11 +9,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
apiclient "github.com/edgelesssys/constellation/v2/internal/api/client"
|
apiclient "github.com/edgelesssys/constellation/v2/internal/api/client"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/staticupload"
|
"github.com/edgelesssys/constellation/v2/internal/staticupload"
|
||||||
|
@ -32,7 +32,7 @@ type Client struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a new Client.
|
// NewClient returns a new Client.
|
||||||
func NewClient(ctx context.Context, cfg staticupload.Config, cosignPwd, privateKey []byte, dryRun bool, versionWindowSize int, log *logger.Logger) (*Client, apiclient.CloseFunc, error) {
|
func NewClient(ctx context.Context, cfg staticupload.Config, cosignPwd, privateKey []byte, dryRun bool, versionWindowSize int, log *slog.Logger) (*Client, apiclient.CloseFunc, error) {
|
||||||
s3Client, clientClose, err := apiclient.NewClient(ctx, cfg.Region, cfg.Bucket, cfg.DistributionID, dryRun, log)
|
s3Client, clientClose, err := apiclient.NewClient(ctx, cfg.Region, cfg.Bucket, cfg.DistributionID, dryRun, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("failed to create s3 storage: %w", err)
|
return nil, nil, fmt.Errorf("failed to create s3 storage: %w", err)
|
||||||
|
|
|
@ -55,23 +55,23 @@ func (c Client) UploadSEVSNPVersionLatest(ctx context.Context, attestation varia
|
||||||
return fmt.Errorf("list reported versions: %w", err)
|
return fmt.Errorf("list reported versions: %w", err)
|
||||||
}
|
}
|
||||||
if len(versionDates) < c.cacheWindowSize {
|
if len(versionDates) < c.cacheWindowSize {
|
||||||
c.s3Client.Logger.Warnf("Skipping version update, found %d, expected %d reported versions.", len(versionDates), c.cacheWindowSize)
|
c.s3Client.Logger.Warn(fmt.Sprintf("Skipping version update, found %d, expected %d reported versions.", len(versionDates), c.cacheWindowSize))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
minVersion, minDate, err := c.findMinVersion(ctx, attestation, versionDates)
|
minVersion, minDate, err := c.findMinVersion(ctx, attestation, versionDates)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get minimal version: %w", err)
|
return fmt.Errorf("get minimal version: %w", err)
|
||||||
}
|
}
|
||||||
c.s3Client.Logger.Infof("Found minimal version: %+v with date: %s", minVersion, minDate)
|
c.s3Client.Logger.Info(fmt.Sprintf("Found minimal version: %+v with date: %s", minVersion, minDate))
|
||||||
shouldUpdateAPI, err := isInputNewerThanOtherVersion(minVersion, latestAPIVersion)
|
shouldUpdateAPI, err := isInputNewerThanOtherVersion(minVersion, latestAPIVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrNoNewerVersion
|
return ErrNoNewerVersion
|
||||||
}
|
}
|
||||||
if !shouldUpdateAPI {
|
if !shouldUpdateAPI {
|
||||||
c.s3Client.Logger.Infof("Input version: %+v is not newer than latest API version: %+v", minVersion, latestAPIVersion)
|
c.s3Client.Logger.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v", minVersion, latestAPIVersion))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
c.s3Client.Logger.Infof("Input version: %+v is newer than latest API version: %+v", minVersion, latestAPIVersion)
|
c.s3Client.Logger.Info(fmt.Sprintf("Input version: %+v is newer than latest API version: %+v", minVersion, latestAPIVersion))
|
||||||
t, err := time.Parse(VersionFormat, minDate)
|
t, err := time.Parse(VersionFormat, minDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("parsing date: %w", err)
|
return fmt.Errorf("parsing date: %w", err)
|
||||||
|
@ -79,7 +79,7 @@ func (c Client) UploadSEVSNPVersionLatest(ctx context.Context, attestation varia
|
||||||
if err := c.uploadSEVSNPVersion(ctx, attestation, minVersion, t); err != nil {
|
if err := c.uploadSEVSNPVersion(ctx, attestation, minVersion, t); err != nil {
|
||||||
return fmt.Errorf("uploading version: %w", err)
|
return fmt.Errorf("uploading version: %w", err)
|
||||||
}
|
}
|
||||||
c.s3Client.Logger.Infof("Successfully uploaded new Azure SEV-SNP version: %+v", minVersion)
|
c.s3Client.Logger.Info(fmt.Sprintf("Successfully uploaded new Azure SEV-SNP version: %+v", minVersion))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,10 @@ go_library(
|
||||||
importpath = "github.com/edgelesssys/constellation/v2/internal/api/client",
|
importpath = "github.com/edgelesssys/constellation/v2/internal/api/client",
|
||||||
visibility = ["//:__subpackages__"],
|
visibility = ["//:__subpackages__"],
|
||||||
deps = [
|
deps = [
|
||||||
"//internal/logger",
|
|
||||||
"//internal/sigstore",
|
"//internal/sigstore",
|
||||||
"//internal/staticupload",
|
"//internal/staticupload",
|
||||||
"@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager",
|
"@com_github_aws_aws_sdk_go_v2_feature_s3_manager//:manager",
|
||||||
"@com_github_aws_aws_sdk_go_v2_service_s3//:s3",
|
"@com_github_aws_aws_sdk_go_v2_service_s3//:s3",
|
||||||
"@com_github_aws_aws_sdk_go_v2_service_s3//types",
|
"@com_github_aws_aws_sdk_go_v2_service_s3//types",
|
||||||
"@org_uber_go_zap//:zap",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -33,16 +33,15 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
|
s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/staticupload"
|
"github.com/edgelesssys/constellation/v2/internal/staticupload"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is the a general client for all APIs.
|
// Client is the a general client for all APIs.
|
||||||
|
@ -54,13 +53,13 @@ type Client struct {
|
||||||
dirtyPaths []string // written paths to be invalidated
|
dirtyPaths []string // written paths to be invalidated
|
||||||
DryRun bool // no write operations are performed
|
DryRun bool // no write operations are performed
|
||||||
|
|
||||||
Logger *logger.Logger
|
Logger *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReadOnlyClient creates a new read-only client.
|
// NewReadOnlyClient creates a new read-only client.
|
||||||
// This client can be used to fetch objects but cannot write updates.
|
// This client can be used to fetch objects but cannot write updates.
|
||||||
func NewReadOnlyClient(ctx context.Context, region, bucket, distributionID string,
|
func NewReadOnlyClient(ctx context.Context, region, bucket, distributionID string,
|
||||||
log *logger.Logger,
|
log *slog.Logger,
|
||||||
) (*Client, CloseFunc, error) {
|
) (*Client, CloseFunc, error) {
|
||||||
staticUploadClient, staticUploadClientClose, err := staticupload.New(ctx, staticupload.Config{
|
staticUploadClient, staticUploadClientClose, err := staticupload.New(ctx, staticupload.Config{
|
||||||
Region: region,
|
Region: region,
|
||||||
|
@ -89,7 +88,7 @@ func NewReadOnlyClient(ctx context.Context, region, bucket, distributionID strin
|
||||||
|
|
||||||
// NewClient creates a new client for the versions API.
|
// NewClient creates a new client for the versions API.
|
||||||
func NewClient(ctx context.Context, region, bucket, distributionID string, dryRun bool,
|
func NewClient(ctx context.Context, region, bucket, distributionID string, dryRun bool,
|
||||||
log *logger.Logger,
|
log *slog.Logger,
|
||||||
) (*Client, CloseFunc, error) {
|
) (*Client, CloseFunc, error) {
|
||||||
staticUploadClient, staticUploadClientClose, err := staticupload.New(ctx, staticupload.Config{
|
staticUploadClient, staticUploadClientClose, err := staticupload.New(ctx, staticupload.Config{
|
||||||
Region: region,
|
Region: region,
|
||||||
|
@ -120,7 +119,7 @@ func NewClient(ctx context.Context, region, bucket, distributionID string, dryRu
|
||||||
// It invalidates the CDN cache for all uploaded files.
|
// It invalidates the CDN cache for all uploaded files.
|
||||||
func (c *Client) Close(ctx context.Context) error {
|
func (c *Client) Close(ctx context.Context) error {
|
||||||
if c.s3ClientClose == nil {
|
if c.s3ClientClose == nil {
|
||||||
c.Logger.Debugf("Client has no s3ClientClose")
|
c.Logger.Debug("Client has no s3ClientClose")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return c.s3ClientClose(ctx)
|
return c.s3ClientClose(ctx)
|
||||||
|
@ -132,7 +131,7 @@ func (c *Client) DeletePath(ctx context.Context, path string) error {
|
||||||
Bucket: &c.bucket,
|
Bucket: &c.bucket,
|
||||||
Prefix: &path,
|
Prefix: &path,
|
||||||
}
|
}
|
||||||
c.Logger.Debugf("Listing objects in %s", path)
|
c.Logger.Debug(fmt.Sprintf("Listing objects in %s", path))
|
||||||
objs := []s3types.Object{}
|
objs := []s3types.Object{}
|
||||||
out := &s3.ListObjectsV2Output{IsTruncated: ptr(true)}
|
out := &s3.ListObjectsV2Output{IsTruncated: ptr(true)}
|
||||||
for out.IsTruncated != nil && *out.IsTruncated {
|
for out.IsTruncated != nil && *out.IsTruncated {
|
||||||
|
@ -143,10 +142,10 @@ func (c *Client) DeletePath(ctx context.Context, path string) error {
|
||||||
}
|
}
|
||||||
objs = append(objs, out.Contents...)
|
objs = append(objs, out.Contents...)
|
||||||
}
|
}
|
||||||
c.Logger.Debugf("Found %d objects in %s", len(objs), path)
|
c.Logger.Debug(fmt.Sprintf("Found %d objects in %s", len(objs), path))
|
||||||
|
|
||||||
if len(objs) == 0 {
|
if len(objs) == 0 {
|
||||||
c.Logger.Warnf("Path %s is already empty", path)
|
c.Logger.Warn(fmt.Sprintf("Path %s is already empty", path))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +155,7 @@ func (c *Client) DeletePath(ctx context.Context, path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.DryRun {
|
if c.DryRun {
|
||||||
c.Logger.Debugf("DryRun: Deleting %d objects with IDs %v", len(objs), objIDs)
|
c.Logger.Debug(fmt.Sprintf("DryRun: Deleting %d objects with IDs %v", len(objs), objIDs))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +167,7 @@ func (c *Client) DeletePath(ctx context.Context, path string) error {
|
||||||
Objects: objIDs,
|
Objects: objIDs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
c.Logger.Debugf("Deleting %d objects in %s", len(objs), path)
|
c.Logger.Debug(fmt.Sprintf("Deleting %d objects in %s", len(objs), path))
|
||||||
if _, err := c.s3Client.DeleteObjects(ctx, deleteIn); err != nil {
|
if _, err := c.s3Client.DeleteObjects(ctx, deleteIn); err != nil {
|
||||||
return fmt.Errorf("deleting objects in %s: %w", path, err)
|
return fmt.Errorf("deleting objects in %s: %w", path, err)
|
||||||
}
|
}
|
||||||
|
@ -198,7 +197,7 @@ func Fetch[T APIObject](ctx context.Context, c *Client, obj T) (T, error) {
|
||||||
Key: ptr(obj.JSONPath()),
|
Key: ptr(obj.JSONPath()),
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Logger.Debugf("Fetching %T from s3: %s", obj, obj.JSONPath())
|
c.Logger.Debug(fmt.Sprintf("Fetching %T from s3: %s", obj, obj.JSONPath()))
|
||||||
out, err := c.s3Client.GetObject(ctx, in)
|
out, err := c.s3Client.GetObject(ctx, in)
|
||||||
var noSuchkey *s3types.NoSuchKey
|
var noSuchkey *s3types.NoSuchKey
|
||||||
if errors.As(err, &noSuchkey) {
|
if errors.As(err, &noSuchkey) {
|
||||||
|
@ -232,7 +231,7 @@ func Update(ctx context.Context, c *Client, obj APIObject) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.DryRun {
|
if c.DryRun {
|
||||||
c.Logger.With(zap.String("bucket", c.bucket), zap.String("key", obj.JSONPath()), zap.String("body", string(rawJSON))).Debugf("DryRun: s3 put object")
|
c.Logger.With(slog.String("bucket", c.bucket), slog.String("key", obj.JSONPath()), slog.String("body", string(rawJSON))).Debug("DryRun: s3 put object")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +243,7 @@ func Update(ctx context.Context, c *Client, obj APIObject) error {
|
||||||
|
|
||||||
c.dirtyPaths = append(c.dirtyPaths, "/"+obj.JSONPath())
|
c.dirtyPaths = append(c.dirtyPaths, "/"+obj.JSONPath())
|
||||||
|
|
||||||
c.Logger.Debugf("Uploading %T to s3: %v", obj, obj.JSONPath())
|
c.Logger.Debug(fmt.Sprintf("Uploading %T to s3: %v", obj, obj.JSONPath()))
|
||||||
if _, err := c.Upload(ctx, in); err != nil {
|
if _, err := c.Upload(ctx, in); err != nil {
|
||||||
return fmt.Errorf("uploading %T: %w", obj, err)
|
return fmt.Errorf("uploading %T: %w", obj, err)
|
||||||
}
|
}
|
||||||
|
@ -307,7 +306,7 @@ func Delete(ctx context.Context, c *Client, obj APIObject) error {
|
||||||
Key: ptr(obj.JSONPath()),
|
Key: ptr(obj.JSONPath()),
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Logger.Debugf("Deleting %T from s3: %s", obj, obj.JSONPath())
|
c.Logger.Debug(fmt.Sprintf("Deleting %T from s3: %s", obj, obj.JSONPath()))
|
||||||
if _, err := c.DeleteObject(ctx, in); err != nil {
|
if _, err := c.DeleteObject(ctx, in); err != nil {
|
||||||
return fmt.Errorf("deleting s3 object at %s: %w", obj.JSONPath(), err)
|
return fmt.Errorf("deleting s3 object at %s: %w", obj.JSONPath(), err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ go_library(
|
||||||
"//internal/api/client",
|
"//internal/api/client",
|
||||||
"//internal/api/fetcher",
|
"//internal/api/fetcher",
|
||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/logger",
|
|
||||||
"@org_golang_x_mod//semver",
|
"@org_golang_x_mod//semver",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue