mirror of
https://github.com/siderolabs/talos.git
synced 2026-04-15 02:32:04 +02:00
Add support for whole machine-wide image verification configuration. Configuration is a set of rules applied top-down to the image reference, each specifying a specific cosign-based identity or static public key claim. Talos provides a machined API to verify an image reference, resolving it to the digest on the way as needed. Talos itself hooks up in the image verification process, while containerd CRI plugin accesses same API via the machined socket. Signed-off-by: Laura Brehm <laurabrehm@hey.com> Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
122 lines
3.4 KiB
Go
122 lines
3.4 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 install
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
containerd "github.com/containerd/containerd/v2/client"
|
|
"github.com/containerd/containerd/v2/pkg/cio"
|
|
"github.com/containerd/containerd/v2/pkg/namespaces"
|
|
"github.com/containerd/containerd/v2/pkg/oci"
|
|
"github.com/containerd/errdefs"
|
|
"github.com/cosi-project/runtime/pkg/state"
|
|
|
|
"github.com/siderolabs/talos/internal/pkg/containers/image"
|
|
"github.com/siderolabs/talos/internal/pkg/containers/image/console"
|
|
"github.com/siderolabs/talos/internal/pkg/selinux"
|
|
"github.com/siderolabs/talos/pkg/machinery/constants"
|
|
)
|
|
|
|
// PullAndValidateInstallerImage pulls down the installer and validates that it can run.
|
|
//
|
|
//nolint:gocyclo
|
|
func PullAndValidateInstallerImage(ctx context.Context, resources state.State, registryBuilder image.RegistriesBuilder, ref string) error {
|
|
// Pull down specified installer image early so we can bail if it doesn't exist in the upstream registry
|
|
containerdctx := namespaces.WithNamespace(ctx, constants.SystemContainerdNamespace)
|
|
|
|
const containerID = "validate"
|
|
|
|
client, err := containerd.New(constants.SystemContainerdAddress)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer client.Close() //nolint:errcheck
|
|
|
|
img, err := image.Pull(containerdctx, registryBuilder, resources, client, ref,
|
|
image.WithSkipIfAlreadyPulled(),
|
|
image.WithMaxNotFoundRetries(1),
|
|
image.WithProgressReporter(console.NewProgressReporter),
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// See if there's previous container/snapshot to clean up
|
|
var oldcontainer containerd.Container
|
|
|
|
if oldcontainer, err = client.LoadContainer(containerdctx, containerID); err == nil {
|
|
if err = oldcontainer.Delete(containerdctx, containerd.WithSnapshotCleanup); err != nil {
|
|
return fmt.Errorf("error deleting old container instance: %w", err)
|
|
}
|
|
}
|
|
|
|
if err = client.SnapshotService("").Remove(containerdctx, containerID); err != nil && !errdefs.IsNotFound(err) {
|
|
return fmt.Errorf("error cleaning up stale snapshot: %w", err)
|
|
}
|
|
|
|
// Launch the container with a known help command for a simple check to make sure the image is valid
|
|
args := []string{
|
|
"/bin/installer",
|
|
"--help",
|
|
}
|
|
|
|
specOpts := []oci.SpecOpts{
|
|
oci.WithImageConfig(img),
|
|
oci.WithProcessArgs(args...),
|
|
}
|
|
|
|
if selinux.IsEnabled() {
|
|
specOpts = append(specOpts, oci.WithSelinuxLabel(constants.SelinuxLabelInstaller))
|
|
}
|
|
|
|
containerOpts := []containerd.NewContainerOpts{
|
|
containerd.WithImage(img),
|
|
containerd.WithNewSnapshot(containerID, img),
|
|
containerd.WithNewSpec(specOpts...),
|
|
}
|
|
|
|
container, err := client.NewContainer(containerdctx, containerID, containerOpts...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
//nolint:errcheck
|
|
defer container.Delete(containerdctx, containerd.WithSnapshotCleanup)
|
|
|
|
task, err := container.NewTask(containerdctx, cio.NullIO)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
//nolint:errcheck
|
|
defer task.Delete(containerdctx)
|
|
|
|
exitStatusC, err := task.Wait(containerdctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = task.Start(containerdctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
status := <-exitStatusC
|
|
|
|
code, _, err := status.Result()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if code != 0 {
|
|
return errors.New("installer help returned non-zero exit. assuming invalid installer")
|
|
}
|
|
|
|
return nil
|
|
}
|