authz_plugin_v2_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //go:build !windows
  2. // +build !windows
  3. package authz // import "github.com/docker/docker/integration/plugin/authz"
  4. import (
  5. "context"
  6. "fmt"
  7. "io"
  8. "os"
  9. "strings"
  10. "testing"
  11. "github.com/docker/docker/api/types"
  12. "github.com/docker/docker/api/types/filters"
  13. "github.com/docker/docker/api/types/volume"
  14. "github.com/docker/docker/client"
  15. "github.com/docker/docker/integration/internal/container"
  16. "github.com/docker/docker/integration/internal/requirement"
  17. "gotest.tools/v3/assert"
  18. "gotest.tools/v3/skip"
  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.If(t, testEnv.DaemonInfo.OSType == "windows")
  29. skip.If(t, !requirement.HasHubConnectivity(t))
  30. teardown := setupTest(t)
  31. d.Start(t)
  32. return teardown
  33. }
  34. func TestAuthZPluginV2AllowNonVolumeRequest(t *testing.T) {
  35. skip.If(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
  36. defer setupTestV2(t)()
  37. c := d.NewClientT(t)
  38. ctx := context.Background()
  39. // Install authz plugin
  40. err := pluginInstallGrantAllPermissions(c, authzPluginNameWithTag)
  41. assert.NilError(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. cID := container.Run(ctx, t, c)
  48. _, err = c.ContainerInspect(ctx, cID)
  49. assert.NilError(t, err)
  50. }
  51. func TestAuthZPluginV2Disable(t *testing.T) {
  52. skip.If(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
  53. defer setupTestV2(t)()
  54. c := d.NewClientT(t)
  55. // Install authz plugin
  56. err := pluginInstallGrantAllPermissions(c, authzPluginNameWithTag)
  57. assert.NilError(t, err)
  58. d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag)
  59. d.LoadBusybox(t)
  60. _, err = c.VolumeCreate(context.Background(), volume.CreateOptions{Driver: "local"})
  61. assert.Assert(t, err != nil)
  62. assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
  63. // disable the plugin
  64. err = c.PluginDisable(context.Background(), authzPluginNameWithTag, types.PluginDisableOptions{})
  65. assert.NilError(t, err)
  66. // now test to see if the docker api works.
  67. _, err = c.VolumeCreate(context.Background(), volume.CreateOptions{Driver: "local"})
  68. assert.NilError(t, err)
  69. }
  70. func TestAuthZPluginV2RejectVolumeRequests(t *testing.T) {
  71. skip.If(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
  72. defer setupTestV2(t)()
  73. c := d.NewClientT(t)
  74. // Install authz plugin
  75. err := pluginInstallGrantAllPermissions(c, authzPluginNameWithTag)
  76. assert.NilError(t, err)
  77. // restart the daemon with the plugin
  78. d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag)
  79. _, err = c.VolumeCreate(context.Background(), volume.CreateOptions{Driver: "local"})
  80. assert.Assert(t, err != nil)
  81. assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
  82. _, err = c.VolumeList(context.Background(), volume.ListOptions{})
  83. assert.Assert(t, err != nil)
  84. assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
  85. // The plugin will block the command before it can determine the volume does not exist
  86. err = c.VolumeRemove(context.Background(), "test", false)
  87. assert.Assert(t, err != nil)
  88. assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
  89. _, err = c.VolumeInspect(context.Background(), "test")
  90. assert.Assert(t, err != nil)
  91. assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
  92. _, err = c.VolumesPrune(context.Background(), filters.Args{})
  93. assert.Assert(t, err != nil)
  94. assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
  95. }
  96. func TestAuthZPluginV2BadManifestFailsDaemonStart(t *testing.T) {
  97. skip.If(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
  98. defer setupTestV2(t)()
  99. c := d.NewClientT(t)
  100. // Install authz plugin with bad manifest
  101. err := pluginInstallGrantAllPermissions(c, authzPluginBadManifestName)
  102. assert.NilError(t, err)
  103. // start the daemon with the plugin, it will error
  104. err = d.RestartWithError("--authorization-plugin=" + authzPluginBadManifestName)
  105. assert.Assert(t, err != nil)
  106. // restarting the daemon without requiring the plugin will succeed
  107. d.Start(t)
  108. }
  109. func TestAuthZPluginV2NonexistentFailsDaemonStart(t *testing.T) {
  110. defer setupTestV2(t)()
  111. // start the daemon with a non-existent authz plugin, it will error
  112. err := d.RestartWithError("--authorization-plugin=" + nonexistentAuthzPluginName)
  113. assert.Assert(t, err != nil)
  114. // restarting the daemon without requiring the plugin will succeed
  115. d.Start(t)
  116. }
  117. func pluginInstallGrantAllPermissions(client client.APIClient, name string) error {
  118. ctx := context.Background()
  119. options := types.PluginInstallOptions{
  120. RemoteRef: name,
  121. AcceptAllPermissions: true,
  122. }
  123. responseReader, err := client.PluginInstall(ctx, "", options)
  124. if err != nil {
  125. return err
  126. }
  127. defer responseReader.Close()
  128. // we have to read the response out here because the client API
  129. // actually starts a goroutine which we can only be sure has
  130. // completed when we get EOF from reading responseBody
  131. _, err = io.ReadAll(responseReader)
  132. return err
  133. }