github.com/ssdev-go/moby@v17.12.1-ce-rc2+incompatible/integration/plugin/authz/main_test.go (about) 1 // +build !windows 2 3 package authz 4 5 import ( 6 "encoding/json" 7 "fmt" 8 "io/ioutil" 9 "net/http" 10 "net/http/httptest" 11 "os" 12 "strings" 13 "testing" 14 15 "github.com/docker/docker/integration-cli/daemon" 16 "github.com/docker/docker/internal/test/environment" 17 "github.com/docker/docker/pkg/authorization" 18 "github.com/docker/docker/pkg/plugins" 19 ) 20 21 var ( 22 testEnv *environment.Execution 23 d *daemon.Daemon 24 server *httptest.Server 25 ) 26 27 const dockerdBinary = "dockerd" 28 29 func TestMain(m *testing.M) { 30 var err error 31 testEnv, err = environment.New() 32 if err != nil { 33 fmt.Println(err) 34 os.Exit(1) 35 } 36 err = environment.EnsureFrozenImagesLinux(testEnv) 37 if err != nil { 38 fmt.Println(err) 39 os.Exit(1) 40 } 41 42 testEnv.Print() 43 setupSuite() 44 exitCode := m.Run() 45 teardownSuite() 46 47 os.Exit(exitCode) 48 } 49 50 func setupTest(t *testing.T) func() { 51 environment.ProtectAll(t, testEnv) 52 53 d = daemon.New(t, "", dockerdBinary, daemon.Config{ 54 Experimental: testEnv.DaemonInfo.ExperimentalBuild, 55 }) 56 57 return func() { 58 if d != nil { 59 d.Stop(t) 60 } 61 testEnv.Clean(t) 62 } 63 } 64 65 func setupSuite() { 66 mux := http.NewServeMux() 67 server = httptest.NewServer(mux) 68 69 mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) { 70 b, err := json.Marshal(plugins.Manifest{Implements: []string{authorization.AuthZApiImplements}}) 71 if err != nil { 72 panic("could not marshal json for /Plugin.Activate: " + err.Error()) 73 } 74 w.Write(b) 75 }) 76 77 mux.HandleFunc("/AuthZPlugin.AuthZReq", func(w http.ResponseWriter, r *http.Request) { 78 defer r.Body.Close() 79 body, err := ioutil.ReadAll(r.Body) 80 if err != nil { 81 panic("could not read body for /AuthZPlugin.AuthZReq: " + err.Error()) 82 } 83 authReq := authorization.Request{} 84 err = json.Unmarshal(body, &authReq) 85 if err != nil { 86 panic("could not unmarshal json for /AuthZPlugin.AuthZReq: " + err.Error()) 87 } 88 89 assertBody(authReq.RequestURI, authReq.RequestHeaders, authReq.RequestBody) 90 assertAuthHeaders(authReq.RequestHeaders) 91 92 // Count only server version api 93 if strings.HasSuffix(authReq.RequestURI, serverVersionAPI) { 94 ctrl.versionReqCount++ 95 } 96 97 ctrl.requestsURIs = append(ctrl.requestsURIs, authReq.RequestURI) 98 99 reqRes := ctrl.reqRes 100 if isAllowed(authReq.RequestURI) { 101 reqRes = authorization.Response{Allow: true} 102 } 103 if reqRes.Err != "" { 104 w.WriteHeader(http.StatusInternalServerError) 105 } 106 b, err := json.Marshal(reqRes) 107 if err != nil { 108 panic("could not marshal json for /AuthZPlugin.AuthZReq: " + err.Error()) 109 } 110 111 ctrl.reqUser = authReq.User 112 w.Write(b) 113 }) 114 115 mux.HandleFunc("/AuthZPlugin.AuthZRes", func(w http.ResponseWriter, r *http.Request) { 116 defer r.Body.Close() 117 body, err := ioutil.ReadAll(r.Body) 118 if err != nil { 119 panic("could not read body for /AuthZPlugin.AuthZRes: " + err.Error()) 120 } 121 authReq := authorization.Request{} 122 err = json.Unmarshal(body, &authReq) 123 if err != nil { 124 panic("could not unmarshal json for /AuthZPlugin.AuthZRes: " + err.Error()) 125 } 126 127 assertBody(authReq.RequestURI, authReq.ResponseHeaders, authReq.ResponseBody) 128 assertAuthHeaders(authReq.ResponseHeaders) 129 130 // Count only server version api 131 if strings.HasSuffix(authReq.RequestURI, serverVersionAPI) { 132 ctrl.versionResCount++ 133 } 134 resRes := ctrl.resRes 135 if isAllowed(authReq.RequestURI) { 136 resRes = authorization.Response{Allow: true} 137 } 138 if resRes.Err != "" { 139 w.WriteHeader(http.StatusInternalServerError) 140 } 141 b, err := json.Marshal(resRes) 142 if err != nil { 143 panic("could not marshal json for /AuthZPlugin.AuthZRes: " + err.Error()) 144 } 145 ctrl.resUser = authReq.User 146 w.Write(b) 147 }) 148 } 149 150 func teardownSuite() { 151 if server == nil { 152 return 153 } 154 155 server.Close() 156 } 157 158 // assertAuthHeaders validates authentication headers are removed 159 func assertAuthHeaders(headers map[string]string) error { 160 for k := range headers { 161 if strings.Contains(strings.ToLower(k), "auth") || strings.Contains(strings.ToLower(k), "x-registry") { 162 panic(fmt.Sprintf("Found authentication headers in request '%v'", headers)) 163 } 164 } 165 return nil 166 } 167 168 // assertBody asserts that body is removed for non text/json requests 169 func assertBody(requestURI string, headers map[string]string, body []byte) { 170 if strings.Contains(strings.ToLower(requestURI), "auth") && len(body) > 0 { 171 panic("Body included for authentication endpoint " + string(body)) 172 } 173 174 for k, v := range headers { 175 if strings.EqualFold(k, "Content-Type") && strings.HasPrefix(v, "text/") || v == "application/json" { 176 return 177 } 178 } 179 if len(body) > 0 { 180 panic(fmt.Sprintf("Body included while it should not (Headers: '%v')", headers)) 181 } 182 }