mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
integration/plugin/authz: inline CLI work-alike library
I strongly disagree with the design of this pull request. Signed-off-by: David Sheets <dsheets@docker.com>
This commit is contained in:
parent
928b0631c9
commit
1574d91463
8 changed files with 163 additions and 400 deletions
|
@ -15,7 +15,7 @@ source "$SCRIPTDIR/make/.go-autogen"
|
|||
|
||||
integration_api_dirs=${TEST_INTEGRATION_DIR:-"$(
|
||||
find ./integration -type d |
|
||||
grep -vE '^(./integration($|/util|/internal|/testdata|/plugin$))')"}
|
||||
grep -vE '^(./integration($|/util|/testdata|/plugin$))')"}
|
||||
|
||||
run_test_integration() {
|
||||
[[ "$TESTFLAGS" != *-check.f* ]] && run_test_integration_suites
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
networktypes "github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
// CreateVMemLabel creates a container with the supplied parameters
|
||||
func CreateVMemLabel(client client.APIClient, v []string, memoryMB int, labels map[string]string, img string, cmd []string) (string, error) {
|
||||
ctx := context.Background()
|
||||
config := container.Config{
|
||||
Cmd: cmd,
|
||||
Image: img,
|
||||
Labels: labels,
|
||||
}
|
||||
hostConfig := container.HostConfig{
|
||||
Binds: v,
|
||||
Resources: container.Resources{
|
||||
Memory: int64(memoryMB * 1024 * 1024),
|
||||
},
|
||||
}
|
||||
networkingConfig := networktypes.NetworkingConfig{}
|
||||
name := ""
|
||||
response, err := client.ContainerCreate(ctx, &config, &hostConfig, &networkingConfig, name)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return response.ID, nil
|
||||
}
|
||||
|
||||
// Run runs the command provided in the container image named
|
||||
func Run(client client.APIClient, img string, cmd []string) (string, error) {
|
||||
return RunV(client, []string{}, img, cmd)
|
||||
}
|
||||
|
||||
// RunV runs the command provided in the container image named with
|
||||
// the equivalent of -v bind mounts
|
||||
func RunV(client client.APIClient, v []string, img string, cmd []string) (string, error) {
|
||||
return RunVMem(client, v, 0, img, cmd)
|
||||
}
|
||||
|
||||
// RunVMem runs the command provided in the container image named with
|
||||
// the equivalent of -v bind mounts and a specified memory limit
|
||||
func RunVMem(client client.APIClient, v []string, memoryMB int, img string, cmd []string) (string, error) {
|
||||
return RunVMemLabel(client, v, memoryMB, map[string]string{}, img, cmd)
|
||||
}
|
||||
|
||||
// RunVLabel runs the command provided in the container image named
|
||||
// with the equivalent of -v bind mounts and the specified labels
|
||||
func RunVLabel(client client.APIClient, v []string, labels map[string]string, img string, cmd []string) (string, error) {
|
||||
return RunVMemLabel(client, v, 0, labels, img, cmd)
|
||||
}
|
||||
|
||||
// RunVMemLabel runs the command provided in the container image named
|
||||
// with the equivalent of -v bind mounts, a specified memory limit,
|
||||
// and the specified labels
|
||||
func RunVMemLabel(client client.APIClient, v []string, memoryMB int, labels map[string]string, img string, cmd []string) (string, error) {
|
||||
containerID, err := CreateVMemLabel(client, v, memoryMB, labels, img, cmd)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
if err := client.ContainerStart(ctx, containerID, types.ContainerStartOptions{}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return containerID, nil
|
||||
}
|
||||
|
||||
// Wait waits until the named container has exited
|
||||
func Wait(client client.APIClient, container string) (int64, error) {
|
||||
resultC, errC := client.ContainerWait(context.Background(), container, "")
|
||||
|
||||
select {
|
||||
case result := <-resultC:
|
||||
return result.StatusCode, nil
|
||||
case err := <-errC:
|
||||
return -1, err
|
||||
}
|
||||
}
|
||||
|
||||
// Stop stops the named container
|
||||
func Stop(client client.APIClient, container string) error {
|
||||
timeout := time.Duration(10) * time.Second
|
||||
ctx := context.Background()
|
||||
return client.ContainerStop(ctx, container, &timeout)
|
||||
}
|
||||
|
||||
// Start starts the named container
|
||||
func Start(client client.APIClient, container string) error {
|
||||
ctx := context.Background()
|
||||
return client.ContainerStart(ctx, container, types.ContainerStartOptions{})
|
||||
}
|
||||
|
||||
// Kill kills the named container with SIGKILL
|
||||
func Kill(client client.APIClient, container string) error {
|
||||
ctx := context.Background()
|
||||
return client.ContainerKill(ctx, container, "KILL")
|
||||
}
|
||||
|
||||
// Export exports a container's file system as a tarball
|
||||
func Export(client client.APIClient, path, name string) error {
|
||||
ctx := context.Background()
|
||||
responseReader, err := client.ContainerExport(ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseReader.Close()
|
||||
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.Copy(file, responseReader)
|
||||
return err
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package image
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
// Save saves an image to a tarball names by path
|
||||
func Save(client client.APIClient, path, image string) error {
|
||||
ctx := context.Background()
|
||||
responseReader, err := client.ImageSave(ctx, []string{image})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseReader.Close()
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(file, responseReader)
|
||||
return err
|
||||
}
|
||||
|
||||
// Load loads an image from a tarball named by path
|
||||
func Load(client client.APIClient, path string) error {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
quiet := true
|
||||
ctx := context.Background()
|
||||
response, err := client.ImageLoad(ctx, file, quiet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Import imports the contents of a tarball named by path
|
||||
func Import(client client.APIClient, path string) error {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
options := types.ImageImportOptions{}
|
||||
ref := ""
|
||||
source := types.ImageImportSource{
|
||||
Source: file,
|
||||
SourceName: "-",
|
||||
}
|
||||
ctx := context.Background()
|
||||
responseReader, err := client.ImageImport(ctx, source, ref, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseReader.Close()
|
||||
return nil
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
// InstallGrantAllPermissions installs the plugin named and grants it
|
||||
// all permissions it may require
|
||||
func InstallGrantAllPermissions(client client.APIClient, name string) error {
|
||||
ctx := context.Background()
|
||||
options := types.PluginInstallOptions{
|
||||
RemoteRef: name,
|
||||
AcceptAllPermissions: true,
|
||||
}
|
||||
responseReader, err := client.PluginInstall(ctx, "", options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseReader.Close()
|
||||
// we have to read the response out here because the client API
|
||||
// actually starts a goroutine which we can only be sure has
|
||||
// completed when we get EOF from reading responseBody
|
||||
_, err = ioutil.ReadAll(responseReader)
|
||||
return err
|
||||
}
|
||||
|
||||
// Enable enables the named plugin
|
||||
func Enable(client client.APIClient, name string) error {
|
||||
ctx := context.Background()
|
||||
options := types.PluginEnableOptions{}
|
||||
return client.PluginEnable(ctx, name, options)
|
||||
}
|
||||
|
||||
// Disable disables the named plugin
|
||||
func Disable(client client.APIClient, name string) error {
|
||||
ctx := context.Background()
|
||||
options := types.PluginDisableOptions{}
|
||||
return client.PluginDisable(ctx, name, options)
|
||||
}
|
||||
|
||||
// Rm removes the named plugin
|
||||
func Rm(client client.APIClient, name string) error {
|
||||
return remove(client, name, false)
|
||||
}
|
||||
|
||||
// RmF forces the removal of the named plugin
|
||||
func RmF(client client.APIClient, name string) error {
|
||||
return remove(client, name, true)
|
||||
}
|
||||
|
||||
func remove(client client.APIClient, name string, force bool) error {
|
||||
ctx := context.Background()
|
||||
options := types.PluginRemoveOptions{Force: force}
|
||||
return client.PluginRemove(ctx, name, options)
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Time provides the current time on the daemon host
|
||||
func Time(t *testing.T, client client.APIClient, testEnv *environment.Execution) time.Time {
|
||||
if testEnv.IsLocalDaemon() {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
info, err := client.Info(ctx)
|
||||
require.Nil(t, err)
|
||||
|
||||
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
||||
require.Nil(t, err, "invalid time format in GET /info response")
|
||||
return dt
|
||||
}
|
||||
|
||||
// Version provides the version of the daemon
|
||||
func Version(client client.APIClient) (types.Version, error) {
|
||||
ctx := context.Background()
|
||||
return client.ServerVersion(ctx)
|
||||
}
|
||||
|
||||
// EventsSince returns event and error streams since a provided time
|
||||
func EventsSince(client client.APIClient, since string) (<-chan events.Message, <-chan error, func()) {
|
||||
eventOptions := types.EventsOptions{
|
||||
Since: since,
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
events, errs := client.Events(ctx, eventOptions)
|
||||
|
||||
return events, errs, cancel
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package volume
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
volumetypes "github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
// Create creates a volume using the named driver with the specified options
|
||||
func Create(client client.APIClient, driver string, opts map[string]string) (string, error) {
|
||||
volReq := volumetypes.VolumesCreateBody{
|
||||
Driver: driver,
|
||||
DriverOpts: opts,
|
||||
Name: "",
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
vol, err := client.VolumeCreate(ctx, volReq)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return vol.Name, nil
|
||||
}
|
||||
|
||||
// Rm removes the volume named
|
||||
func Rm(client client.APIClient, name string) error {
|
||||
ctx := context.Background()
|
||||
return client.VolumeRemove(ctx, name, false)
|
||||
}
|
||||
|
||||
// Ls lists the volumes available
|
||||
func Ls(client client.APIClient) ([]string, error) {
|
||||
ctx := context.Background()
|
||||
volumes, err := client.VolumeList(ctx, filters.Args{})
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
names := []string{}
|
||||
for _, volume := range volumes.Volumes {
|
||||
names = append(names, volume.Name)
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// Prune removes all volumes not used by at least one container
|
||||
func Prune(client client.APIClient) (types.VolumesPruneReport, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
return client.VolumesPrune(ctx, filters.Args{})
|
||||
}
|
||||
|
||||
// Inspect retrieves detailed information about the named volume
|
||||
func Inspect(client client.APIClient, name string) (types.Volume, error) {
|
||||
ctx := context.Background()
|
||||
return client.VolumeInspect(ctx, name)
|
||||
}
|
|
@ -18,11 +18,13 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
eventtypes "github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/integration/internal/api/container"
|
||||
"github.com/docker/docker/integration/internal/api/image"
|
||||
"github.com/docker/docker/integration/internal/api/system"
|
||||
networktypes "github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/util/request"
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
"github.com/docker/docker/pkg/authorization"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -90,13 +92,16 @@ func TestAuthZPluginAllowRequest(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
|
||||
// Ensure command successful
|
||||
id, err := container.Run(client, "busybox", []string{"top"})
|
||||
createResponse, err := client.ContainerCreate(context.Background(), &container.Config{Cmd: []string{"top"}, Image: "busybox"}, &container.HostConfig{}, &networktypes.NetworkingConfig{}, "")
|
||||
require.Nil(t, err)
|
||||
|
||||
err = client.ContainerStart(context.Background(), createResponse.ID, types.ContainerStartOptions{})
|
||||
require.Nil(t, err)
|
||||
|
||||
assertURIRecorded(t, ctrl.requestsURIs, "/containers/create")
|
||||
assertURIRecorded(t, ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", id))
|
||||
assertURIRecorded(t, ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", createResponse.ID))
|
||||
|
||||
_, err = system.Version(client)
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, ctrl.versionReqCount)
|
||||
require.Equal(t, 1, ctrl.versionResCount)
|
||||
|
@ -127,7 +132,7 @@ func TestAuthZPluginTLS(t *testing.T) {
|
|||
client, err := request.NewTLSAPIClient(t, testDaemonHTTPSAddr, cacertPath, clientCertPath, clientKeyPath)
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = system.Version(client)
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, "client", ctrl.reqUser)
|
||||
|
@ -144,7 +149,7 @@ func TestAuthZPluginDenyRequest(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
|
||||
// Ensure command is blocked
|
||||
_, err = system.Version(client)
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, 1, ctrl.versionReqCount)
|
||||
require.Equal(t, 0, ctrl.versionResCount)
|
||||
|
@ -186,7 +191,7 @@ func TestAuthZPluginDenyResponse(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
|
||||
// Ensure command is blocked
|
||||
_, err = system.Version(client)
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, 1, ctrl.versionReqCount)
|
||||
require.Equal(t, 1, ctrl.versionResCount)
|
||||
|
@ -208,15 +213,19 @@ func TestAuthZPluginAllowEventStream(t *testing.T) {
|
|||
client, err := d.NewClient()
|
||||
require.Nil(t, err)
|
||||
|
||||
startTime := strconv.FormatInt(system.Time(t, client, testEnv).Unix(), 10)
|
||||
events, errs, cancel := system.EventsSince(client, startTime)
|
||||
startTime := strconv.FormatInt(systemTime(t, client, testEnv).Unix(), 10)
|
||||
events, errs, cancel := systemEventsSince(client, startTime)
|
||||
defer cancel()
|
||||
|
||||
// Create a container and wait for the creation events
|
||||
id, err := container.Run(client, "busybox", []string{"top"})
|
||||
createResponse, err := client.ContainerCreate(context.Background(), &container.Config{Cmd: []string{"top"}, Image: "busybox"}, &container.HostConfig{}, &networktypes.NetworkingConfig{}, "")
|
||||
require.Nil(t, err)
|
||||
|
||||
err = client.ContainerStart(context.Background(), createResponse.ID, types.ContainerStartOptions{})
|
||||
require.Nil(t, err)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
c, err := client.ContainerInspect(context.Background(), id)
|
||||
c, err := client.ContainerInspect(context.Background(), createResponse.ID)
|
||||
require.Nil(t, err)
|
||||
if c.State.Running {
|
||||
break
|
||||
|
@ -232,7 +241,7 @@ func TestAuthZPluginAllowEventStream(t *testing.T) {
|
|||
for !created && !started {
|
||||
select {
|
||||
case event := <-events:
|
||||
if event.Type == eventtypes.ContainerEventType && event.Actor.ID == id {
|
||||
if event.Type == eventtypes.ContainerEventType && event.Actor.ID == createResponse.ID {
|
||||
if event.Action == "create" {
|
||||
created = true
|
||||
}
|
||||
|
@ -255,7 +264,31 @@ func TestAuthZPluginAllowEventStream(t *testing.T) {
|
|||
// authorization plugin
|
||||
assertURIRecorded(t, ctrl.requestsURIs, "/events")
|
||||
assertURIRecorded(t, ctrl.requestsURIs, "/containers/create")
|
||||
assertURIRecorded(t, ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", id))
|
||||
assertURIRecorded(t, ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", createResponse.ID))
|
||||
}
|
||||
|
||||
func systemTime(t *testing.T, client client.APIClient, testEnv *environment.Execution) time.Time {
|
||||
if testEnv.IsLocalDaemon() {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
info, err := client.Info(ctx)
|
||||
require.Nil(t, err)
|
||||
|
||||
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
||||
require.Nil(t, err, "invalid time format in GET /info response")
|
||||
return dt
|
||||
}
|
||||
|
||||
func systemEventsSince(client client.APIClient, since string) (<-chan eventtypes.Message, <-chan error, func()) {
|
||||
eventOptions := types.EventsOptions{
|
||||
Since: since,
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
events, errs := client.Events(ctx, eventOptions)
|
||||
|
||||
return events, errs, cancel
|
||||
}
|
||||
|
||||
func TestAuthZPluginErrorResponse(t *testing.T) {
|
||||
|
@ -268,7 +301,7 @@ func TestAuthZPluginErrorResponse(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
|
||||
// Ensure command is blocked
|
||||
_, err = system.Version(client)
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, fmt.Sprintf("Error response from daemon: plugin %s failed with error: %s: %s", testAuthZPlugin, authorization.AuthZApiResponse, errorMessage), err.Error())
|
||||
}
|
||||
|
@ -282,7 +315,7 @@ func TestAuthZPluginErrorRequest(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
|
||||
// Ensure command is blocked
|
||||
_, err = system.Version(client)
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, fmt.Sprintf("Error response from daemon: plugin %s failed with error: %s: %s", testAuthZPlugin, authorization.AuthZApiRequest, errorMessage), err.Error())
|
||||
}
|
||||
|
@ -297,7 +330,7 @@ func TestAuthZPluginEnsureNoDuplicatePluginRegistration(t *testing.T) {
|
|||
client, err := d.NewClient()
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = system.Version(client)
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
require.Nil(t, err)
|
||||
|
||||
// assert plugin is only called once..
|
||||
|
@ -320,19 +353,83 @@ func TestAuthZPluginEnsureLoadImportWorking(t *testing.T) {
|
|||
|
||||
savedImagePath := filepath.Join(tmp, "save.tar")
|
||||
|
||||
err = image.Save(client, savedImagePath, "busybox")
|
||||
err = imageSave(client, savedImagePath, "busybox")
|
||||
require.Nil(t, err)
|
||||
err = image.Load(client, savedImagePath)
|
||||
err = imageLoad(client, savedImagePath)
|
||||
require.Nil(t, err)
|
||||
|
||||
exportedImagePath := filepath.Join(tmp, "export.tar")
|
||||
|
||||
id, err := container.Run(client, "busybox", []string{})
|
||||
createResponse, err := client.ContainerCreate(context.Background(), &container.Config{Cmd: []string{}, Image: "busybox"}, &container.HostConfig{}, &networktypes.NetworkingConfig{}, "")
|
||||
require.Nil(t, err)
|
||||
err = container.Export(client, exportedImagePath, id)
|
||||
|
||||
err = client.ContainerStart(context.Background(), createResponse.ID, types.ContainerStartOptions{})
|
||||
require.Nil(t, err)
|
||||
err = image.Import(client, exportedImagePath)
|
||||
|
||||
responseReader, err := client.ContainerExport(context.Background(), createResponse.ID)
|
||||
require.Nil(t, err)
|
||||
defer responseReader.Close()
|
||||
file, err := os.Create(exportedImagePath)
|
||||
require.Nil(t, err)
|
||||
defer file.Close()
|
||||
_, err = io.Copy(file, responseReader)
|
||||
require.Nil(t, err)
|
||||
|
||||
err = imageImport(client, exportedImagePath)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func imageSave(client client.APIClient, path, image string) error {
|
||||
ctx := context.Background()
|
||||
responseReader, err := client.ImageSave(ctx, []string{image})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseReader.Close()
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(file, responseReader)
|
||||
return err
|
||||
}
|
||||
|
||||
func imageLoad(client client.APIClient, path string) error {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
quiet := true
|
||||
ctx := context.Background()
|
||||
response, err := client.ImageLoad(ctx, file, quiet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func imageImport(client client.APIClient, path string) error {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
options := types.ImageImportOptions{}
|
||||
ref := ""
|
||||
source := types.ImageImportSource{
|
||||
Source: file,
|
||||
SourceName: "-",
|
||||
}
|
||||
ctx := context.Background()
|
||||
responseReader, err := client.ImageImport(ctx, source, ref, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseReader.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestAuthZPluginHeader(t *testing.T) {
|
||||
|
|
|
@ -5,13 +5,17 @@ package authz
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/integration/internal/api/container"
|
||||
"github.com/docker/docker/integration/internal/api/plugin"
|
||||
"github.com/docker/docker/integration/internal/api/volume"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
networktypes "github.com/docker/docker/api/types/network"
|
||||
volumetypes "github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/util/requirement"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -44,7 +48,7 @@ func TestAuthZPluginV2AllowNonVolumeRequest(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
|
||||
// Install authz plugin
|
||||
err = plugin.InstallGrantAllPermissions(client, authzPluginNameWithTag)
|
||||
err = pluginInstallGrantAllPermissions(client, authzPluginNameWithTag)
|
||||
require.Nil(t, err)
|
||||
// start the daemon with the plugin and load busybox, --net=none build fails otherwise
|
||||
// because it needs to pull busybox
|
||||
|
@ -52,10 +56,13 @@ func TestAuthZPluginV2AllowNonVolumeRequest(t *testing.T) {
|
|||
d.LoadBusybox(t)
|
||||
|
||||
// Ensure docker run command and accompanying docker ps are successful
|
||||
id, err := container.Run(client, "busybox", []string{"top"})
|
||||
createResponse, err := client.ContainerCreate(context.Background(), &container.Config{Cmd: []string{"top"}, Image: "busybox"}, &container.HostConfig{}, &networktypes.NetworkingConfig{}, "")
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = client.ContainerInspect(context.Background(), id)
|
||||
err = client.ContainerStart(context.Background(), createResponse.ID, types.ContainerStartOptions{})
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = client.ContainerInspect(context.Background(), createResponse.ID)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
|
@ -67,22 +74,22 @@ func TestAuthZPluginV2Disable(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
|
||||
// Install authz plugin
|
||||
err = plugin.InstallGrantAllPermissions(client, authzPluginNameWithTag)
|
||||
err = pluginInstallGrantAllPermissions(client, authzPluginNameWithTag)
|
||||
require.Nil(t, err)
|
||||
|
||||
d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag)
|
||||
d.LoadBusybox(t)
|
||||
|
||||
_, err = volume.Create(client, "local", map[string]string{})
|
||||
_, err = client.VolumeCreate(context.Background(), volumetypes.VolumesCreateBody{Driver: "local"})
|
||||
require.NotNil(t, err)
|
||||
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
|
||||
// disable the plugin
|
||||
err = plugin.Disable(client, authzPluginNameWithTag)
|
||||
err = client.PluginDisable(context.Background(), authzPluginNameWithTag, types.PluginDisableOptions{})
|
||||
require.Nil(t, err)
|
||||
|
||||
// now test to see if the docker api works.
|
||||
_, err = volume.Create(client, "local", map[string]string{})
|
||||
_, err = client.VolumeCreate(context.Background(), volumetypes.VolumesCreateBody{Driver: "local"})
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
|
@ -94,30 +101,30 @@ func TestAuthZPluginV2RejectVolumeRequests(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
|
||||
// Install authz plugin
|
||||
err = plugin.InstallGrantAllPermissions(client, authzPluginNameWithTag)
|
||||
err = pluginInstallGrantAllPermissions(client, authzPluginNameWithTag)
|
||||
require.Nil(t, err)
|
||||
|
||||
// restart the daemon with the plugin
|
||||
d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag)
|
||||
|
||||
_, err = volume.Create(client, "local", map[string]string{})
|
||||
_, err = client.VolumeCreate(context.Background(), volumetypes.VolumesCreateBody{Driver: "local"})
|
||||
require.NotNil(t, err)
|
||||
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
|
||||
_, err = volume.Ls(client)
|
||||
_, err = client.VolumeList(context.Background(), filters.Args{})
|
||||
require.NotNil(t, err)
|
||||
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
|
||||
// The plugin will block the command before it can determine the volume does not exist
|
||||
err = volume.Rm(client, "test")
|
||||
err = client.VolumeRemove(context.Background(), "test", false)
|
||||
require.NotNil(t, err)
|
||||
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
|
||||
_, err = volume.Inspect(client, "test")
|
||||
_, err = client.VolumeInspect(context.Background(), "test")
|
||||
require.NotNil(t, err)
|
||||
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
|
||||
_, err = volume.Prune(client)
|
||||
_, err = client.VolumesPrune(context.Background(), filters.Args{})
|
||||
require.NotNil(t, err)
|
||||
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
}
|
||||
|
@ -130,7 +137,7 @@ func TestAuthZPluginV2BadManifestFailsDaemonStart(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
|
||||
// Install authz plugin with bad manifest
|
||||
err = plugin.InstallGrantAllPermissions(client, authzPluginBadManifestName)
|
||||
err = pluginInstallGrantAllPermissions(client, authzPluginBadManifestName)
|
||||
require.Nil(t, err)
|
||||
|
||||
// start the daemon with the plugin, it will error
|
||||
|
@ -151,3 +158,21 @@ func TestAuthZPluginV2NonexistentFailsDaemonStart(t *testing.T) {
|
|||
// restarting the daemon without requiring the plugin will succeed
|
||||
d.Start(t)
|
||||
}
|
||||
|
||||
func pluginInstallGrantAllPermissions(client client.APIClient, name string) error {
|
||||
ctx := context.Background()
|
||||
options := types.PluginInstallOptions{
|
||||
RemoteRef: name,
|
||||
AcceptAllPermissions: true,
|
||||
}
|
||||
responseReader, err := client.PluginInstall(ctx, "", options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseReader.Close()
|
||||
// we have to read the response out here because the client API
|
||||
// actually starts a goroutine which we can only be sure has
|
||||
// completed when we get EOF from reading responseBody
|
||||
_, err = ioutil.ReadAll(responseReader)
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue