From 485aa68483695ce50fce3e2ce1b274023273d657 Mon Sep 17 00:00:00 2001 From: Magnus Kulke Date: Mon, 9 Dec 2024 11:40:03 +0100 Subject: [PATCH] caa: remove option to configure agent via userdata The agent doesn't require dynamic configuration any more (userdata is untrusted input) we can reduce the surface and package a static configuration. In this change image auth support is always enabled. An empty auth file is provisioned by default to /run/peerpod/auth.json, it can be overwritten by userdata. Signed-off-by: Magnus Kulke --- src/cloud-api-adaptor/docs/initdata.md | 2 - .../pkg/adaptor/cloud/cloud.go | 12 ---- src/cloud-api-adaptor/pkg/agent/config.go | 36 ----------- .../pkg/agent/config_test.go | 59 ------------------- .../pkg/userdata/provision.go | 2 +- .../pkg/userdata/provision_test.go | 32 +--------- .../podvm/files/etc/agent-config.toml | 3 + .../podvm/files/etc/kata-oci/empty-auth.json | 3 + .../etc/systemd/system/kata-agent.service | 4 +- .../podvm/files/etc/tmpfiles.d/auth.conf | 2 + .../podvm/qcow2/copy-files.sh | 5 ++ 11 files changed, 18 insertions(+), 142 deletions(-) delete mode 100644 src/cloud-api-adaptor/pkg/agent/config.go delete mode 100644 src/cloud-api-adaptor/pkg/agent/config_test.go create mode 100644 src/cloud-api-adaptor/podvm/files/etc/agent-config.toml create mode 100644 src/cloud-api-adaptor/podvm/files/etc/kata-oci/empty-auth.json create mode 100644 src/cloud-api-adaptor/podvm/files/etc/tmpfiles.d/auth.conf diff --git a/src/cloud-api-adaptor/docs/initdata.md b/src/cloud-api-adaptor/docs/initdata.md index 816064204..02f6520f0 100644 --- a/src/cloud-api-adaptor/docs/initdata.md +++ b/src/cloud-api-adaptor/docs/initdata.md @@ -146,8 +146,6 @@ spec: cloud-api-adaptor will read the annotation and write it to [write_files](../../cloud-providers/util/cloudinit/cloudconfig.go). Note: files unrelated to initdata (like network tunnel configuration in `/run/peerpod/daemon.json`) are also part of the `write_files` directive. ```yaml write_files: -- path: /run/peerpod/agent-config.toml - content: - path: /run/peerpod/daemon.json content: - path: /run/peerpod/auth.json diff --git a/src/cloud-api-adaptor/pkg/adaptor/cloud/cloud.go b/src/cloud-api-adaptor/pkg/adaptor/cloud/cloud.go index b956f8284..8a88eb9cd 100644 --- a/src/cloud-api-adaptor/pkg/adaptor/cloud/cloud.go +++ b/src/cloud-api-adaptor/pkg/adaptor/cloud/cloud.go @@ -23,7 +23,6 @@ import ( "github.com/confidential-containers/cloud-api-adaptor/src/cloud-api-adaptor/pkg/adaptor/k8sops" "github.com/confidential-containers/cloud-api-adaptor/src/cloud-api-adaptor/pkg/adaptor/proxy" - "github.com/confidential-containers/cloud-api-adaptor/src/cloud-api-adaptor/pkg/agent" "github.com/confidential-containers/cloud-api-adaptor/src/cloud-api-adaptor/pkg/forwarder" . "github.com/confidential-containers/cloud-api-adaptor/src/cloud-api-adaptor/pkg/paths" "github.com/confidential-containers/cloud-api-adaptor/src/cloud-api-adaptor/pkg/podnetwork" @@ -255,7 +254,6 @@ func (s *cloudService) CreateVM(ctx context.Context, req *pb.CreateVMRequest) (r agentProxy := s.proxyFactory.New(serverName, socketPath) var authJSON []byte - var authFilePath string _, err = os.Stat(SrcAuthfilePath) if err != nil { logger.Printf("credential file %s is not present, skipping image auth config", SrcAuthfilePath) @@ -264,15 +262,9 @@ func (s *cloudService) CreateVM(ctx context.Context, req *pb.CreateVMRequest) (r if err != nil { return nil, fmt.Errorf("error reading %s: %v", SrcAuthfilePath, err) } - authFilePath = AuthFilePath logger.Printf("configure agent to use credentials file %s", SrcAuthfilePath) } - agentConfig, err := agent.CreateConfigFile(authFilePath) - if err != nil { - return nil, fmt.Errorf("creating agent config: %w", err) - } - daemonConfig := forwarder.Config{ PodNamespace: namespace, PodName: pod, @@ -321,10 +313,6 @@ func (s *cloudService) CreateVM(ctx context.Context, req *pb.CreateVMRequest) (r cloudConfig := &cloudinit.CloudConfig{ WriteFiles: []cloudinit.WriteFile{ - { - Path: agent.ConfigFilePath, - Content: agentConfig, - }, { Path: forwarder.DefaultConfigPath, Content: string(daemonJSON), diff --git a/src/cloud-api-adaptor/pkg/agent/config.go b/src/cloud-api-adaptor/pkg/agent/config.go deleted file mode 100644 index 58bcc8343..000000000 --- a/src/cloud-api-adaptor/pkg/agent/config.go +++ /dev/null @@ -1,36 +0,0 @@ -package agent - -import ( - "github.com/pelletier/go-toml/v2" -) - -const ( - ConfigFilePath = "/run/peerpod/agent-config.toml" - ServerAddr = "unix:///run/kata-containers/agent.sock" - GuestComponentsProcs = "none" -) - -type agentConfig struct { - ServerAddr string `toml:"server_addr"` - GuestComponentsProcs string `toml:"guest_components_procs"` - ImageRegistryAuth string `toml:"image_registry_auth,omitempty"` -} - -func CreateConfigFile(authJsonPath string) (string, error) { - var imageRegistryAuth string - if authJsonPath != "" { - imageRegistryAuth = "file://" + authJsonPath - } - - config := agentConfig{ - ServerAddr: ServerAddr, - GuestComponentsProcs: GuestComponentsProcs, - ImageRegistryAuth: imageRegistryAuth, - } - - bytes, err := toml.Marshal(config) - if err != nil { - return "", err - } - return string(bytes), nil -} diff --git a/src/cloud-api-adaptor/pkg/agent/config_test.go b/src/cloud-api-adaptor/pkg/agent/config_test.go deleted file mode 100644 index d374d7b1c..000000000 --- a/src/cloud-api-adaptor/pkg/agent/config_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package agent - -import ( - "testing" - - "github.com/pelletier/go-toml/v2" -) - -func TestAgentConfigFile(t *testing.T) { - refdoc := `server_addr = 'unix:///run/kata-containers/agent.sock' -guest_components_procs = 'none' -` - var refcfg agentConfig - err := toml.Unmarshal([]byte(refdoc), &refcfg) - if err != nil { - panic(err) - } - - if refcfg.ServerAddr != ServerAddr { - t.Errorf("Expected %s, got %s", ServerAddr, refcfg.ServerAddr) - } - if refcfg.GuestComponentsProcs != GuestComponentsProcs { - t.Errorf("Expected %s, got %s", GuestComponentsProcs, refcfg.GuestComponentsProcs) - } - - configstr, err := CreateConfigFile("") - if err != nil { - panic(err) - } - if refdoc != string(configstr) { - t.Errorf("Expected %s, got %s", refdoc, configstr) - } -} - -func TestAgentConfigFileWithAuthJsonFile(t *testing.T) { - refdoc := `server_addr = 'unix:///run/kata-containers/agent.sock' -guest_components_procs = 'none' -image_registry_auth = 'file:///run/peerpod/auth.json' -` - authJsonFile := "/run/peerpod/auth.json" - - configstr, err := CreateConfigFile(authJsonFile) - if err != nil { - panic(err) - } - if refdoc != string(configstr) { - t.Errorf("Expected %s, got %s", refdoc, configstr) - } - - var config agentConfig - err = toml.Unmarshal([]byte(configstr), &config) - if err != nil { - panic(err) - } - - if config.ImageRegistryAuth != "file://"+authJsonFile { - t.Errorf("Expected %s, got %s", config.ImageRegistryAuth, authJsonFile) - } -} diff --git a/src/cloud-api-adaptor/pkg/userdata/provision.go b/src/cloud-api-adaptor/pkg/userdata/provision.go index 830d99740..2f780a00b 100644 --- a/src/cloud-api-adaptor/pkg/userdata/provision.go +++ b/src/cloud-api-adaptor/pkg/userdata/provision.go @@ -37,7 +37,7 @@ const ( ) var logger = log.New(log.Writer(), "[userdata/provision] ", log.LstdFlags|log.Lmsgprefix) -var WriteFilesList = []string{AACfgPath, CDHCfgPath, AgentCfgPath, ForwarderCfgPath, AuthFilePath, InitDataPath} +var WriteFilesList = []string{AACfgPath, CDHCfgPath, ForwarderCfgPath, AuthFilePath, InitDataPath} var InitdDataFilesList = []string{AACfgPath, CDHCfgPath, PolicyPath} type Config struct { diff --git a/src/cloud-api-adaptor/pkg/userdata/provision_test.go b/src/cloud-api-adaptor/pkg/userdata/provision_test.go index da19ac694..071ff9cea 100644 --- a/src/cloud-api-adaptor/pkg/userdata/provision_test.go +++ b/src/cloud-api-adaptor/pkg/userdata/provision_test.go @@ -14,10 +14,6 @@ import ( "time" ) -var testAgentConfig string = `server_addr = 'unix:///run/kata-containers/agent.sock' -guest_components_procs = 'none' -` - var testDaemonConfig string = `{ "pod-network": { "podip": "10.244.0.19/24", @@ -336,12 +332,11 @@ func TestProcessCloudConfig(t *testing.T) { defer os.RemoveAll(tempDir) var aaCfgPath = filepath.Join(tempDir, "aa.toml") - var agentCfgPath = filepath.Join(tempDir, "agent-config.toml") var cdhCfgPath = filepath.Join(tempDir, "cdh.toml") var daemonPath = filepath.Join(tempDir, "daemon.json") var authPath = filepath.Join(tempDir, "auth.json") var initdataPath = filepath.Join(tempDir, "initdata") - var writeFilesList = []string{aaCfgPath, agentCfgPath, cdhCfgPath, daemonPath, authPath, initdataPath} + var writeFilesList = []string{aaCfgPath, cdhCfgPath, daemonPath, authPath, initdataPath} content := fmt.Sprintf(`#cloud-config write_files: @@ -360,14 +355,9 @@ write_files: - path: %s content: | %s -- path: %s - content: | -%s `, aaCfgPath, indentTextBlock(testAAConfig, 4), - agentCfgPath, - indentTextBlock(testAgentConfig, 4), cdhCfgPath, indentTextBlock(testCDHConfig, 4), daemonPath, @@ -403,12 +393,6 @@ write_files: t.Fatalf("file content does not match aa config fixture: got %q", fileContent) } - data, _ = os.ReadFile(agentCfgPath) - fileContent = string(data) - if fileContent != testAgentConfig { - t.Fatalf("file content does not match agent config fixture: got %q", fileContent) - } - data, _ = os.ReadFile(cdhCfgPath) fileContent = string(data) if fileContent != testCDHConfig { @@ -439,12 +423,11 @@ func TestProcessCloudConfigWithMalicious(t *testing.T) { defer os.RemoveAll(tempDir) var aaCfgPath = filepath.Join(tempDir, "aa.toml") - var agentCfgPath = filepath.Join(tempDir, "agent-config.toml") var cdhCfgPath = filepath.Join(tempDir, "cdh.toml") var daemonPath = filepath.Join(tempDir, "daemon.json") var authPath = filepath.Join(tempDir, "auth.json") var malicious = filepath.Join(tempDir, "malicious") - var writeFilesList = []string{aaCfgPath, agentCfgPath, cdhCfgPath, daemonPath, authPath} + var writeFilesList = []string{aaCfgPath, cdhCfgPath, daemonPath, authPath} content := fmt.Sprintf(`#cloud-config write_files: @@ -463,14 +446,9 @@ write_files: - path: %s content: | %s -- path: %s - content: | -%s `, aaCfgPath, indentTextBlock(testAAConfig, 4), - agentCfgPath, - indentTextBlock(testAgentConfig, 4), cdhCfgPath, indentTextBlock(testCDHConfig, 4), daemonPath, @@ -506,12 +484,6 @@ write_files: t.Fatalf("file content does not match aa config fixture: got %q", fileContent) } - data, _ = os.ReadFile(agentCfgPath) - fileContent = string(data) - if fileContent != testAgentConfig { - t.Fatalf("file content does not match agent config fixture: got %q", fileContent) - } - data, _ = os.ReadFile(cdhCfgPath) fileContent = string(data) if fileContent != testCDHConfig { diff --git a/src/cloud-api-adaptor/podvm/files/etc/agent-config.toml b/src/cloud-api-adaptor/podvm/files/etc/agent-config.toml new file mode 100644 index 000000000..1940efb72 --- /dev/null +++ b/src/cloud-api-adaptor/podvm/files/etc/agent-config.toml @@ -0,0 +1,3 @@ +server_addr = "unix:///run/kata-containers/agent.sock" +guest_components_procs = "none" +image_registry_auth = "file:///etc/kata-oci/auth.json" diff --git a/src/cloud-api-adaptor/podvm/files/etc/kata-oci/empty-auth.json b/src/cloud-api-adaptor/podvm/files/etc/kata-oci/empty-auth.json new file mode 100644 index 000000000..9a1ab3374 --- /dev/null +++ b/src/cloud-api-adaptor/podvm/files/etc/kata-oci/empty-auth.json @@ -0,0 +1,3 @@ +{ + "auths": {} +} diff --git a/src/cloud-api-adaptor/podvm/files/etc/systemd/system/kata-agent.service b/src/cloud-api-adaptor/podvm/files/etc/systemd/system/kata-agent.service index 1cedaa1a4..27224dcb8 100644 --- a/src/cloud-api-adaptor/podvm/files/etc/systemd/system/kata-agent.service +++ b/src/cloud-api-adaptor/podvm/files/etc/systemd/system/kata-agent.service @@ -5,9 +5,9 @@ After=netns@podns.service process-user-data.service [Service] ExecStartPre=mkdir -p /run/kata-containers -ExecStart=/usr/local/bin/kata-agent --config /run/peerpod/agent-config.toml +ExecStart=/usr/local/bin/kata-agent --config /etc/agent-config.toml ExecStartPre=-umount /sys/fs/cgroup/misc -ExecStopPost=/usr/local/bin/kata-agent-clean --config /run/peerpod/agent-config.toml +ExecStopPost=/usr/local/bin/kata-agent-clean --config /etc/agent-config.toml SyslogIdentifier=kata-agent [Install] diff --git a/src/cloud-api-adaptor/podvm/files/etc/tmpfiles.d/auth.conf b/src/cloud-api-adaptor/podvm/files/etc/tmpfiles.d/auth.conf new file mode 100644 index 000000000..413afd614 --- /dev/null +++ b/src/cloud-api-adaptor/podvm/files/etc/tmpfiles.d/auth.conf @@ -0,0 +1,2 @@ +#Type Path Mode User Group Age Argument +C /run/peerpod/auth.json - - - - /etc/kata-oci/empty-auth.json diff --git a/src/cloud-api-adaptor/podvm/qcow2/copy-files.sh b/src/cloud-api-adaptor/podvm/qcow2/copy-files.sh index 9f18b096b..9e2d71a47 100755 --- a/src/cloud-api-adaptor/podvm/qcow2/copy-files.sh +++ b/src/cloud-api-adaptor/podvm/qcow2/copy-files.sh @@ -30,3 +30,8 @@ sudo cp -a /tmp/files/pause_bundle / sudo mkdir -p /etc/kata-opa sudo cp -a /tmp/files/etc/kata-opa/* /etc/kata-opa/ sudo cp -a /tmp/files/etc/tmpfiles.d/policy.conf /etc/tmpfiles.d/ + +# Copy an empty auth.json for image pulling +sudo mkdir -p /etc/kata-oci +sudo cp -a /tmp/files/etc/kata-oci/* /etc/kata-oci/ +sudo cp -a /tmp/files/etc/tmpfiles.d/auth.conf /etc/tmpfiles.d/