8000 api: add MaskedPaths and ReadonlyPaths options by jessfraz · Pull Request #36644 · moby/moby · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

api: add MaskedPaths and ReadonlyPaths options #36644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 7, 2018
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
10 changes: 10 additions & 0 deletions api/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,16 @@ definitions:
- "default"
- "process"
- "hyperv"
MaskedPaths:
type: "array"
description: "The list of paths to be masked inside the container (this overrides the default set of paths)"
items:
type: "string"
ReadonlyPaths:
type: "array"
description: "The list of paths to be set as read-only inside the container (this overrides the default set of paths)"
items:
< 8000 /td> type: "string"

ContainerConfig:
description: "Configuration for a container that is portable between hosts"
Expand Down
6 changes: 6 additions & 0 deletions api/types/container/host_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,12 @@ type HostConfig struct {
// Mounts specs used by the container
Mounts []mount.Mount `json:",omitempty"`

// MaskedPaths is the list of paths to be masked inside the container (this overrides the default set of paths)
MaskedPaths []string

// ReadonlyPaths is the list of paths to be set as read-only inside the container (this overrides the default set of paths)
ReadonlyPaths []string

This comment was marked as resolved.

Copy link
Contributor Author
8000

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do!


// Run a custom init inside the container, if null, use the daemon's configured settings
Init *bool `json:",omitempty"`
}
11 changes: 11 additions & 0 deletions daemon/create_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
containertypes "github.com/docker/docker/api/types/container"
mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/container"
"github.com/docker/docker/oci"
"github.com/docker/docker/pkg/stringid"
volumeopts "github.com/docker/docker/volume/service/opts"
"github.com/opencontainers/selinux/go-selinux/label"
Expand All @@ -29,6 +30,16 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
return err
}

// Set the default masked and readonly paths with regard to the host config options if they are not set.
if hostConfig.MaskedPaths == nil && !hostConfig.Privileged {
hostConfig.MaskedPaths = oci.DefaultSpec().Linux.MaskedPaths // Set it to the default if nil
container.HostConfig.MaskedPaths = hostConfig.MaskedPaths
}
if hostConfig.ReadonlyPaths == nil && !hostConfig.Privileged {
hostConfig.ReadonlyPaths = oci.DefaultSpec().Linux.ReadonlyPaths // Set it to the default if nil
container.HostConfig.ReadonlyPaths = hostConfig.ReadonlyPaths
}

for spec := range config.Volumes {
name := stringid.GenerateNonCryptoID()
destination := filepath.Clean(spec)
Expand Down
8 changes: 8 additions & 0 deletions daemon/oci_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,14 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
s.Process.OOMScoreAdj = &c.HostConfig.OomScoreAdj
s.Linux.MountLabel = c.MountLabel

// Set the masked and readonly paths with regard to the host config options if they are set.
if c.HostConfig.MaskedPaths != nil {
s.Linux.MaskedPaths = c.HostConfig.MaskedPaths
}
if c.HostConfig.ReadonlyPaths != nil {
s.Linux.ReadonlyPaths = c.HostConfig.ReadonlyPaths
}

return &s, nil
}

Expand Down
164 changes: 164 additions & 0 deletions integration/container/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ package container // import "github.com/docker/docker/integration/container"

import (
"context"
"encoding/json"
"fmt"
"strconv"
"testing"
"time"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
ctr "github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/internal/test/request"
"github.com/docker/docker/oci"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/poll"
"github.com/gotestyourself/gotestyourself/skip"
)

Expand Down Expand Up @@ -137,3 +144,160 @@ func TestCreateTmpfsMountsTarget(t *testing.T) {
assert.Check(t, is.ErrorContains(err, tc.expectedError))
}
}
func TestCreateWithCustomMaskedPaths(t *testing.T) {
skip.If(t, testEnv.DaemonInfo.OSType != "linux")

defer setupTest(t)()
client := request.NewAPIClient(t)
ctx := context.Background()

testCases := []struct {
maskedPaths []string
expected []string
}{
{
maskedPaths: []string{},
expected: []string{},
},
{
maskedPaths: nil,
expected: oci.DefaultSpec().Linux.MaskedPaths,
},
{
maskedPaths: []string{"/proc/kcore", "/proc/keys"},
expected: []string{"/proc/kcore", "/proc/keys"},
},
}

checkInspect := func(t *testing.T, ctx context.Context, name string, expected []string) {
_, b, err := client.ContainerInspectWithRaw(ctx, name, false)
assert.NilError(t, err)

var inspectJSON map[string]interface{}
err = json.Unmarshal(b, &inspectJSON)
assert.NilError(t, err)

cfg, ok := inspectJSON["HostConfig"].(map[string]interface{})
assert.Check(t, is.Equal(true, ok), name)

maskedPaths, ok := cfg["MaskedPaths"].([]interface{})
assert.Check(t, is.Equal(true, ok), name)

mps := []string{}
for _, mp := range maskedPaths {
mps = append(mps, mp.(string))
}

assert.DeepEqual(t, expected, mps)
}

for i, tc := range testCases {
name := fmt.Sprintf("create-masked-paths-%d", i)
config := container.Config{
Image: "busybox",
Cmd: []string{"true"},
}
hc := container.HostConfig{}
if tc.maskedPaths != nil {
hc.MaskedPaths = tc.maskedPaths
}

// Create the container.
c, err := client.ContainerCreate(context.Background(),
&config,
&hc,
&network.NetworkingConfig{},
name,
)
assert.NilError(t, err)

checkInspect(t, ctx, name, tc.expected)

// Start the container.
err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
assert.NilError(t, err)

poll.WaitOn(t, ctr.IsInState(ctx, client, c.ID, "exited"), poll.WithDelay(100*time.Millisecond))

checkInspect(t, ctx, name, tc.expected)
}
}

func TestCreateWithCustomReadonlyPaths(t *testing.T) {
skip.If(t, testEnv.DaemonInfo.OSType != "linux")

defer setupTest(t)()
client := request.NewAPIClient(t)
ctx := context.Background()

testCases := []struct {
doc string
readonlyPaths []string
expected []string
}{
{
readonlyPaths: []string{},
expected: []string{},
},
{
readonlyPaths: nil,
expected: oci.DefaultSpec().Linux.ReadonlyPaths,
},
{
readonlyPaths: []string{"/proc/asound", "/proc/bus"},
expected: []string{"/proc/asound", "/proc/bus"},
},
}

checkInspect := func(t *testing.T, ctx context.Context, name string, expected []string) {
_, b, err := client.ContainerInspectWithRaw(ctx, name, false)
assert.NilError(t, err)

var inspectJSON map[string]interface{}
err = json.Unmarshal(b, &inspectJSON)
assert.NilError(t, err)

cfg, ok := inspectJSON["HostConfig"].(map[string]interface{})
assert.Check(t, is.Equal(true, ok), name)

readonlyPaths, ok := cfg["ReadonlyPaths"].([]interface{})
assert.Check(t, is.Equal(true, ok), name)

rops := []string{}
for _, rop := range readonlyPaths {
rops = append(rops, rop.(string))
}
assert.DeepEqual(t, expected, rops)
}

for i, tc := range testCases {
name := fmt.Sprintf("create-readonly-paths-%d", i)
config := container.Config{
Image: "busybox",
Cmd: []string{"true"},
}
hc := container.HostConfig{}
if tc.readonlyPaths != nil {
hc.ReadonlyPaths = tc.readonlyPaths
}

// Create the container.
c, err := client.ContainerCreate(context.Background(),
&config,
&hc,
&network.NetworkingConfig{},
name,
)
assert.NilError(t, err)

checkInspect(t, ctx, name, tc.expected)

// Start the container.
err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
assert.NilError(t, err)

poll.WaitOn(t, ctr.IsInState(ctx, client, c.ID, "exited"), poll.WithDelay(100*time.Millisecond))

checkInspect(t, ctx, name, tc.expected)
}
}
0