Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/resource/definitions/runtime/runtime.proto
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ message SecurityStateSpec {
talos.resource.definitions.enums.RuntimeSELinuxState se_linux_state = 4;
bool booted_with_uki = 5;
talos.resource.definitions.enums.RuntimeFIPSState fips_state = 6;
bool module_signature_enforced = 7;
}

// UniqueMachineTokenSpec is the spec for the machine unique token. Token can be empty if machine wasn't assigned any.
Expand Down
8 changes: 8 additions & 0 deletions hack/release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ Additionally `talosctl image cache-create` has some changes:
* multiple instances (`--platform=linux/amd64 --platform=linux/arm64`);
"""

[notes.kernel-module]
title = "Kernel Module"
description = """\
Talos now supports optionally disabling kernel module signature verification by setting `module.sig_enforce=0` kernel parameter.
By default module signature verification is enabled (`module.sig_enforce=1`).
When using Factory or Imager supply as `-module.sig_enfore module.sig_enforce=0` kernel parameters to disable module signature enforcement.
"""

[make_deps]

[make_deps.tools]
Expand Down
10 changes: 9 additions & 1 deletion internal/app/machined/pkg/controllers/runtime/security_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/cosi-project/runtime/pkg/safe"
"github.com/cosi-project/runtime/pkg/state"
"github.com/foxboron/go-uefi/efi"
"github.com/siderolabs/go-procfs/procfs"
"go.uber.org/zap"

machineruntime "github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
Expand Down Expand Up @@ -65,7 +66,7 @@ func (ctrl *SecurityStateController) Outputs() []controller.Output {

// Run implements controller.Controller interface.
//
//nolint:gocyclo
//nolint:gocyclo,cyclop
func (ctrl *SecurityStateController) Run(ctx context.Context, r controller.Runtime, _ *zap.Logger) error {
for {
select {
Expand All @@ -87,6 +88,7 @@ func (ctrl *SecurityStateController) Run(ctx context.Context, r controller.Runti
var (
secureBootState bool
bootedWithUKI bool
moduleSignatureEnforced bool
pcrSigningKeyFingerprint string
)

Expand Down Expand Up @@ -133,6 +135,11 @@ func (ctrl *SecurityStateController) Run(ctx context.Context, r controller.Runti
return fmt.Errorf("failed to get SELinux state: %w", err)
}

moduleSignatureEnforcedInfo := procfs.ProcCmdline().Get(constants.KernelParamEnforceModuleSigVerify).First()
if moduleSignatureEnforcedInfo != nil && *moduleSignatureEnforcedInfo == "1" {
moduleSignatureEnforced = true
}

fipsState := runtimeres.FIPSStateDisabled

if fipsmode.Enabled() {
Expand All @@ -149,6 +156,7 @@ func (ctrl *SecurityStateController) Run(ctx context.Context, r controller.Runti
state.TypedSpec().SELinuxState = selinuxState
state.TypedSpec().FIPSState = fipsState
state.TypedSpec().BootedWithUKI = bootedWithUKI
state.TypedSpec().ModuleSignatureEnforced = moduleSignatureEnforced

return nil
}); err != nil {
Expand Down
66 changes: 66 additions & 0 deletions internal/integration/api/security.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// 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/.

//go:build integration_api

package api

import (
"context"
"time"

"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/resource/rtestutils"
"github.com/stretchr/testify/assert"

"github.com/siderolabs/talos/internal/integration/base"
"github.com/siderolabs/talos/pkg/machinery/client"
runtimeres "github.com/siderolabs/talos/pkg/machinery/resources/runtime"
)

// SecuritySuite verifies the security state resource.
type SecuritySuite struct {
base.APISuite

ctx context.Context //nolint:containedctx
ctxCancel context.CancelFunc
}

// SuiteName returns the name of the suite.
func (suite *SecuritySuite) SuiteName() string {
return "api.SecuritySuite"
}

// SetupTest sets up the test.
func (suite *SecuritySuite) SetupTest() {
// make sure API calls have timeout
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 1*time.Minute)

if suite.Cluster == nil || suite.Cluster.Provisioner() != base.ProvisionerQEMU {
suite.T().Skip("skipping Security test since provisioner is not qemu")
}
}

// TearDownTest tears down the test.
func (suite *SecuritySuite) TearDownTest() {
if suite.ctxCancel != nil {
suite.ctxCancel()
}
}

// TestSecurityState verifies that the security state resource is present and has valid values.
func (suite *SecuritySuite) TestSecurityState() {
node := suite.RandomDiscoveredNodeInternalIP()
ctx := client.WithNode(suite.ctx, node)

rtestutils.AssertResources(ctx, suite.T(), suite.Client.COSI, []resource.ID{runtimeres.SecurityStateID},
func(r *runtimeres.SecurityState, asrt *assert.Assertions) {
asrt.True(r.TypedSpec().ModuleSignatureEnforced, "module signature enforcement should be enabled")
},
)
}

func init() {
allSuites = append(allSuites, &SecuritySuite{})
}
1 change: 1 addition & 0 deletions internal/pkg/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ func RunInstallerContainer(
constants.KernelParamAuditdDisabled,
constants.KernelParamDashboardDisabled,
constants.KernelParamNetIfnames,
constants.KernelParamEnforceModuleSigVerify,
} {
if c := procfs.ProcCmdline().Get(preservedArg).First(); c != nil {
args = append(args, "--extra-kernel-arg", fmt.Sprintf("%s=%s", preservedArg, *c))
Expand Down
13 changes: 11 additions & 2 deletions pkg/machinery/api/resource/definitions/runtime/runtime.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pkg/machinery/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ const (
// This param is injected by Equinix Metal and depends on the device ID and datacenter.
KernelParamEquinixMetalEvents = "em.events_url"

// KernelParamEnforceModuleSigVerify is the kernel parameter name to specify module signature verification enforcement.
// see https://github.com/siderolabs/talos/issues/11989
KernelParamEnforceModuleSigVerify = "module.sig_enforce"

// NewRoot is the path where the switchroot target is mounted.
NewRoot = "/root"

Expand Down
12 changes: 12 additions & 0 deletions pkg/machinery/imager/quirks/quirks.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,15 @@ func (q Quirks) SupportsEmbeddedConfig() bool {

return q.v.GTE(minTalosVersionEmbeddedConfig)
}

var minTalosVersionDisableModSigVerify = semver.MustParse("1.12.0")

// SupportsDisablingModuleSignatureVerification returns true if the Talos version supports disabling module signature verification.
func (q Quirks) SupportsDisablingModuleSignatureVerification() bool {
// if the version doesn't parse, we assume it's latest Talos
if q.v == nil {
return true
}

return q.v.GTE(minTalosVersionDisableModSigVerify)
}
4 changes: 4 additions & 0 deletions pkg/machinery/kernel/kernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func DefaultArgs(quirks quirks.Quirks) []string {
result = append(result, constants.KernelParamSELinux+"=1")
}

if quirks.SupportsDisablingModuleSignatureVerification() {
result = append(result, constants.KernelParamEnforceModuleSigVerify+"=1") // see https://github.com/siderolabs/talos/issues/11989
}

return result
}

Expand Down
1 change: 1 addition & 0 deletions pkg/machinery/kernel/kernel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func TestDefaultKernelArgs(t *testing.T) {
"nvme_core.io_timeout=4294967295",
"printk.devkmsg=on",
"selinux=1",
"module.sig_enforce=1",
},
},
{
Expand Down
5 changes: 5 additions & 0 deletions pkg/machinery/resources/runtime/security_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type SecurityStateSpec struct {
SELinuxState SELinuxState `yaml:"selinuxState,omitempty" protobuf:"4"`
FIPSState FIPSState `yaml:"fipsState,omitempty" protobuf:"6"`
BootedWithUKI bool `yaml:"bootedWithUKI,omitempty" protobuf:"5"`
ModuleSignatureEnforced bool `yaml:"moduleSignatureEnforced,omitempty" protobuf:"7"`
}

// NewSecurityStateSpec initializes a security state resource.
Expand Down Expand Up @@ -93,6 +94,10 @@ func (SecurityStateExtension) ResourceDefinition() meta.ResourceDefinitionSpec {
Name: "SELinuxState",
JSONPath: `{.selinuxState}`,
},
{
Name: "ModuleSignatureEnforced",
JSONPath: `{.moduleSignatureEnforced}`,
},
},
}
}
Expand Down
1 change: 1 addition & 0 deletions website/content/v1.12/reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -8136,6 +8136,7 @@ SecurityStateSpec describes the security state resource properties.
| se_linux_state | [talos.resource.definitions.enums.RuntimeSELinuxState](#talos.resource.definitions.enums.RuntimeSELinuxState) | | |
| booted_with_uki | [bool](#bool) | | |
| fips_state | [talos.resource.definitions.enums.RuntimeFIPSState](#talos.resource.definitions.enums.RuntimeFIPSState) | | |
| module_signature_enforced | [bool](#bool) | | |



Expand Down