...

Source file src/github.com/docker/distribution/registry/auth/htpasswd/access_test.go

Documentation: github.com/docker/distribution/registry/auth/htpasswd

     1  package htpasswd
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"os"
     9  	"testing"
    10  
    11  	"github.com/docker/distribution/context"
    12  	"github.com/docker/distribution/registry/auth"
    13  )
    14  
    15  func TestBasicAccessController(t *testing.T) {
    16  	testRealm := "The-Shire"
    17  	testUsers := []string{"bilbo", "frodo", "MiShil", "DeokMan"}
    18  	testPasswords := []string{"baggins", "baggins", "새주", "공주님"}
    19  	testHtpasswdContent := `bilbo:{SHA}5siv5c0SHx681xU6GiSx9ZQryqs=
    20  							frodo:$2y$05$926C3y10Quzn/LnqQH86VOEVh/18T6RnLaS.khre96jLNL/7e.K5W
    21  							MiShil:$2y$05$0oHgwMehvoe8iAWS8I.7l.KoECXrwVaC16RPfaSCU5eVTFrATuMI2
    22  							DeokMan:공주님`
    23  
    24  	tempFile, err := ioutil.TempFile("", "htpasswd-test")
    25  	if err != nil {
    26  		t.Fatal("could not create temporary htpasswd file")
    27  	}
    28  	if _, err = tempFile.WriteString(testHtpasswdContent); err != nil {
    29  		t.Fatal("could not write temporary htpasswd file")
    30  	}
    31  
    32  	options := map[string]interface{}{
    33  		"realm": testRealm,
    34  		"path":  tempFile.Name(),
    35  	}
    36  	ctx := context.Background()
    37  
    38  	accessController, err := newAccessController(options)
    39  	if err != nil {
    40  		t.Fatal("error creating access controller")
    41  	}
    42  
    43  	tempFile.Close()
    44  
    45  	var userNumber = 0
    46  
    47  	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    48  		ctx := context.WithRequest(ctx, r)
    49  		authCtx, err := accessController.Authorized(ctx)
    50  		if err != nil {
    51  			switch err := err.(type) {
    52  			case auth.Challenge:
    53  				err.SetHeaders(r, w)
    54  				w.WriteHeader(http.StatusUnauthorized)
    55  				return
    56  			default:
    57  				t.Fatalf("unexpected error authorizing request: %v", err)
    58  			}
    59  		}
    60  
    61  		userInfo, ok := authCtx.Value(auth.UserKey).(auth.UserInfo)
    62  		if !ok {
    63  			t.Fatal("basic accessController did not set auth.user context")
    64  		}
    65  
    66  		if userInfo.Name != testUsers[userNumber] {
    67  			t.Fatalf("expected user name %q, got %q", testUsers[userNumber], userInfo.Name)
    68  		}
    69  
    70  		w.WriteHeader(http.StatusNoContent)
    71  	}))
    72  
    73  	client := &http.Client{
    74  		CheckRedirect: nil,
    75  	}
    76  
    77  	req, _ := http.NewRequest("GET", server.URL, nil)
    78  	resp, err := client.Do(req)
    79  
    80  	if err != nil {
    81  		t.Fatalf("unexpected error during GET: %v", err)
    82  	}
    83  	defer resp.Body.Close()
    84  
    85  	// Request should not be authorized
    86  	if resp.StatusCode != http.StatusUnauthorized {
    87  		t.Fatalf("unexpected non-fail response status: %v != %v", resp.StatusCode, http.StatusUnauthorized)
    88  	}
    89  
    90  	nonbcrypt := map[string]struct{}{
    91  		"bilbo":   {},
    92  		"DeokMan": {},
    93  	}
    94  
    95  	for i := 0; i < len(testUsers); i++ {
    96  		userNumber = i
    97  		req, err := http.NewRequest("GET", server.URL, nil)
    98  		if err != nil {
    99  			t.Fatalf("error allocating new request: %v", err)
   100  		}
   101  
   102  		req.SetBasicAuth(testUsers[i], testPasswords[i])
   103  
   104  		resp, err = client.Do(req)
   105  		if err != nil {
   106  			t.Fatalf("unexpected error during GET: %v", err)
   107  		}
   108  		defer resp.Body.Close()
   109  
   110  		if _, ok := nonbcrypt[testUsers[i]]; ok {
   111  			// these are not allowed.
   112  			// Request should be authorized
   113  			if resp.StatusCode != http.StatusUnauthorized {
   114  				t.Fatalf("unexpected non-success response status: %v != %v for %s %s", resp.StatusCode, http.StatusUnauthorized, testUsers[i], testPasswords[i])
   115  			}
   116  		} else {
   117  			// Request should be authorized
   118  			if resp.StatusCode != http.StatusNoContent {
   119  				t.Fatalf("unexpected non-success response status: %v != %v for %s %s", resp.StatusCode, http.StatusNoContent, testUsers[i], testPasswords[i])
   120  			}
   121  		}
   122  	}
   123  
   124  }
   125  
   126  func TestCreateHtpasswdFile(t *testing.T) {
   127  	tempFile, err := ioutil.TempFile("", "htpasswd-test")
   128  	if err != nil {
   129  		t.Fatalf("could not create temporary htpasswd file %v", err)
   130  	}
   131  	defer tempFile.Close()
   132  	options := map[string]interface{}{
   133  		"realm": "/auth/htpasswd",
   134  		"path":  tempFile.Name(),
   135  	}
   136  	// Ensure file is not populated
   137  	if _, err := newAccessController(options); err != nil {
   138  		t.Fatalf("error creating access controller %v", err)
   139  	}
   140  	content, err := ioutil.ReadAll(tempFile)
   141  	if err != nil {
   142  		t.Fatalf("failed to read file %v", err)
   143  	}
   144  	if !bytes.Equal([]byte{}, content) {
   145  		t.Fatalf("htpasswd file should not be populated %v", string(content))
   146  	}
   147  	if err := os.Remove(tempFile.Name()); err != nil {
   148  		t.Fatalf("failed to remove temp file %v", err)
   149  	}
   150  
   151  	// Ensure htpasswd file is populated
   152  	if _, err := newAccessController(options); err != nil {
   153  		t.Fatalf("error creating access controller %v", err)
   154  	}
   155  	content, err = ioutil.ReadFile(tempFile.Name())
   156  	if err != nil {
   157  		t.Fatalf("failed to read file %v", err)
   158  	}
   159  	if !bytes.HasPrefix(content, []byte("docker:$2a$")) {
   160  		t.Fatalf("failed to find default user in file %s", string(content))
   161  	}
   162  }
   163  

View as plain text