diff --git a/e2e/tests/up/provider_docker.go b/e2e/tests/up/provider_docker.go index 6969d01a5..57d950a7d 100644 --- a/e2e/tests/up/provider_docker.go +++ b/e2e/tests/up/provider_docker.go @@ -508,6 +508,26 @@ var _ = ginkgo.Describe( ginkgo.SpecTimeout(framework.TimeoutShort()), ) + ginkgo.It("security options", func(ctx context.Context) { + tempDir, err := dtc.setupAndUp(ctx, "tests/up/testdata/docker-securityopt") + framework.ExpectNoError(err) + + workspace, err := dtc.f.FindWorkspace(ctx, tempDir) + framework.ExpectNoError(err) + + ids, err := dtc.findWorkspaceContainer(ctx, workspace) + framework.ExpectNoError(err) + gomega.Expect(ids).To(gomega.HaveLen(1)) + + var details []container.InspectResponse + err = dtc.dockerHelper.Inspect(ctx, ids, "container", &details) + framework.ExpectNoError(err) + gomega.Expect(details[0].HostConfig.SecurityOpt). + To(gomega.ContainElement("seccomp=unconfined")) + gomega.Expect(details[0].HostConfig.SecurityOpt). + To(gomega.ContainElement("apparmor=unconfined")) + }, ginkgo.SpecTimeout(framework.TimeoutShort())) + ginkgo.It("multi devcontainer selection", func(ctx context.Context) { tempDir, err := setupWorkspace( "tests/up/testdata/docker-multi-devcontainer", diff --git a/e2e/tests/up/testdata/docker-securityopt/.devcontainer.json b/e2e/tests/up/testdata/docker-securityopt/.devcontainer.json new file mode 100644 index 000000000..47be2d6d0 --- /dev/null +++ b/e2e/tests/up/testdata/docker-securityopt/.devcontainer.json @@ -0,0 +1,5 @@ +{ + "name": "Go", + "image": "ghcr.io/devsy-org/test-images/go:1", + "securityOpt": ["seccomp=unconfined", "apparmor=unconfined"] +} diff --git a/pkg/devcontainer/single.go b/pkg/devcontainer/single.go index 0b6a9ab88..0f41badbc 100644 --- a/pkg/devcontainer/single.go +++ b/pkg/devcontainer/single.go @@ -438,8 +438,9 @@ func (r *runner) getDockerlessRunOptions( "--cmd", GetStartScript(mergedConfig), "--user", buildInfo.Dockerless.User, }, - Env: env, - CapAdd: mergedConfig.CapAdd, + Env: env, + CapAdd: mergedConfig.CapAdd, + SecurityOpt: mergedConfig.SecurityOpt, Labels: []string{ metadata.ImageMetadataLabel + "=" + string(marshalled), config.UserLabel + "=" + buildInfo.Dockerless.User, diff --git a/pkg/driver/docker/docker_test.go b/pkg/driver/docker/docker_test.go index 44f7d0e06..37bc0de52 100644 --- a/pkg/driver/docker/docker_test.go +++ b/pkg/driver/docker/docker_test.go @@ -5,9 +5,15 @@ import ( "testing" "github.com/devsy-org/devsy/pkg/devcontainer/config" + "github.com/devsy-org/devsy/pkg/driver" "github.com/stretchr/testify/suite" ) +const ( + testSeccompUnconfined = "seccomp=unconfined" + testSecurityOptFlag = "--security-opt" +) + type DockerDriverTestSuite struct { suite.Suite driver *dockerDriver @@ -137,3 +143,38 @@ func (s *DockerDriverTestSuite) TestGatherUpdateRequirements_WithContainerUser() s.NotNil(localUser) s.Equal("container", containerUser) } + +func (s *DockerDriverTestSuite) TestAddCapabilityArgs_SingleSecurityOpt() { + opts := &driver.RunOptions{SecurityOpt: []string{testSeccompUnconfined}} + args := s.driver.addCapabilityArgs(nil, opts) + s.Equal([]string{testSecurityOptFlag, testSeccompUnconfined}, args) +} + +func (s *DockerDriverTestSuite) TestAddCapabilityArgs_MultipleSecurityOpts() { + opts := &driver.RunOptions{ + SecurityOpt: []string{testSeccompUnconfined, "apparmor=unconfined"}, + } + args := s.driver.addCapabilityArgs(nil, opts) + s.Equal([]string{ + testSecurityOptFlag, testSeccompUnconfined, + testSecurityOptFlag, "apparmor=unconfined", + }, args) +} + +func (s *DockerDriverTestSuite) TestAddCapabilityArgs_EmptySecurityOpt() { + opts := &driver.RunOptions{} + args := s.driver.addCapabilityArgs(nil, opts) + s.Nil(args) +} + +func (s *DockerDriverTestSuite) TestAddCapabilityArgs_CapAddAndSecurityOpt() { + opts := &driver.RunOptions{ + CapAdd: []string{"SYS_PTRACE"}, + SecurityOpt: []string{testSeccompUnconfined}, + } + args := s.driver.addCapabilityArgs(nil, opts) + s.Equal([]string{ + "--cap-add", "SYS_PTRACE", + testSecurityOptFlag, testSeccompUnconfined, + }, args) +}