fix: rewrite encryption system information flow
Pass getter to the key handler instead of already fetched node uuid. Signed-off-by: Artem Chernyshev <artem.chernyshev@talos-systems.com>
This commit is contained in:
parent
3206db5289
commit
cb226eec46
@ -15,7 +15,6 @@ import (
|
||||
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/safe"
|
||||
"github.com/cosi-project/runtime/pkg/state"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
|
||||
@ -227,12 +226,7 @@ func (r *Runtime) IsBootstrapAllowed() bool {
|
||||
|
||||
// GetSystemInformation returns system information resource if it exists.
|
||||
func (r *Runtime) GetSystemInformation(ctx context.Context) (*hardware.SystemInformation, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Second*2)
|
||||
defer cancel()
|
||||
|
||||
return safe.StateWatchFor[*hardware.SystemInformation](ctx, r.State().V1Alpha2().Resources(), hardware.NewSystemInformation(hardware.SystemInformationID).Metadata(),
|
||||
state.WithEventTypes(state.Created, state.Updated),
|
||||
)
|
||||
return safe.StateGet[*hardware.SystemInformation](ctx, r.State().V1Alpha2().Resources(), hardware.NewSystemInformation(hardware.SystemInformationID).Metadata())
|
||||
}
|
||||
|
||||
// atomicInterface is a typed wrapper around atomic.Value. It's only useful for storing the interfaces, because
|
||||
|
@ -2115,7 +2115,7 @@ func MountStatePartition(seq runtime.Sequence, _ any) (runtime.TaskExecutionFunc
|
||||
}
|
||||
|
||||
if encryption != nil {
|
||||
opts = append(opts, mount.WithEncryptionConfig(encryption))
|
||||
opts = append(opts, mount.WithEncryptionConfig(encryption), mount.WithSystemInformationGetter(r.GetSystemInformation))
|
||||
}
|
||||
|
||||
return mount.SystemPartitionMount(ctx, r, logger, constants.StatePartitionLabel, opts...)
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"github.com/siderolabs/go-blockdevice/blockdevice/partition/gpt"
|
||||
"github.com/siderolabs/go-retry/retry"
|
||||
|
||||
"github.com/siderolabs/talos/internal/pkg/encryption/helpers"
|
||||
"github.com/siderolabs/talos/internal/pkg/encryption/keys"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/config"
|
||||
)
|
||||
@ -33,7 +34,7 @@ const (
|
||||
)
|
||||
|
||||
// NewHandler creates new Handler.
|
||||
func NewHandler(device *blockdevice.BlockDevice, partition *gpt.Partition, encryptionConfig config.Encryption, nodeParams NodeParams) (*Handler, error) {
|
||||
func NewHandler(device *blockdevice.BlockDevice, partition *gpt.Partition, encryptionConfig config.Encryption, getSystemInformation helpers.SystemInformationGetter) (*Handler, error) {
|
||||
var provider encryption.Provider
|
||||
|
||||
switch encryptionConfig.Kind() {
|
||||
@ -71,23 +72,23 @@ func NewHandler(device *blockdevice.BlockDevice, partition *gpt.Partition, encry
|
||||
}
|
||||
|
||||
return &Handler{
|
||||
device: device,
|
||||
partition: partition,
|
||||
encryptionConfig: encryptionConfig,
|
||||
encryptionProvider: provider,
|
||||
nodeParams: nodeParams,
|
||||
device: device,
|
||||
partition: partition,
|
||||
encryptionConfig: encryptionConfig,
|
||||
encryptionProvider: provider,
|
||||
getSystemInformation: getSystemInformation,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Handler reads encryption config, creates appropriate
|
||||
// encryption provider, handles encrypted partition open and close.
|
||||
type Handler struct {
|
||||
device *blockdevice.BlockDevice
|
||||
partition *gpt.Partition
|
||||
encryptionConfig config.Encryption
|
||||
encryptionProvider encryption.Provider
|
||||
nodeParams NodeParams
|
||||
encryptedPath string
|
||||
device *blockdevice.BlockDevice
|
||||
partition *gpt.Partition
|
||||
encryptionConfig config.Encryption
|
||||
encryptionProvider encryption.Provider
|
||||
getSystemInformation helpers.SystemInformationGetter
|
||||
encryptedPath string
|
||||
}
|
||||
|
||||
// Open encrypted partition.
|
||||
@ -337,7 +338,7 @@ func (h *Handler) initKeyHandlers(encryptionConfig config.Encryption, partition
|
||||
handlers := make([]keys.Handler, 0, len(encryptionConfig.Keys()))
|
||||
|
||||
for _, cfg := range encryptionConfig.Keys() {
|
||||
handler, err := keys.NewHandler(cfg, keys.WithPartitionLabel(partition.Name), keys.WithNodeUUID(h.nodeParams.UUID))
|
||||
handler, err := keys.NewHandler(cfg, keys.WithPartitionLabel(partition.Name), keys.WithSystemInformationGetter(h.getSystemInformation))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
15
internal/pkg/encryption/helpers/helpers.go
Normal file
15
internal/pkg/encryption/helpers/helpers.go
Normal file
@ -0,0 +1,15 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package helpers defines encryption handlers.
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/hardware"
|
||||
)
|
||||
|
||||
// SystemInformationGetter defines the closure which can be used in key handlers to get the node UUID.
|
||||
type SystemInformationGetter func(context.Context) (*hardware.SystemInformation, error)
|
@ -15,7 +15,7 @@ import (
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/config"
|
||||
)
|
||||
|
||||
var errNoNodeUUID = fmt.Errorf("the node UUID is not set")
|
||||
var errNoSystemInfoGetter = fmt.Errorf("the UUID getter is not set")
|
||||
|
||||
// NewHandler key using provided config.
|
||||
func NewHandler(cfg config.EncryptionKey, options ...KeyOption) (Handler, error) {
|
||||
@ -35,17 +35,17 @@ func NewHandler(cfg config.EncryptionKey, options ...KeyOption) (Handler, error)
|
||||
|
||||
return NewStaticKeyHandler(key, k), nil
|
||||
case cfg.NodeID() != nil:
|
||||
if opts.NodeUUID == "" {
|
||||
return nil, fmt.Errorf("failed to create nodeUUID key handler at slot %d: %w", cfg.Slot(), errNoNodeUUID)
|
||||
if opts.GetSystemInformation == nil {
|
||||
return nil, fmt.Errorf("failed to create nodeUUID key handler at slot %d: %w", cfg.Slot(), errNoSystemInfoGetter)
|
||||
}
|
||||
|
||||
return NewNodeIDKeyHandler(key, opts.PartitionLabel, opts.NodeUUID), nil
|
||||
return NewNodeIDKeyHandler(key, opts.PartitionLabel, opts.GetSystemInformation), nil
|
||||
case cfg.KMS() != nil:
|
||||
if opts.NodeUUID == "" {
|
||||
return nil, fmt.Errorf("failed to create KMS key handler at slot %d: %w", cfg.Slot(), errNoNodeUUID)
|
||||
if opts.GetSystemInformation == nil {
|
||||
return nil, fmt.Errorf("failed to create KMS key handler at slot %d: %w", cfg.Slot(), errNoSystemInfoGetter)
|
||||
}
|
||||
|
||||
return NewKMSKeyHandler(key, cfg.KMS().Endpoint(), opts.NodeUUID)
|
||||
return NewKMSKeyHandler(key, cfg.KMS().Endpoint(), opts.GetSystemInformation)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("malformed config: no key handler can be created")
|
||||
|
@ -21,8 +21,8 @@ import (
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
"github.com/siderolabs/talos/internal/pkg/encryption/helpers"
|
||||
"github.com/siderolabs/talos/internal/pkg/endpoint"
|
||||
"github.com/siderolabs/talos/internal/pkg/smbios"
|
||||
)
|
||||
|
||||
// KMSToken is the userdata stored in the partition token metadata.
|
||||
@ -33,15 +33,16 @@ type KMSToken struct {
|
||||
// KMSKeyHandler seals token using KMS service.
|
||||
type KMSKeyHandler struct {
|
||||
KeyHandler
|
||||
kmsEndpoint string
|
||||
nodeUUID string
|
||||
kmsEndpoint string
|
||||
getSystemInfo helpers.SystemInformationGetter
|
||||
}
|
||||
|
||||
// NewKMSKeyHandler creates new KMSKeyHandler.
|
||||
func NewKMSKeyHandler(key KeyHandler, kmsEndpoint, nodeUUID string) (*KMSKeyHandler, error) {
|
||||
func NewKMSKeyHandler(key KeyHandler, kmsEndpoint string, getSystemInfo helpers.SystemInformationGetter) (*KMSKeyHandler, error) {
|
||||
return &KMSKeyHandler{
|
||||
KeyHandler: key,
|
||||
kmsEndpoint: kmsEndpoint,
|
||||
KeyHandler: key,
|
||||
kmsEndpoint: kmsEndpoint,
|
||||
getSystemInfo: getSystemInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -62,8 +63,13 @@ func (h *KMSKeyHandler) NewKey(ctx context.Context) (*encryption.Key, token.Toke
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
systemInformation, err := h.getSystemInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
resp, err := client.Seal(ctx, &kms.Request{
|
||||
NodeUuid: h.nodeUUID,
|
||||
NodeUuid: systemInformation.TypedSpec().UUID,
|
||||
Data: key,
|
||||
})
|
||||
if err != nil {
|
||||
@ -97,13 +103,13 @@ func (h *KMSKeyHandler) GetKey(ctx context.Context, t token.Token) (*encryption.
|
||||
|
||||
client := kms.NewKMSServiceClient(conn)
|
||||
|
||||
s, err := smbios.GetSMBIOSInfo()
|
||||
systemInformation, err := h.getSystemInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := client.Unseal(ctx, &kms.Request{
|
||||
NodeUuid: s.SystemInformation.UUID,
|
||||
NodeUuid: systemInformation.TypedSpec().UUID,
|
||||
Data: token.UserData.SealedData,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -10,6 +10,8 @@ import (
|
||||
|
||||
"github.com/siderolabs/go-blockdevice/blockdevice/encryption"
|
||||
"github.com/siderolabs/go-blockdevice/blockdevice/encryption/token"
|
||||
|
||||
"github.com/siderolabs/talos/internal/pkg/encryption/helpers"
|
||||
)
|
||||
|
||||
// NodeIDKeyHandler generates the key based on current node information
|
||||
@ -17,14 +19,15 @@ import (
|
||||
type NodeIDKeyHandler struct {
|
||||
KeyHandler
|
||||
partitionLabel string
|
||||
nodeUUID string
|
||||
getSystemInfo helpers.SystemInformationGetter
|
||||
}
|
||||
|
||||
// NewNodeIDKeyHandler creates new NodeIDKeyHandler.
|
||||
func NewNodeIDKeyHandler(key KeyHandler, partitionLabel, nodeUUID string) *NodeIDKeyHandler {
|
||||
func NewNodeIDKeyHandler(key KeyHandler, partitionLabel string, systemInfoGetter helpers.SystemInformationGetter) *NodeIDKeyHandler {
|
||||
return &NodeIDKeyHandler{
|
||||
KeyHandler: key,
|
||||
partitionLabel: partitionLabel,
|
||||
getSystemInfo: systemInfoGetter,
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,19 +39,26 @@ func (h *NodeIDKeyHandler) NewKey(ctx context.Context) (*encryption.Key, token.T
|
||||
}
|
||||
|
||||
// GetKey implements Handler interface.
|
||||
func (h *NodeIDKeyHandler) GetKey(context.Context, token.Token) (*encryption.Key, error) {
|
||||
if h.nodeUUID == "" {
|
||||
return nil, fmt.Errorf("machine UUID is not populated %s", h.nodeUUID)
|
||||
func (h *NodeIDKeyHandler) GetKey(ctx context.Context, _ token.Token) (*encryption.Key, error) {
|
||||
systemInformation, err := h.getSystemInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get UUID: %w", err)
|
||||
}
|
||||
|
||||
nodeUUID := systemInformation.TypedSpec().UUID
|
||||
|
||||
if nodeUUID == "" {
|
||||
return nil, fmt.Errorf("machine UUID is not populated %s", nodeUUID)
|
||||
}
|
||||
|
||||
// primitive entropy check
|
||||
counts := map[rune]int{}
|
||||
for _, s := range h.nodeUUID {
|
||||
for _, s := range nodeUUID {
|
||||
counts[s]++
|
||||
if counts[s] > len(h.nodeUUID)/2 {
|
||||
return nil, fmt.Errorf("machine UUID %s entropy check failed", h.nodeUUID)
|
||||
if counts[s] > len(nodeUUID)/2 {
|
||||
return nil, fmt.Errorf("machine UUID %s entropy check failed", nodeUUID)
|
||||
}
|
||||
}
|
||||
|
||||
return encryption.NewKey(h.slot, []byte(h.nodeUUID+h.partitionLabel)), nil
|
||||
return encryption.NewKey(h.slot, []byte(nodeUUID+h.partitionLabel)), nil
|
||||
}
|
||||
|
@ -4,13 +4,15 @@
|
||||
|
||||
package keys
|
||||
|
||||
import "github.com/siderolabs/talos/internal/pkg/encryption/helpers"
|
||||
|
||||
// KeyOption represents key option callback used in KeyHandler.GetKey func.
|
||||
type KeyOption func(o *KeyOptions) error
|
||||
|
||||
// KeyOptions set of options to be used in KeyHandler.GetKey func.
|
||||
type KeyOptions struct {
|
||||
PartitionLabel string
|
||||
NodeUUID string
|
||||
PartitionLabel string
|
||||
GetSystemInformation helpers.SystemInformationGetter
|
||||
}
|
||||
|
||||
// WithPartitionLabel passes the partition label to the key handler.
|
||||
@ -22,10 +24,10 @@ func WithPartitionLabel(label string) KeyOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithNodeUUID passes the node UUID to the key handler.
|
||||
func WithNodeUUID(uuid string) KeyOption {
|
||||
// WithSystemInformationGetter passes the node UUID to the key handler.
|
||||
func WithSystemInformationGetter(getter helpers.SystemInformationGetter) KeyOption {
|
||||
return func(o *KeyOptions) error {
|
||||
o.NodeUUID = uuid
|
||||
o.GetSystemInformation = getter
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ package mount
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/siderolabs/talos/internal/pkg/encryption"
|
||||
"github.com/siderolabs/talos/internal/pkg/encryption/helpers"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/config"
|
||||
)
|
||||
|
||||
@ -40,15 +40,15 @@ type Flags uint
|
||||
|
||||
// Options is the functional options struct.
|
||||
type Options struct {
|
||||
Loopback string
|
||||
Prefix string
|
||||
MountFlags Flags
|
||||
PreMountHooks []Hook
|
||||
PostUnmountHooks []Hook
|
||||
Encryption config.Encryption
|
||||
NodeParams encryption.NodeParams
|
||||
Logger *log.Logger
|
||||
ProjectQuota bool
|
||||
Loopback string
|
||||
Prefix string
|
||||
MountFlags Flags
|
||||
PreMountHooks []Hook
|
||||
PostUnmountHooks []Hook
|
||||
Encryption config.Encryption
|
||||
SystemInformationGetter helpers.SystemInformationGetter
|
||||
Logger *log.Logger
|
||||
ProjectQuota bool
|
||||
}
|
||||
|
||||
// Option is the functional option func.
|
||||
@ -113,10 +113,10 @@ func WithProjectQuota(enable bool) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithNodeParams node info used by the encryption handler.
|
||||
func WithNodeParams(params encryption.NodeParams) Option {
|
||||
// WithSystemInformationGetter the function to get system information on the node.
|
||||
func WithSystemInformationGetter(getter helpers.SystemInformationGetter) Option {
|
||||
return func(args *Options) {
|
||||
args.NodeParams = params
|
||||
args.SystemInformationGetter = getter
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ func SystemMountPointForLabel(ctx context.Context, device *blockdevice.BlockDevi
|
||||
device,
|
||||
part,
|
||||
o.Encryption,
|
||||
o.NodeParams,
|
||||
o.SystemInformationGetter,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -123,7 +123,7 @@ func SystemMountPointForLabel(ctx context.Context, device *blockdevice.BlockDevi
|
||||
path string
|
||||
)
|
||||
|
||||
if path, err = encryptionHandler.Open(context.TODO()); err != nil {
|
||||
if path, err = encryptionHandler.Open(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -189,27 +189,13 @@ func SystemPartitionMount(ctx context.Context, r runtime.Runtime, logger *log.Lo
|
||||
return fmt.Errorf("failed to find device with partition labeled %s", label)
|
||||
}
|
||||
|
||||
systemInformation, err := r.GetSystemInformation(ctx)
|
||||
if err != nil && !errors.Is(err, context.Canceled) && state.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if systemInformation != nil {
|
||||
opts = append(opts, WithNodeParams(encryption.NodeParams{
|
||||
UUID: systemInformation.TypedSpec().UUID,
|
||||
}))
|
||||
}
|
||||
|
||||
var encrypted bool
|
||||
|
||||
if r.Config() != nil && r.Config().Machine() != nil {
|
||||
encryptionConfig := r.Config().Machine().SystemDiskEncryption().Get(label)
|
||||
|
||||
if encryptionConfig != nil {
|
||||
encrypted = true
|
||||
|
||||
opts = append(opts,
|
||||
WithEncryptionConfig(encryptionConfig),
|
||||
WithSystemInformationGetter(r.GetSystemInformation),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -239,6 +225,9 @@ func SystemPartitionMount(ctx context.Context, r runtime.Runtime, logger *log.Lo
|
||||
return
|
||||
}
|
||||
|
||||
o := NewDefaultOptions(opts...)
|
||||
encrypted := o.Encryption != nil
|
||||
|
||||
// record mount as the resource
|
||||
mountStatus := runtimeres.NewMountStatus(v1alpha1.NamespaceName, label)
|
||||
mountStatus.TypedSpec().Source = mountpoint.Source()
|
||||
|
Loading…
Reference in New Issue
Block a user