feat: use SSH host certificates (#3786)

This commit is contained in:
miampf 2025-07-01 12:47:04 +02:00 committed by GitHub
parent 95f17a6d06
commit 7ea5c41f9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 706 additions and 117 deletions

View file

@ -13,11 +13,13 @@ import (
"fmt"
"log/slog"
"net"
"strings"
"time"
"github.com/edgelesssys/constellation/v2/internal/attestation"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/crypto"
"github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/grpc/grpclog"
"github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versions/components"
@ -40,6 +42,7 @@ type Server struct {
dataKeyGetter dataKeyGetter
ca certificateAuthority
kubeClient kubeClient
fileHandler file.Handler
joinproto.UnimplementedAPIServer
}
@ -47,6 +50,7 @@ type Server struct {
func New(
measurementSalt []byte, ca certificateAuthority,
joinTokenGetter joinTokenGetter, dataKeyGetter dataKeyGetter, kubeClient kubeClient, log *slog.Logger,
fileHandler file.Handler,
) (*Server, error) {
return &Server{
measurementSalt: measurementSalt,
@ -55,6 +59,7 @@ func New(
dataKeyGetter: dataKeyGetter,
ca: ca,
kubeClient: kubeClient,
fileHandler: fileHandler,
}, nil
}
@ -114,6 +119,25 @@ func (s *Server) IssueJoinTicket(ctx context.Context, req *joinproto.IssueJoinTi
return nil, status.Errorf(codes.Internal, "generating ssh emergency CA key: %s", err)
}
principalList := req.HostCertificatePrincipals
additionalPrincipals, err := s.fileHandler.Read(constants.SSHAdditionalPrincipalsPath)
if err != nil {
log.With(slog.Any("error", err)).Error("Failed to read additional principals file")
return nil, status.Errorf(codes.Internal, "reading additional principals file: %s", err)
}
principalList = append(principalList, strings.Split(string(additionalPrincipals), ",")...)
publicKey, err := ssh.ParsePublicKey(req.HostPublicKey)
if err != nil {
log.With(slog.Any("error", err)).Error("Failed to parse host public key")
return nil, status.Errorf(codes.Internal, "unmarshalling host public key: %s", err)
}
hostCertificate, err := crypto.GenerateSSHHostCertificate(principalList, publicKey, ca)
if err != nil {
log.With(slog.Any("error", err)).Error("Failed to generate and sign SSH host key")
return nil, status.Errorf(codes.Internal, "generating and signing SSH host key: %s", err)
}
log.Info("Creating Kubernetes join token")
kubeArgs, err := s.joinTokenGetter.GetJoinToken(constants.KubernetesJoinTokenTTL)
if err != nil {
@ -182,6 +206,7 @@ func (s *Server) IssueJoinTicket(ctx context.Context, req *joinproto.IssueJoinTi
ControlPlaneFiles: controlPlaneFiles,
KubernetesComponents: components,
AuthorizedCaPublicKey: ssh.MarshalAuthorizedKey(ca.PublicKey()),
HostCertificate: ssh.MarshalAuthorizedKey(hostCertificate),
}, nil
}