feat: add security state resource

Add security state resource that describes the state of Talos SecureBoot
and PCR signing key fingerprints.

The UKI fingerprint is currently not populated.

Fixes: #7514

Signed-off-by: Noel Georgi <git@frezbo.dev>
This commit is contained in:
Noel Georgi 2023-07-28 21:06:52 +05:30
parent 209c34801e
commit 68e6b98f7d
No known key found for this signature in database
GPG Key ID: 21A9F444075C9E36
12 changed files with 547 additions and 25 deletions

View File

@ -85,6 +85,13 @@ message PlatformMetadataSpec {
bool spot = 8;
}
// SecurityStateSpec describes the security state resource properties.
message SecurityStateSpec {
bool secure_boot = 1;
string uki_signing_key_fingerprint = 2;
string pcr_signing_key_fingerprint = 3;
}
// UnmetCondition is a failure which prevents machine from being ready at the stage.
message UnmetCondition {
string name = 1;

View File

@ -325,6 +325,8 @@ function validate_rlimit_nofile {
function validate_booted_secureboot {
${TALOSCTL} dmesg | grep "Secure boot enabled"
${TALOSCTL} get securitystate -o json
${TALOSCTL} get securitystate -o json | jq -e '.spec.secureBoot == true'
}
function install_and_run_cilium_cni_tests {

View File

@ -0,0 +1,110 @@
// 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/foxboron/go-uefi/efi"
"go.uber.org/zap"
"github.com/siderolabs/talos/pkg/machinery/constants"
runtimeres "github.com/siderolabs/talos/pkg/machinery/resources/runtime"
)
// SecurityStateController is a controller that updates the security state of Talos.
type SecurityStateController struct{}
// 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 nil
}
// 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 {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
var secureBootState bool
if efi.GetSecureBoot() && !efi.GetSetupMode() {
secureBootState = true
}
if err := safe.WriterModify(ctx, r, runtimeres.NewSecurityStateSpec(runtimeres.NamespaceName), func(state *runtimeres.SecurityState) error {
state.TypedSpec().SecureBoot = secureBootState
return nil
}); err != nil {
return err
}
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,
}
if err := safe.WriterModify(ctx, r, runtimeres.NewSecurityStateSpec(runtimeres.NamespaceName), func(state *runtimeres.SecurityState) error {
state.TypedSpec().PCRSigningKeyFingerprint = x509CertFingerprint(cert)
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()
}

View File

@ -278,6 +278,7 @@ func (ctrl *Controller) Run(ctx context.Context, drainer *runtime.Drainer) error
&runtimecontrollers.MachineStatusPublisherController{
V1Alpha1Events: ctrl.v1alpha1Runtime.Events(),
},
&runtimecontrollers.SecurityStateController{},
&secrets.APICertSANsController{},
&secrets.APIController{},
&secrets.EtcdController{},

View File

@ -182,6 +182,7 @@ func NewState() (*State, error) {
&runtime.MetaKey{},
&runtime.MountStatus{},
&runtime.PlatformMetadata{},
&runtime.SecurityState{},
&secrets.API{},
&secrets.CertSAN{},
&secrets.Etcd{},

View File

@ -744,6 +744,70 @@ func (x *PlatformMetadataSpec) GetSpot() bool {
return false
}
// SecurityStateSpec describes the security state resource properties.
type SecurityStateSpec struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
SecureBoot bool `protobuf:"varint,1,opt,name=secure_boot,json=secureBoot,proto3" json:"secure_boot,omitempty"`
UkiSigningKeyFingerprint string `protobuf:"bytes,2,opt,name=uki_signing_key_fingerprint,json=ukiSigningKeyFingerprint,proto3" json:"uki_signing_key_fingerprint,omitempty"`
PcrSigningKeyFingerprint string `protobuf:"bytes,3,opt,name=pcr_signing_key_fingerprint,json=pcrSigningKeyFingerprint,proto3" json:"pcr_signing_key_fingerprint,omitempty"`
}
func (x *SecurityStateSpec) Reset() {
*x = SecurityStateSpec{}
if protoimpl.UnsafeEnabled {
mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SecurityStateSpec) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SecurityStateSpec) ProtoMessage() {}
func (x *SecurityStateSpec) ProtoReflect() protoreflect.Message {
mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SecurityStateSpec.ProtoReflect.Descriptor instead.
func (*SecurityStateSpec) Descriptor() ([]byte, []int) {
return file_resource_definitions_runtime_runtime_proto_rawDescGZIP(), []int{12}
}
func (x *SecurityStateSpec) GetSecureBoot() bool {
if x != nil {
return x.SecureBoot
}
return false
}
func (x *SecurityStateSpec) GetUkiSigningKeyFingerprint() string {
if x != nil {
return x.UkiSigningKeyFingerprint
}
return ""
}
func (x *SecurityStateSpec) GetPcrSigningKeyFingerprint() string {
if x != nil {
return x.PcrSigningKeyFingerprint
}
return ""
}
// UnmetCondition is a failure which prevents machine from being ready at the stage.
type UnmetCondition struct {
state protoimpl.MessageState
@ -757,7 +821,7 @@ type UnmetCondition struct {
func (x *UnmetCondition) Reset() {
*x = UnmetCondition{}
if protoimpl.UnsafeEnabled {
mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[12]
mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -770,7 +834,7 @@ func (x *UnmetCondition) String() string {
func (*UnmetCondition) ProtoMessage() {}
func (x *UnmetCondition) ProtoReflect() protoreflect.Message {
mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[12]
mi := &file_resource_definitions_runtime_runtime_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -783,7 +847,7 @@ func (x *UnmetCondition) ProtoReflect() protoreflect.Message {
// Deprecated: Use UnmetCondition.ProtoReflect.Descriptor instead.
func (*UnmetCondition) Descriptor() ([]byte, []int) {
return file_resource_definitions_runtime_runtime_proto_rawDescGZIP(), []int{12}
return file_resource_definitions_runtime_runtime_proto_rawDescGZIP(), []int{13}
}
func (x *UnmetCondition) GetName() string {
@ -895,16 +959,28 @@ var file_resource_definitions_runtime_runtime_proto_rawDesc = []byte{
0x63, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72,
0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x70, 0x6f, 0x74, 0x18, 0x08, 0x20,
0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x70, 0x6f, 0x74, 0x22, 0x3c, 0x0a, 0x0e, 0x55, 0x6e, 0x6d,
0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73,
0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, 0x75,
0x6e, 0x74, 0x69, 0x6d, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x70, 0x6f, 0x74, 0x22, 0xb2, 0x01, 0x0a, 0x11, 0x53, 0x65,
0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12,
0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x74, 0x18, 0x01,
0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x42, 0x6f, 0x6f, 0x74,
0x12, 0x3d, 0x0a, 0x1b, 0x75, 0x6b, 0x69, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f,
0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x75, 0x6b, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e,
0x67, 0x4b, 0x65, 0x79, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12,
0x3d, 0x0a, 0x1b, 0x70, 0x63, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6b,
0x65, 0x79, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x70, 0x63, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67,
0x4b, 0x65, 0x79, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x3c,
0x0a, 0x0e, 0x55, 0x6e, 0x6d, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x4c, 0x5a, 0x4a,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x64, 0x65, 0x72,
0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
@ -919,7 +995,7 @@ func file_resource_definitions_runtime_runtime_proto_rawDescGZIP() []byte {
return file_resource_definitions_runtime_runtime_proto_rawDescData
}
var file_resource_definitions_runtime_runtime_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_resource_definitions_runtime_runtime_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_resource_definitions_runtime_runtime_proto_goTypes = []interface{}{
(*DevicesStatusSpec)(nil), // 0: talos.resource.definitions.runtime.DevicesStatusSpec
(*EventSinkConfigSpec)(nil), // 1: talos.resource.definitions.runtime.EventSinkConfigSpec
@ -933,17 +1009,18 @@ var file_resource_definitions_runtime_runtime_proto_goTypes = []interface{}{
(*MetaKeySpec)(nil), // 9: talos.resource.definitions.runtime.MetaKeySpec
(*MountStatusSpec)(nil), // 10: talos.resource.definitions.runtime.MountStatusSpec
(*PlatformMetadataSpec)(nil), // 11: talos.resource.definitions.runtime.PlatformMetadataSpec
(*UnmetCondition)(nil), // 12: talos.resource.definitions.runtime.UnmetCondition
(*common.URL)(nil), // 13: common.URL
(enums.RuntimeMachineStage)(0), // 14: talos.resource.definitions.enums.RuntimeMachineStage
(*common.NetIP)(nil), // 15: common.NetIP
(*SecurityStateSpec)(nil), // 12: talos.resource.definitions.runtime.SecurityStateSpec
(*UnmetCondition)(nil), // 13: talos.resource.definitions.runtime.UnmetCondition
(*common.URL)(nil), // 14: common.URL
(enums.RuntimeMachineStage)(0), // 15: talos.resource.definitions.enums.RuntimeMachineStage
(*common.NetIP)(nil), // 16: common.NetIP
}
var file_resource_definitions_runtime_runtime_proto_depIdxs = []int32{
13, // 0: talos.resource.definitions.runtime.KmsgLogConfigSpec.destinations:type_name -> common.URL
14, // 1: talos.resource.definitions.runtime.MachineStatusSpec.stage:type_name -> talos.resource.definitions.enums.RuntimeMachineStage
14, // 0: talos.resource.definitions.runtime.KmsgLogConfigSpec.destinations:type_name -> common.URL
15, // 1: talos.resource.definitions.runtime.MachineStatusSpec.stage:type_name -> talos.resource.definitions.enums.RuntimeMachineStage
7, // 2: talos.resource.definitions.runtime.MachineStatusSpec.status:type_name -> talos.resource.definitions.runtime.MachineStatusStatus
12, // 3: talos.resource.definitions.runtime.MachineStatusStatus.unmet_conditions:type_name -> talos.resource.definitions.runtime.UnmetCondition
15, // 4: talos.resource.definitions.runtime.MaintenanceServiceConfigSpec.reachable_addresses:type_name -> common.NetIP
13, // 3: talos.resource.definitions.runtime.MachineStatusStatus.unmet_conditions:type_name -> talos.resource.definitions.runtime.UnmetCondition
16, // 4: talos.resource.definitions.runtime.MaintenanceServiceConfigSpec.reachable_addresses:type_name -> common.NetIP
5, // [5:5] is the sub-list for method output_type
5, // [5:5] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
@ -1102,6 +1179,18 @@ func file_resource_definitions_runtime_runtime_proto_init() {
}
}
file_resource_definitions_runtime_runtime_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SecurityStateSpec); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_resource_definitions_runtime_runtime_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UnmetCondition); i {
case 0:
return &v.state
@ -1120,7 +1209,7 @@ func file_resource_definitions_runtime_runtime_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_resource_definitions_runtime_runtime_proto_rawDesc,
NumEnums: 0,
NumMessages: 13,
NumMessages: 14,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -691,6 +691,63 @@ func (m *PlatformMetadataSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error)
return len(dAtA) - i, nil
}
func (m *SecurityStateSpec) MarshalVT() (dAtA []byte, err error) {
if m == nil {
return nil, nil
}
size := m.SizeVT()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *SecurityStateSpec) MarshalToVT(dAtA []byte) (int, error) {
size := m.SizeVT()
return m.MarshalToSizedBufferVT(dAtA[:size])
}
func (m *SecurityStateSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
if m == nil {
return 0, nil
}
i := len(dAtA)
_ = i
var l int
_ = l
if m.unknownFields != nil {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if len(m.PcrSigningKeyFingerprint) > 0 {
i -= len(m.PcrSigningKeyFingerprint)
copy(dAtA[i:], m.PcrSigningKeyFingerprint)
i = encodeVarint(dAtA, i, uint64(len(m.PcrSigningKeyFingerprint)))
i--
dAtA[i] = 0x1a
}
if len(m.UkiSigningKeyFingerprint) > 0 {
i -= len(m.UkiSigningKeyFingerprint)
copy(dAtA[i:], m.UkiSigningKeyFingerprint)
i = encodeVarint(dAtA, i, uint64(len(m.UkiSigningKeyFingerprint)))
i--
dAtA[i] = 0x12
}
if m.SecureBoot {
i--
if m.SecureBoot {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func (m *UnmetCondition) MarshalVT() (dAtA []byte, err error) {
if m == nil {
return nil, nil
@ -1004,6 +1061,27 @@ func (m *PlatformMetadataSpec) SizeVT() (n int) {
return n
}
func (m *SecurityStateSpec) SizeVT() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.SecureBoot {
n += 2
}
l = len(m.UkiSigningKeyFingerprint)
if l > 0 {
n += 1 + l + sov(uint64(l))
}
l = len(m.PcrSigningKeyFingerprint)
if l > 0 {
n += 1 + l + sov(uint64(l))
}
n += len(m.unknownFields)
return n
}
func (m *UnmetCondition) SizeVT() (n int) {
if m == nil {
return 0
@ -2541,6 +2619,141 @@ func (m *PlatformMetadataSpec) UnmarshalVT(dAtA []byte) error {
}
return nil
}
func (m *SecurityStateSpec) UnmarshalVT(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: SecurityStateSpec: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: SecurityStateSpec: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field SecureBoot", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.SecureBoot = bool(v != 0)
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field UkiSigningKeyFingerprint", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLength
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.UkiSigningKeyFingerprint = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PcrSigningKeyFingerprint", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLength
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.PcrSigningKeyFingerprint = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skip(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLength
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *UnmetCondition) UnmarshalVT(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0

View File

@ -2,7 +2,7 @@
// 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/.
// Code generated by "deep-copy -type DevicesStatusSpec -type EventSinkConfigSpec -type KernelModuleSpecSpec -type KernelParamSpecSpec -type KernelParamStatusSpec -type KmsgLogConfigSpec -type MaintenanceServiceConfigSpec -type MaintenanceServiceRequestSpec -type MachineStatusSpec -type MetaKeySpec -type MountStatusSpec -type PlatformMetadataSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go ."; DO NOT EDIT.
// Code generated by "deep-copy -type DevicesStatusSpec -type EventSinkConfigSpec -type KernelModuleSpecSpec -type KernelParamSpecSpec -type KernelParamStatusSpec -type KmsgLogConfigSpec -type MaintenanceServiceConfigSpec -type MaintenanceServiceRequestSpec -type MachineStatusSpec -type MetaKeySpec -type MountStatusSpec -type PlatformMetadataSpec -type SecurityStateSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go ."; DO NOT EDIT.
package runtime
@ -112,3 +112,9 @@ func (o PlatformMetadataSpec) DeepCopy() PlatformMetadataSpec {
var cp PlatformMetadataSpec = o
return cp
}
// DeepCopy generates a deep copy of SecurityStateSpec.
func (o SecurityStateSpec) DeepCopy() SecurityStateSpec {
var cp SecurityStateSpec = o
return cp
}

View File

@ -5,4 +5,4 @@
package runtime
//nolint:lll
//go:generate deep-copy -type DevicesStatusSpec -type EventSinkConfigSpec -type KernelModuleSpecSpec -type KernelParamSpecSpec -type KernelParamStatusSpec -type KmsgLogConfigSpec -type MaintenanceServiceConfigSpec -type MaintenanceServiceRequestSpec -type MachineStatusSpec -type MetaKeySpec -type MountStatusSpec -type PlatformMetadataSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go .
//go:generate deep-copy -type DevicesStatusSpec -type EventSinkConfigSpec -type KernelModuleSpecSpec -type KernelParamSpecSpec -type KernelParamStatusSpec -type KmsgLogConfigSpec -type MaintenanceServiceConfigSpec -type MaintenanceServiceRequestSpec -type MachineStatusSpec -type MetaKeySpec -type MountStatusSpec -type PlatformMetadataSpec -type SecurityStateSpec -header-file ../../../../hack/boilerplate.txt -o deep_copy.generated.go .

View File

@ -38,6 +38,7 @@ func TestRegisterResource(t *testing.T) {
&runtime.MetaKey{},
&runtime.MountStatus{},
&runtime.PlatformMetadata{},
&runtime.SecurityState{},
} {
assert.NoError(t, resourceRegistry.Register(ctx, resource))
}

View File

@ -0,0 +1,74 @@
// 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 (
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/resource/meta"
"github.com/cosi-project/runtime/pkg/resource/protobuf"
"github.com/cosi-project/runtime/pkg/resource/typed"
"github.com/siderolabs/talos/pkg/machinery/proto"
)
// SecurityStateType is the type of the security state resource.
const SecurityStateType = resource.Type("SecurityStates.talos.dev")
// SecurityStateID is the ID of the security state resource.
const SecurityStateID = resource.ID("securitystate")
// SecurityState is the security state resource.
type SecurityState = typed.Resource[SecurityStateSpec, SecurityStateExtension]
// SecurityStateSpec describes the security state resource properties.
//
//gotagsrewrite:gen
type SecurityStateSpec struct {
SecureBoot bool `yaml:"secureBoot" protobuf:"1"`
UKISigningKeyFingerprint string `yaml:"ukiSigningKeyFingerprint,omitempty" protobuf:"2"`
PCRSigningKeyFingerprint string `yaml:"pcrSigningKeyFingerprint,omitempty" protobuf:"3"`
}
// NewSecurityStateSpec initializes a security state resource.
func NewSecurityStateSpec(namespace resource.Namespace) *SecurityState {
return typed.NewResource[SecurityStateSpec, SecurityStateExtension](
resource.NewMetadata(namespace, SecurityStateType, SecurityStateID, resource.VersionUndefined),
SecurityStateSpec{},
)
}
// SecurityStateExtension provides auxiliary methods for SecurityState.
type SecurityStateExtension struct{}
// ResourceDefinition implements [typed.Extension] interface.
func (SecurityStateExtension) ResourceDefinition() meta.ResourceDefinitionSpec {
return meta.ResourceDefinitionSpec{
Type: SecurityStateType,
DefaultNamespace: NamespaceName,
PrintColumns: []meta.PrintColumn{
{
Name: "SecureBoot",
JSONPath: `{.secureBoot}`,
},
{
Name: "UKISigningKeyFingerprint",
JSONPath: `{.ukiSigningKeyFingerprint}`,
},
{
Name: "PCRSigningKeyFingerprint",
JSONPath: `{.pcrSigningKeyFingerprint}`,
},
},
}
}
func init() {
proto.RegisterDefaultTypes()
err := protobuf.RegisterDynamic[SecurityStateSpec](SecurityStateType, &SecurityState{})
if err != nil {
panic(err)
}
}

View File

@ -200,6 +200,7 @@ description: Talos gRPC API reference.
- [MetaKeySpec](#talos.resource.definitions.runtime.MetaKeySpec)
- [MountStatusSpec](#talos.resource.definitions.runtime.MountStatusSpec)
- [PlatformMetadataSpec](#talos.resource.definitions.runtime.PlatformMetadataSpec)
- [SecurityStateSpec](#talos.resource.definitions.runtime.SecurityStateSpec)
- [UnmetCondition](#talos.resource.definitions.runtime.UnmetCondition)
- [resource/definitions/secrets/secrets.proto](#resource/definitions/secrets/secrets.proto)
@ -3643,6 +3644,23 @@ PlatformMetadataSpec describes platform metadata properties.
<a name="talos.resource.definitions.runtime.SecurityStateSpec"></a>
### SecurityStateSpec
SecurityStateSpec describes the security state resource properties.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| secure_boot | [bool](#bool) | | |
| uki_signing_key_fingerprint | [string](#string) | | |
| pcr_signing_key_fingerprint | [string](#string) | | |
<a name="talos.resource.definitions.runtime.UnmetCondition"></a>
### UnmetCondition