authz_plugin_v2_test.go 6.2 KB

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