github.com/ssdev-go/moby@v17.12.1-ce-rc2+incompatible/integration/plugin/authz/authz_plugin_v2_test.go (about)

     1  // +build !windows
     2  
     3  package authz
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/docker/docker/api/types"
    14  	"github.com/docker/docker/api/types/container"
    15  	"github.com/docker/docker/api/types/filters"
    16  	networktypes "github.com/docker/docker/api/types/network"
    17  	volumetypes "github.com/docker/docker/api/types/volume"
    18  	"github.com/docker/docker/client"
    19  	"github.com/docker/docker/integration/util/requirement"
    20  	"github.com/gotestyourself/gotestyourself/skip"
    21  	"github.com/stretchr/testify/require"
    22  )
    23  
    24  var (
    25  	authzPluginName            = "riyaz/authz-no-volume-plugin"
    26  	authzPluginTag             = "latest"
    27  	authzPluginNameWithTag     = authzPluginName + ":" + authzPluginTag
    28  	authzPluginBadManifestName = "riyaz/authz-plugin-bad-manifest"
    29  	nonexistentAuthzPluginName = "riyaz/nonexistent-authz-plugin"
    30  )
    31  
    32  func setupTestV2(t *testing.T) func() {
    33  	skip.IfCondition(t, testEnv.DaemonInfo.OSType != "linux")
    34  	skip.IfCondition(t, !requirement.HasHubConnectivity(t))
    35  
    36  	teardown := setupTest(t)
    37  
    38  	d.Start(t)
    39  
    40  	return teardown
    41  }
    42  
    43  func TestAuthZPluginV2AllowNonVolumeRequest(t *testing.T) {
    44  	skip.IfCondition(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
    45  	defer setupTestV2(t)()
    46  
    47  	client, err := d.NewClient()
    48  	require.Nil(t, err)
    49  
    50  	// Install authz plugin
    51  	err = pluginInstallGrantAllPermissions(client, authzPluginNameWithTag)
    52  	require.Nil(t, err)
    53  	// start the daemon with the plugin and load busybox, --net=none build fails otherwise
    54  	// because it needs to pull busybox
    55  	d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag)
    56  	d.LoadBusybox(t)
    57  
    58  	// Ensure docker run command and accompanying docker ps are successful
    59  	createResponse, err := client.ContainerCreate(context.Background(), &container.Config{Cmd: []string{"top"}, Image: "busybox"}, &container.HostConfig{}, &networktypes.NetworkingConfig{}, "")
    60  	require.Nil(t, err)
    61  
    62  	err = client.ContainerStart(context.Background(), createResponse.ID, types.ContainerStartOptions{})
    63  	require.Nil(t, err)
    64  
    65  	_, err = client.ContainerInspect(context.Background(), createResponse.ID)
    66  	require.Nil(t, err)
    67  }
    68  
    69  func TestAuthZPluginV2Disable(t *testing.T) {
    70  	skip.IfCondition(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
    71  	defer setupTestV2(t)()
    72  
    73  	client, err := d.NewClient()
    74  	require.Nil(t, err)
    75  
    76  	// Install authz plugin
    77  	err = pluginInstallGrantAllPermissions(client, authzPluginNameWithTag)
    78  	require.Nil(t, err)
    79  
    80  	d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag)
    81  	d.LoadBusybox(t)
    82  
    83  	_, err = client.VolumeCreate(context.Background(), volumetypes.VolumesCreateBody{Driver: "local"})
    84  	require.NotNil(t, err)
    85  	require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
    86  
    87  	// disable the plugin
    88  	err = client.PluginDisable(context.Background(), authzPluginNameWithTag, types.PluginDisableOptions{})
    89  	require.Nil(t, err)
    90  
    91  	// now test to see if the docker api works.
    92  	_, err = client.VolumeCreate(context.Background(), volumetypes.VolumesCreateBody{Driver: "local"})
    93  	require.Nil(t, err)
    94  }
    95  
    96  func TestAuthZPluginV2RejectVolumeRequests(t *testing.T) {
    97  	skip.IfCondition(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
    98  	defer setupTestV2(t)()
    99  
   100  	client, err := d.NewClient()
   101  	require.Nil(t, err)
   102  
   103  	// Install authz plugin
   104  	err = pluginInstallGrantAllPermissions(client, authzPluginNameWithTag)
   105  	require.Nil(t, err)
   106  
   107  	// restart the daemon with the plugin
   108  	d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag)
   109  
   110  	_, err = client.VolumeCreate(context.Background(), volumetypes.VolumesCreateBody{Driver: "local"})
   111  	require.NotNil(t, err)
   112  	require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
   113  
   114  	_, err = client.VolumeList(context.Background(), filters.Args{})
   115  	require.NotNil(t, err)
   116  	require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
   117  
   118  	// The plugin will block the command before it can determine the volume does not exist
   119  	err = client.VolumeRemove(context.Background(), "test", false)
   120  	require.NotNil(t, err)
   121  	require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
   122  
   123  	_, err = client.VolumeInspect(context.Background(), "test")
   124  	require.NotNil(t, err)
   125  	require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
   126  
   127  	_, err = client.VolumesPrune(context.Background(), filters.Args{})
   128  	require.NotNil(t, err)
   129  	require.True(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
   130  }
   131  
   132  func TestAuthZPluginV2BadManifestFailsDaemonStart(t *testing.T) {
   133  	skip.IfCondition(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
   134  	defer setupTestV2(t)()
   135  
   136  	client, err := d.NewClient()
   137  	require.Nil(t, err)
   138  
   139  	// Install authz plugin with bad manifest
   140  	err = pluginInstallGrantAllPermissions(client, authzPluginBadManifestName)
   141  	require.Nil(t, err)
   142  
   143  	// start the daemon with the plugin, it will error
   144  	err = d.RestartWithError("--authorization-plugin=" + authzPluginBadManifestName)
   145  	require.NotNil(t, err)
   146  
   147  	// restarting the daemon without requiring the plugin will succeed
   148  	d.Start(t)
   149  }
   150  
   151  func TestAuthZPluginV2NonexistentFailsDaemonStart(t *testing.T) {
   152  	defer setupTestV2(t)()
   153  
   154  	// start the daemon with a non-existent authz plugin, it will error
   155  	err := d.RestartWithError("--authorization-plugin=" + nonexistentAuthzPluginName)
   156  	require.NotNil(t, err)
   157  
   158  	// restarting the daemon without requiring the plugin will succeed
   159  	d.Start(t)
   160  }
   161  
   162  func pluginInstallGrantAllPermissions(client client.APIClient, name string) error {
   163  	ctx := context.Background()
   164  	options := types.PluginInstallOptions{
   165  		RemoteRef:            name,
   166  		AcceptAllPermissions: true,
   167  	}
   168  	responseReader, err := client.PluginInstall(ctx, "", options)
   169  	if err != nil {
   170  		return err
   171  	}
   172  	defer responseReader.Close()
   173  	// we have to read the response out here because the client API
   174  	// actually starts a goroutine which we can only be sure has
   175  	// completed when we get EOF from reading responseBody
   176  	_, err = ioutil.ReadAll(responseReader)
   177  	return err
   178  }