diff --git a/authorization/authz.go b/authorization/authz.go index daebbcb..0388391 100644 --- a/authorization/authz.go +++ b/authorization/authz.go @@ -26,7 +26,13 @@ import ( // For response manipulation, the response from each plugin is piped between plugins. Plugin execution order // is determined according to daemon parameters func NewCtx(authZPlugins []Plugin, user, userAuthNMethod, requestMethod, requestURI string) *Ctx { - return &Ctx{plugins: authZPlugins, user: user, userAuthNMethod: userAuthNMethod, requestMethod: requestMethod, requestURI: requestURI} + return &Ctx{ + plugins: authZPlugins, + user: user, + userAuthNMethod: userAuthNMethod, + requestMethod: requestMethod, + requestURI: requestURI, + } } // Ctx stores a a single request-response interaction context @@ -41,27 +47,26 @@ type Ctx struct { } // AuthZRequest authorized the request to the docker daemon using authZ plugins -func (a *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) (err error) { - +func (a *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) error { var body []byte if sendBody(a.requestURI, r.Header) { - var drainedBody io.ReadCloser + var ( + err error + drainedBody io.ReadCloser + ) drainedBody, r.Body, err = drainBody(r.Body) if err != nil { return err } - body, err = ioutil.ReadAll(drainedBody) defer drainedBody.Close() - + body, err = ioutil.ReadAll(drainedBody) if err != nil { return err } } var h bytes.Buffer - err = r.Header.Write(&h) - - if err != nil { + if err := r.Header.Write(&h); err != nil { return err } @@ -74,9 +79,7 @@ func (a *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) (err error) { RequestHeaders: headers(r.Header)} for _, plugin := range a.plugins { - authRes, err := plugin.AuthZRequest(a.authReq) - if err != nil { return err } @@ -91,7 +94,6 @@ func (a *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) (err error) { // AuthZResponse authorized and manipulates the response from docker daemon using authZ plugins func (a *Ctx) AuthZResponse(rm ResponseModifier, r *http.Request) error { - a.authReq.ResponseStatusCode = rm.StatusCode() a.authReq.ResponseHeaders = headers(rm.Header()) @@ -100,9 +102,7 @@ func (a *Ctx) AuthZResponse(rm ResponseModifier, r *http.Request) error { } for _, plugin := range a.plugins { - authRes, err := plugin.AuthZResponse(a.authReq) - if err != nil { return err } @@ -119,12 +119,12 @@ func (a *Ctx) AuthZResponse(rm ResponseModifier, r *http.Request) error { // drainBody dump the body, it reads the body data into memory and // see go sources /go/src/net/http/httputil/dump.go -func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) { +func drainBody(b io.ReadCloser) (io.ReadCloser, io.ReadCloser, error) { var buf bytes.Buffer - if _, err = buf.ReadFrom(b); err != nil { + if _, err := buf.ReadFrom(b); err != nil { return nil, nil, err } - if err = b.Close(); err != nil { + if err := b.Close(); err != nil { return nil, nil, err } return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil @@ -132,7 +132,6 @@ func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) { // sendBody returns true when request/response body should be sent to AuthZPlugin func sendBody(url string, header http.Header) bool { - // Skip body for auth endpoint if strings.HasSuffix(url, "/auth") { return false diff --git a/authorization/authz_test.go b/authorization/authz_test.go index 47cf401..f1c844c 100644 --- a/authorization/authz_test.go +++ b/authorization/authz_test.go @@ -2,10 +2,6 @@ package authorization import ( "encoding/json" - "fmt" - "github.com/docker/docker/pkg/plugins" - "github.com/docker/docker/pkg/tlsconfig" - "github.com/gorilla/mux" "io/ioutil" "log" "net" @@ -15,12 +11,15 @@ import ( "path" "reflect" "testing" + + "github.com/docker/docker/pkg/plugins" + "github.com/docker/docker/pkg/tlsconfig" + "github.com/gorilla/mux" ) const pluginAddress = "authzplugin.sock" func TestAuthZRequestPlugin(t *testing.T) { - server := authZPluginTestServer{t: t} go server.start() defer server.stop() @@ -40,7 +39,6 @@ func TestAuthZRequestPlugin(t *testing.T) { } actualResponse, err := authZPlugin.AuthZRequest(&request) - if err != nil { t.Fatalf("Failed to authorize request %v", err) } @@ -54,7 +52,6 @@ func TestAuthZRequestPlugin(t *testing.T) { } func TestAuthZResponsePlugin(t *testing.T) { - server := authZPluginTestServer{t: t} go server.start() defer server.stop() @@ -71,7 +68,6 @@ func TestAuthZResponsePlugin(t *testing.T) { } actualResponse, err := authZPlugin.AuthZResponse(&request) - if err != nil { t.Fatalf("Failed to authorize request %v", err) } @@ -85,7 +81,6 @@ func TestAuthZResponsePlugin(t *testing.T) { } func TestResponseModifier(t *testing.T) { - r := httptest.NewRecorder() m := NewResponseModifier(r) m.Header().Set("h1", "v1") @@ -105,7 +100,6 @@ func TestResponseModifier(t *testing.T) { } func TestResponseModifierOverride(t *testing.T) { - r := httptest.NewRecorder() m := NewResponseModifier(r) m.Header().Set("h1", "v1") @@ -137,18 +131,12 @@ func TestResponseModifierOverride(t *testing.T) { // createTestPlugin creates a new sample authorization plugin func createTestPlugin(t *testing.T) *authorizationPlugin { plugin := &plugins.Plugin{Name: "authz"} - var err error pwd, err := os.Getwd() - if err != nil { - fmt.Println(err) - os.Exit(1) - } if err != nil { log.Fatal(err) } plugin.Client, err = plugins.NewClient("unix:///"+path.Join(pwd, pluginAddress), tlsconfig.Options{InsecureSkipVerify: true}) - if err != nil { t.Fatalf("Failed to create client %v", err) } @@ -186,9 +174,7 @@ func (t *authZPluginTestServer) start() { // stop stops the test server that implements the plugin func (t *authZPluginTestServer) stop() { - os.Remove(pluginAddress) - if t.listener != nil { t.listener.Close() } @@ -196,9 +182,7 @@ func (t *authZPluginTestServer) stop() { // auth is a used to record/replay the authentication api messages func (t *authZPluginTestServer) auth(w http.ResponseWriter, r *http.Request) { - t.recordedRequest = Request{} - defer r.Body.Close() body, err := ioutil.ReadAll(r.Body) json.Unmarshal(body, &t.recordedRequest) @@ -207,11 +191,9 @@ func (t *authZPluginTestServer) auth(w http.ResponseWriter, r *http.Request) { log.Fatal(err) } w.Write(b) - } func (t *authZPluginTestServer) activate(w http.ResponseWriter, r *http.Request) { - b, err := json.Marshal(plugins.Manifest{Implements: []string{AuthZApiImplements}}) if err != nil { log.Fatal(err) diff --git a/authorization/plugin.go b/authorization/plugin.go index cab571e..3b47632 100644 --- a/authorization/plugin.go +++ b/authorization/plugin.go @@ -8,12 +8,11 @@ import ( // Plugin allows third party plugins to authorize requests and responses // in the context of docker API type Plugin interface { - // AuthZRequest authorize the request from the client to the daemon - AuthZRequest(authReq *Request) (authRes *Response, err error) + AuthZRequest(*Request) (*Response, error) // AuthZResponse authorize the response from the daemon to the client - AuthZResponse(authReq *Request) (authRes *Response, err error) + AuthZResponse(*Request) (*Response, error) } // NewPlugins constructs and initialize the authorization plugins based on plugin names @@ -35,38 +34,30 @@ func newAuthorizationPlugin(name string) Plugin { return &authorizationPlugin{name: name} } -func (a *authorizationPlugin) AuthZRequest(authReq *Request) (authRes *Response, err error) { - +func (a *authorizationPlugin) AuthZRequest(authReq *Request) (*Response, error) { logrus.Debugf("AuthZ requset using plugins %s", a.name) - err = a.initPlugin() - if err != nil { + if err := a.initPlugin(); err != nil { return nil, err } - authRes = &Response{} - err = a.plugin.Client.Call(AuthZApiRequest, authReq, authRes) - - if err != nil { + authRes := &Response{} + if err := a.plugin.Client.Call(AuthZApiRequest, authReq, authRes); err != nil { return nil, err } return authRes, nil } -func (a *authorizationPlugin) AuthZResponse(authReq *Request) (authRes *Response, err error) { - +func (a *authorizationPlugin) AuthZResponse(authReq *Request) (*Response, error) { logrus.Debugf("AuthZ response using plugins %s", a.name) - err = a.initPlugin() - if err != nil { + if err := a.initPlugin(); err != nil { return nil, err } - authRes = &Response{} - err = a.plugin.Client.Call(AuthZApiResponse, authReq, authRes) - - if err != nil { + authRes := &Response{} + if err := a.plugin.Client.Call(AuthZApiResponse, authReq, authRes); err != nil { return nil, err } @@ -74,10 +65,10 @@ func (a *authorizationPlugin) AuthZResponse(authReq *Request) (authRes *Response } // initPlugin initialize the authorization plugin if needed -func (a *authorizationPlugin) initPlugin() (err error) { - +func (a *authorizationPlugin) initPlugin() error { // Lazy loading of plugins if a.plugin == nil { + var err error a.plugin, err = plugins.Get(a.name, AuthZApiImplements) if err != nil { return err diff --git a/authorization/response.go b/authorization/response.go index ee4cb2d..8acbcd1 100644 --- a/authorization/response.go +++ b/authorization/response.go @@ -81,9 +81,7 @@ func (rm *responseModifier) OverrideStatusCode(statusCode int) { // Override replace the headers of the HTTP reply func (rm *responseModifier) OverrideHeader(b []byte) error { header := http.Header{} - err := json.Unmarshal(b, &header) - - if err != nil { + if err := json.Unmarshal(b, &header); err != nil { return err } rm.header = header @@ -103,8 +101,7 @@ func (rm *responseModifier) RawBody() []byte { func (rm *responseModifier) RawHeaders() ([]byte, error) { var b bytes.Buffer - err := rm.header.Write(&b) - if err != nil { + if err := rm.header.Write(&b); err != nil { return nil, err } return b.Bytes(), nil @@ -121,7 +118,6 @@ func (rm *responseModifier) Hijack() (net.Conn, *bufio.ReadWriter, error) { // Flush flushes all data to the HTTP response func (rm *responseModifier) Flush() error { - // Copy the status code if rm.statusCode > 0 { rm.rw.WriteHeader(rm.statusCode)