mirror of
https://github.com/siderolabs/talos.git
synced 2025-10-30 16:01:12 +01:00
Drop startup/rand.go, as since Go 1.20 `rand.Seed` is done automatically. Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
136 lines
3.5 KiB
Go
136 lines
3.5 KiB
Go
// 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 runtime
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/sha256"
|
|
"crypto/x509"
|
|
"encoding/hex"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/cosi-project/runtime/pkg/controller"
|
|
"github.com/cosi-project/runtime/pkg/safe"
|
|
"github.com/cosi-project/runtime/pkg/state"
|
|
"github.com/foxboron/go-uefi/efi"
|
|
"go.uber.org/zap"
|
|
|
|
machineruntime "github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
|
|
"github.com/siderolabs/talos/pkg/machinery/constants"
|
|
runtimeres "github.com/siderolabs/talos/pkg/machinery/resources/runtime"
|
|
"github.com/siderolabs/talos/pkg/machinery/resources/v1alpha1"
|
|
)
|
|
|
|
// SecurityStateController is a controller that updates the security state of Talos.
|
|
type SecurityStateController struct {
|
|
V1Alpha1Mode machineruntime.Mode
|
|
}
|
|
|
|
// Name implements controller.Controller interface.
|
|
func (ctrl *SecurityStateController) Name() string {
|
|
return "runtime.SecurityStateController"
|
|
}
|
|
|
|
// Inputs implements controller.Controller interface.
|
|
func (ctrl *SecurityStateController) Inputs() []controller.Input {
|
|
return []controller.Input{
|
|
{
|
|
Namespace: v1alpha1.NamespaceName,
|
|
Type: v1alpha1.ServiceType,
|
|
Kind: controller.OutputExclusive,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Outputs implements controller.Controller interface.
|
|
func (ctrl *SecurityStateController) Outputs() []controller.Output {
|
|
return []controller.Output{
|
|
{
|
|
Type: runtimeres.SecurityStateType,
|
|
Kind: controller.OutputExclusive,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Run implements controller.Controller interface.
|
|
//
|
|
//nolint:gocyclo
|
|
func (ctrl *SecurityStateController) Run(ctx context.Context, r controller.Runtime, logger *zap.Logger) error {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil
|
|
case <-r.EventCh():
|
|
}
|
|
|
|
// wait for the `machined` service to start, as by that time initial mounts will be done
|
|
_, err := safe.ReaderGetByID[*v1alpha1.Service](ctx, r, "machined")
|
|
if err != nil {
|
|
if state.IsNotFoundError(err) {
|
|
continue
|
|
}
|
|
|
|
return fmt.Errorf("failed to get machined state: %w", err)
|
|
}
|
|
|
|
var (
|
|
secureBootState bool
|
|
pcrSigningKeyFingerprint string
|
|
)
|
|
|
|
// in container mode, never populate the fields
|
|
if ctrl.V1Alpha1Mode != machineruntime.ModeContainer {
|
|
if efi.GetSecureBoot() && !efi.GetSetupMode() {
|
|
secureBootState = true
|
|
}
|
|
|
|
if pcrPublicKeyData, err := os.ReadFile(constants.PCRPublicKey); err == nil {
|
|
block, _ := pem.Decode(pcrPublicKeyData)
|
|
if block == nil {
|
|
return fmt.Errorf("failed to decode PEM block for PCR public key")
|
|
}
|
|
|
|
cert := x509.Certificate{
|
|
Raw: block.Bytes,
|
|
}
|
|
|
|
pcrSigningKeyFingerprint = x509CertFingerprint(cert)
|
|
}
|
|
}
|
|
|
|
if err := safe.WriterModify(ctx, r, runtimeres.NewSecurityStateSpec(runtimeres.NamespaceName), func(state *runtimeres.SecurityState) error {
|
|
state.TypedSpec().SecureBoot = secureBootState
|
|
state.TypedSpec().PCRSigningKeyFingerprint = pcrSigningKeyFingerprint
|
|
|
|
return nil
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
// terminating the controller here, as we need to only populate securitystate once
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func x509CertFingerprint(cert x509.Certificate) string {
|
|
hash := sha256.Sum256(cert.Raw)
|
|
|
|
var buf bytes.Buffer
|
|
|
|
for i, b := range hex.EncodeToString(hash[:]) {
|
|
if i > 0 && i%2 == 0 {
|
|
buf.WriteByte(':')
|
|
}
|
|
|
|
buf.WriteString(strings.ToUpper(string(b)))
|
|
}
|
|
|
|
return buf.String()
|
|
}
|