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 }