diff --git a/src/runtime/cmd/kata-runtime/kata-policy.go b/src/runtime/cmd/kata-runtime/kata-policy.go new file mode 100644 index 0000000000..1ca1779d8b --- /dev/null +++ b/src/runtime/cmd/kata-runtime/kata-policy.go @@ -0,0 +1,73 @@ +// Copyright (c) 2023 Intel Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +package main + +import ( + "fmt" + "os" + + containerdshim "github.com/kata-containers/kata-containers/src/runtime/pkg/containerd-shim-v2" + "github.com/kata-containers/kata-containers/src/runtime/pkg/katautils" + "github.com/kata-containers/kata-containers/src/runtime/pkg/utils/shimclient" + "github.com/urfave/cli" +) + +var policySubCmds = []cli.Command{ + setPolicyCommand, +} + +var kataPolicyCommand = cli.Command{ + Name: "policy", + Usage: "set policy within the Kata Containers guest", + Subcommands: policySubCmds, + Action: func(context *cli.Context) { + cli.ShowSubcommandHelp(context) + }, +} + +var setPolicyCommand = cli.Command{ + Name: "set", + Usage: "set policy in a specifc Kata Containers guest based on file", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "sandbox-id", + Usage: "the target sandbox for setting the policy", + Required: true, + Destination: &sandboxID, + }, + }, + Action: func(c *cli.Context) error { + policyFile := c.Args().Get(0) + + // verify sandbox exists: + if err := katautils.VerifyContainerID(sandboxID); err != nil { + return err + } + + // verify policy were provided: + if policyFile == "" { + return fmt.Errorf("policy file not provided") + } + + if !katautils.FileExists(policyFile) { + return fmt.Errorf("policy file does not exist: %s", policyFile) + } + + // Read file into buffer, and make request to the appropriate shim + buf, err := os.ReadFile(policyFile) + if err != nil { + return err + } + + url := containerdshim.PolicyUrl + + if err = shimclient.DoPut(sandboxID, defaultTimeout, url, "application/octet-stream", buf); err != nil { + return fmt.Errorf("Error observed when making policy-set request(%s): %s", policyFile, err) + } + + return nil + }, +} diff --git a/src/runtime/cmd/kata-runtime/main.go b/src/runtime/cmd/kata-runtime/main.go index a722afd6be..2c89c1eaf1 100644 --- a/src/runtime/cmd/kata-runtime/main.go +++ b/src/runtime/cmd/kata-runtime/main.go @@ -126,6 +126,7 @@ var runtimeCommands = []cli.Command{ factoryCLICommand, kataVolumeCommand, kataIPTablesCommand, + kataPolicyCommand, } // runtimeBeforeSubcommands is the function to run before command-line diff --git a/src/runtime/pkg/containerd-shim-v2/shim_management.go b/src/runtime/pkg/containerd-shim-v2/shim_management.go index e83e54417a..4133e786e1 100644 --- a/src/runtime/pkg/containerd-shim-v2/shim_management.go +++ b/src/runtime/pkg/containerd-shim-v2/shim_management.go @@ -38,6 +38,7 @@ const ( DirectVolumeStatUrl = "/direct-volume/stats" DirectVolumeResizeUrl = "/direct-volume/resize" IPTablesUrl = "/iptables" + PolicyUrl = "/policy" IP6TablesUrl = "/ip6tables" MetricsUrl = "/metrics" ) @@ -199,6 +200,32 @@ func (s *service) serveVolumeResize(w http.ResponseWriter, r *http.Request) { w.Write([]byte("")) } +func (s *service) policyHandler(w http.ResponseWriter, r *http.Request) { + logger := shimMgtLog.WithFields(logrus.Fields{"handler": "policy"}) + + switch r.Method { + case http.MethodPut: + body, err := io.ReadAll(r.Body) + if err != nil { + logger.WithError(err).Error("failed to read request body") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + if err = s.sandbox.SetPolicy(context.Background(), string(body)); err != nil { + logger.WithError(err).Error("failed to set policy") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + } + w.Write([]byte("")) + + default: + w.WriteHeader(http.StatusNotImplemented) + return + } +} + func (s *service) ip6TablesHandler(w http.ResponseWriter, r *http.Request) { s.genericIPTablesHandler(w, r, true) } @@ -266,6 +293,7 @@ func (s *service) startManagementServer(ctx context.Context, ociSpec *specs.Spec m.Handle(DirectVolumeStatUrl, http.HandlerFunc(s.serveVolumeStats)) m.Handle(DirectVolumeResizeUrl, http.HandlerFunc(s.serveVolumeResize)) m.Handle(IPTablesUrl, http.HandlerFunc(s.ipTablesHandler)) + m.Handle(PolicyUrl, http.HandlerFunc(s.policyHandler)) m.Handle(IP6TablesUrl, http.HandlerFunc(s.ip6TablesHandler)) s.mountPprofHandle(m, ociSpec) diff --git a/src/runtime/virtcontainers/interfaces.go b/src/runtime/virtcontainers/interfaces.go index 492d3f35a7..742156a6b5 100644 --- a/src/runtime/virtcontainers/interfaces.go +++ b/src/runtime/virtcontainers/interfaces.go @@ -82,6 +82,7 @@ type VCSandbox interface { GetIPTables(ctx context.Context, isIPv6 bool) ([]byte, error) SetIPTables(ctx context.Context, isIPv6 bool, data []byte) error + SetPolicy(ctx context.Context, policy string) error } // VCContainer is the Container interface diff --git a/src/runtime/virtcontainers/pkg/vcmock/sandbox.go b/src/runtime/virtcontainers/pkg/vcmock/sandbox.go index 77f56846a2..09ece4e765 100644 --- a/src/runtime/virtcontainers/pkg/vcmock/sandbox.go +++ b/src/runtime/virtcontainers/pkg/vcmock/sandbox.go @@ -269,3 +269,7 @@ func (s *Sandbox) GetIPTables(ctx context.Context, isIPv6 bool) ([]byte, error) func (s *Sandbox) SetIPTables(ctx context.Context, isIPv6 bool, data []byte) error { return nil } + +func (s *Sandbox) SetPolicy(ctx context.Context, policy string) error { + return nil +} diff --git a/src/runtime/virtcontainers/sandbox.go b/src/runtime/virtcontainers/sandbox.go index 548c6f8300..bff8b6b9b0 100644 --- a/src/runtime/virtcontainers/sandbox.go +++ b/src/runtime/virtcontainers/sandbox.go @@ -2607,6 +2607,11 @@ func (s *Sandbox) SetIPTables(ctx context.Context, isIPv6 bool, data []byte) err return s.agent.setIPTables(ctx, isIPv6, data) } +// SetPolicy will set the policy in the guest +func (s *Sandbox) SetPolicy(ctx context.Context, policy string) error { + return s.agent.setPolicy(ctx, policy) +} + // GuestVolumeStats return the filesystem stat of a given volume in the guest. func (s *Sandbox) GuestVolumeStats(ctx context.Context, volumePath string) ([]byte, error) { guestMountPath, err := s.guestMountPath(volumePath)