github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/pkg/authorization/authz_test.go (about)

     1  package authorization
     2  
     3  import (
     4  	"encoding/json"
     5  	"io/ioutil"
     6  	"log"
     7  	"net"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"os"
    11  	"path"
    12  	"reflect"
    13  	"testing"
    14  
    15  	"github.com/docker/docker/pkg/plugins"
    16  	"github.com/docker/go-connections/tlsconfig"
    17  	"github.com/gorilla/mux"
    18  )
    19  
    20  const pluginAddress = "authzplugin.sock"
    21  
    22  func TestAuthZRequestPluginError(t *testing.T) {
    23  	server := authZPluginTestServer{t: t}
    24  	go server.start()
    25  	defer server.stop()
    26  
    27  	authZPlugin := createTestPlugin(t)
    28  
    29  	request := Request{
    30  		User:           "user",
    31  		RequestBody:    []byte("sample body"),
    32  		RequestURI:     "www.authz.com",
    33  		RequestMethod:  "GET",
    34  		RequestHeaders: map[string]string{"header": "value"},
    35  	}
    36  	server.replayResponse = Response{
    37  		Err: "an error",
    38  	}
    39  
    40  	actualResponse, err := authZPlugin.AuthZRequest(&request)
    41  	if err != nil {
    42  		t.Fatalf("Failed to authorize request %v", err)
    43  	}
    44  
    45  	if !reflect.DeepEqual(server.replayResponse, *actualResponse) {
    46  		t.Fatalf("Response must be equal")
    47  	}
    48  	if !reflect.DeepEqual(request, server.recordedRequest) {
    49  		t.Fatalf("Requests must be equal")
    50  	}
    51  }
    52  
    53  func TestAuthZRequestPlugin(t *testing.T) {
    54  	server := authZPluginTestServer{t: t}
    55  	go server.start()
    56  	defer server.stop()
    57  
    58  	authZPlugin := createTestPlugin(t)
    59  
    60  	request := Request{
    61  		User:           "user",
    62  		RequestBody:    []byte("sample body"),
    63  		RequestURI:     "www.authz.com",
    64  		RequestMethod:  "GET",
    65  		RequestHeaders: map[string]string{"header": "value"},
    66  	}
    67  	server.replayResponse = Response{
    68  		Allow: true,
    69  		Msg:   "Sample message",
    70  	}
    71  
    72  	actualResponse, err := authZPlugin.AuthZRequest(&request)
    73  	if err != nil {
    74  		t.Fatalf("Failed to authorize request %v", err)
    75  	}
    76  
    77  	if !reflect.DeepEqual(server.replayResponse, *actualResponse) {
    78  		t.Fatalf("Response must be equal")
    79  	}
    80  	if !reflect.DeepEqual(request, server.recordedRequest) {
    81  		t.Fatalf("Requests must be equal")
    82  	}
    83  }
    84  
    85  func TestAuthZResponsePlugin(t *testing.T) {
    86  	server := authZPluginTestServer{t: t}
    87  	go server.start()
    88  	defer server.stop()
    89  
    90  	authZPlugin := createTestPlugin(t)
    91  
    92  	request := Request{
    93  		User:        "user",
    94  		RequestBody: []byte("sample body"),
    95  	}
    96  	server.replayResponse = Response{
    97  		Allow: true,
    98  		Msg:   "Sample message",
    99  	}
   100  
   101  	actualResponse, err := authZPlugin.AuthZResponse(&request)
   102  	if err != nil {
   103  		t.Fatalf("Failed to authorize request %v", err)
   104  	}
   105  
   106  	if !reflect.DeepEqual(server.replayResponse, *actualResponse) {
   107  		t.Fatalf("Response must be equal")
   108  	}
   109  	if !reflect.DeepEqual(request, server.recordedRequest) {
   110  		t.Fatalf("Requests must be equal")
   111  	}
   112  }
   113  
   114  func TestResponseModifier(t *testing.T) {
   115  	r := httptest.NewRecorder()
   116  	m := NewResponseModifier(r)
   117  	m.Header().Set("h1", "v1")
   118  	m.Write([]byte("body"))
   119  	m.WriteHeader(500)
   120  
   121  	m.Flush()
   122  	if r.Header().Get("h1") != "v1" {
   123  		t.Fatalf("Header value must exists %s", r.Header().Get("h1"))
   124  	}
   125  	if !reflect.DeepEqual(r.Body.Bytes(), []byte("body")) {
   126  		t.Fatalf("Body value must exists %s", r.Body.Bytes())
   127  	}
   128  	if r.Code != 500 {
   129  		t.Fatalf("Status code must be correct %d", r.Code)
   130  	}
   131  }
   132  
   133  func TestResponseModifierOverride(t *testing.T) {
   134  	r := httptest.NewRecorder()
   135  	m := NewResponseModifier(r)
   136  	m.Header().Set("h1", "v1")
   137  	m.Write([]byte("body"))
   138  	m.WriteHeader(500)
   139  
   140  	overrideHeader := make(http.Header)
   141  	overrideHeader.Add("h1", "v2")
   142  	overrideHeaderBytes, err := json.Marshal(overrideHeader)
   143  	if err != nil {
   144  		t.Fatalf("override header failed %v", err)
   145  	}
   146  
   147  	m.OverrideHeader(overrideHeaderBytes)
   148  	m.OverrideBody([]byte("override body"))
   149  	m.OverrideStatusCode(404)
   150  	m.Flush()
   151  	if r.Header().Get("h1") != "v2" {
   152  		t.Fatalf("Header value must exists %s", r.Header().Get("h1"))
   153  	}
   154  	if !reflect.DeepEqual(r.Body.Bytes(), []byte("override body")) {
   155  		t.Fatalf("Body value must exists %s", r.Body.Bytes())
   156  	}
   157  	if r.Code != 404 {
   158  		t.Fatalf("Status code must be correct %d", r.Code)
   159  	}
   160  }
   161  
   162  // createTestPlugin creates a new sample authorization plugin
   163  func createTestPlugin(t *testing.T) *authorizationPlugin {
   164  	plugin := &plugins.Plugin{Name: "authz"}
   165  	pwd, err := os.Getwd()
   166  	if err != nil {
   167  		log.Fatal(err)
   168  	}
   169  
   170  	plugin.Client, err = plugins.NewClient("unix:///"+path.Join(pwd, pluginAddress), tlsconfig.Options{InsecureSkipVerify: true})
   171  	if err != nil {
   172  		t.Fatalf("Failed to create client %v", err)
   173  	}
   174  
   175  	return &authorizationPlugin{name: "plugin", plugin: plugin}
   176  }
   177  
   178  // AuthZPluginTestServer is a simple server that implements the authZ plugin interface
   179  type authZPluginTestServer struct {
   180  	listener net.Listener
   181  	t        *testing.T
   182  	// request stores the request sent from the daemon to the plugin
   183  	recordedRequest Request
   184  	// response stores the response sent from the plugin to the daemon
   185  	replayResponse Response
   186  }
   187  
   188  // start starts the test server that implements the plugin
   189  func (t *authZPluginTestServer) start() {
   190  	r := mux.NewRouter()
   191  	os.Remove(pluginAddress)
   192  	l, err := net.ListenUnix("unix", &net.UnixAddr{Name: pluginAddress, Net: "unix"})
   193  	if err != nil {
   194  		t.t.Fatalf("Failed to listen %v", err)
   195  	}
   196  	t.listener = l
   197  
   198  	r.HandleFunc("/Plugin.Activate", t.activate)
   199  	r.HandleFunc("/"+AuthZApiRequest, t.auth)
   200  	r.HandleFunc("/"+AuthZApiResponse, t.auth)
   201  	t.listener, err = net.Listen("tcp", pluginAddress)
   202  	server := http.Server{Handler: r, Addr: pluginAddress}
   203  	server.Serve(l)
   204  }
   205  
   206  // stop stops the test server that implements the plugin
   207  func (t *authZPluginTestServer) stop() {
   208  	os.Remove(pluginAddress)
   209  	if t.listener != nil {
   210  		t.listener.Close()
   211  	}
   212  }
   213  
   214  // auth is a used to record/replay the authentication api messages
   215  func (t *authZPluginTestServer) auth(w http.ResponseWriter, r *http.Request) {
   216  	t.recordedRequest = Request{}
   217  	defer r.Body.Close()
   218  	body, err := ioutil.ReadAll(r.Body)
   219  	json.Unmarshal(body, &t.recordedRequest)
   220  	b, err := json.Marshal(t.replayResponse)
   221  	if err != nil {
   222  		log.Fatal(err)
   223  	}
   224  	w.Write(b)
   225  }
   226  
   227  func (t *authZPluginTestServer) activate(w http.ResponseWriter, r *http.Request) {
   228  	b, err := json.Marshal(plugins.Manifest{Implements: []string{AuthZApiImplements}})
   229  	if err != nil {
   230  		log.Fatal(err)
   231  	}
   232  	w.Write(b)
   233  }