Skip to content

Commit

Permalink
Use http's basic auth instead of manual encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
Kris committed Nov 6, 2015
1 parent 4566e03 commit 0a4ee95
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 235 deletions.
37 changes: 6 additions & 31 deletions pkg/client/unversioned/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package unversioned

import (
"bytes"
"encoding/base64"
"errors"
"io"
"io/ioutil"
Expand Down Expand Up @@ -1126,36 +1125,14 @@ func TestBody(t *testing.T) {
}
}

func authFromReq(r *http.Request) (*Config, bool) {
auth, ok := r.Header["Authorization"]
if !ok {
return nil, false
}

encoded := strings.Split(auth[0], " ")
if len(encoded) != 2 || encoded[0] != "Basic" {
return nil, false
}

decoded, err := base64.StdEncoding.DecodeString(encoded[1])
if err != nil {
return nil, false
}
parts := strings.Split(string(decoded), ":")
if len(parts) != 2 {
return nil, false
}
return &Config{Username: parts[0], Password: parts[1]}, true
}

// checkAuth sets errors if the auth found in r doesn't match the expectation.
// TODO: Move to util, test in more places.
func checkAuth(t *testing.T, expect *Config, r *http.Request) {
foundAuth, found := authFromReq(r)
func checkAuth(t *testing.T, expectedUser, expectedPass string, r *http.Request) {
user, pass, found := r.BasicAuth()
if !found {
t.Errorf("no auth found")
} else if e, a := expect, foundAuth; !api.Semantic.DeepDerivative(e, a) {
t.Fatalf("Wrong basic auth: wanted %#v, got %#v", e, a)
} else if user != expectedUser || pass != expectedPass {
t.Fatalf("Wrong basic auth: wanted %s:%s, got %s:%s", expectedUser, expectedPass, user, pass)
}
}

Expand All @@ -1169,9 +1146,8 @@ func TestWatch(t *testing.T) {
{watch.Deleted, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "last"}}},
}

auth := &Config{Username: "user", Password: "pass"}
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
checkAuth(t, auth, r)
checkAuth(t, "user", "pass", r)
flusher, ok := w.(http.Flusher)
if !ok {
panic("need flusher!")
Expand Down Expand Up @@ -1225,11 +1201,10 @@ func TestWatch(t *testing.T) {
}

func TestStream(t *testing.T) {
auth := &Config{Username: "user", Password: "pass"}
expectedBody := "expected body"

testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
checkAuth(t, auth, r)
checkAuth(t, "user", "pass", r)
flusher, ok := w.(http.Flusher)
if !ok {
panic("need flusher!")
Expand Down
3 changes: 1 addition & 2 deletions pkg/client/unversioned/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package unversioned

import (
"encoding/base64"
"net/http"
"testing"

Expand Down Expand Up @@ -60,7 +59,7 @@ func TestBasicAuthRoundTripper(t *testing.T) {
if rt.Request == req {
t.Fatalf("round tripper should have copied request object: %#v", rt.Request)
}
if rt.Request.Header.Get("Authorization") != "Basic "+base64.StdEncoding.EncodeToString([]byte("user:pass")) {
if user, pass, found := rt.Request.BasicAuth(); !found || user != "user" || pass != "pass" {
t.Errorf("unexpected authorization header: %#v", rt.Request)
}
}
Expand Down
24 changes: 2 additions & 22 deletions plugin/pkg/auth/authenticator/request/basicauth/basicauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ limitations under the License.
package basicauth

import (
"encoding/base64"
"errors"
"net/http"
"strings"

"k8s.io/kubernetes/pkg/auth/authenticator"
"k8s.io/kubernetes/pkg/auth/user"
Expand All @@ -38,26 +35,9 @@ func New(auth authenticator.Password) *Authenticator {

// AuthenticateRequest authenticates the request using the "Authorization: Basic" header in the request
func (a *Authenticator) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
auth := strings.TrimSpace(req.Header.Get("Authorization"))
if auth == "" {
username, password, found := req.BasicAuth()
if !found {
return nil, false, nil
}
parts := strings.Split(auth, " ")
if len(parts) < 2 || strings.ToLower(parts[0]) != "basic" {
return nil, false, nil
}

payload, err := base64.StdEncoding.DecodeString(parts[1])
if err != nil {
return nil, false, err
}

pair := strings.SplitN(string(payload), ":", 2)
if len(pair) != 2 {
return nil, false, errors.New("malformed basic auth header")
}

username := pair[0]
password := pair[1]
return a.auth.AuthenticatePassword(username, password)
}
42 changes: 9 additions & 33 deletions plugin/pkg/auth/authenticator/request/basicauth/basicauth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package basicauth

import (
"encoding/base64"
"errors"
"net/http"
"testing"
Expand Down Expand Up @@ -56,40 +55,18 @@ func TestBasicAuth(t *testing.T) {
ExpectedOK bool
ExpectedErr bool
}{
"no header": {
Header: "",
},
"non-basic header": {
Header: "Bearer foo",
},
"empty value basic header": {
Header: "Basic",
},
"whitespace value basic header": {
Header: "Basic ",
},
"non base-64 basic header": {
Header: "Basic !@#$",
ExpectedErr: true,
},
"malformed basic header": {
Header: "Basic " + base64.StdEncoding.EncodeToString([]byte("user_without_password")),
ExpectedErr: true,
},
"no auth": {},
"empty password basic header": {
Header: "Basic " + base64.StdEncoding.EncodeToString([]byte("user_with_empty_password:")),
ExpectedCalled: true,
ExpectedUsername: "user_with_empty_password",
ExpectedPassword: "",
},
"valid basic header": {
Header: "Basic " + base64.StdEncoding.EncodeToString([]byte("myuser:mypassword:withcolon")),
ExpectedCalled: true,
ExpectedUsername: "myuser",
ExpectedPassword: "mypassword:withcolon",
},
"password auth returned user": {
Header: "Basic " + base64.StdEncoding.EncodeToString([]byte("myuser:mypw")),
Password: testPassword{User: &user.DefaultInfo{Name: "returneduser"}, OK: true},
ExpectedCalled: true,
ExpectedUsername: "myuser",
Expand All @@ -98,7 +75,6 @@ func TestBasicAuth(t *testing.T) {
ExpectedOK: true,
},
"password auth returned error": {
Header: "Basic " + base64.StdEncoding.EncodeToString([]byte("myuser:mypw")),
Password: testPassword{Err: errors.New("auth error")},
ExpectedCalled: true,
ExpectedUsername: "myuser",
Expand All @@ -112,35 +88,35 @@ func TestBasicAuth(t *testing.T) {
auth := authenticator.Request(New(&password))

req, _ := http.NewRequest("GET", "/", nil)
if testCase.Header != "" {
req.Header.Set("Authorization", testCase.Header)
if testCase.ExpectedUsername != "" || testCase.ExpectedPassword != "" {
req.SetBasicAuth(testCase.ExpectedUsername, testCase.ExpectedPassword)
}

user, ok, err := auth.AuthenticateRequest(req)

if testCase.ExpectedCalled != password.Called {
t.Fatalf("%s: Expected called=%v, got %v", k, testCase.ExpectedCalled, password.Called)
t.Errorf("%s: Expected called=%v, got %v", k, testCase.ExpectedCalled, password.Called)
continue
}
if testCase.ExpectedUsername != password.Username {
t.Fatalf("%s: Expected called with username=%v, got %v", k, testCase.ExpectedUsername, password.Username)
t.Errorf("%s: Expected called with username=%v, got %v", k, testCase.ExpectedUsername, password.Username)
continue
}
if testCase.ExpectedPassword != password.Password {
t.Fatalf("%s: Expected called with password=%v, got %v", k, testCase.ExpectedPassword, password.Password)
t.Errorf("%s: Expected called with password=%v, got %v", k, testCase.ExpectedPassword, password.Password)
continue
}

if testCase.ExpectedErr != (err != nil) {
t.Fatalf("%s: Expected err=%v, got err=%v", k, testCase.ExpectedErr, err)
t.Errorf("%s: Expected err=%v, got err=%v", k, testCase.ExpectedErr, err)
continue
}
if testCase.ExpectedOK != ok {
t.Fatalf("%s: Expected ok=%v, got ok=%v", k, testCase.ExpectedOK, ok)
t.Errorf("%s: Expected ok=%v, got ok=%v", k, testCase.ExpectedOK, ok)
continue
}
if testCase.ExpectedUser != "" && testCase.ExpectedUser != user.GetName() {
t.Fatalf("%s: Expected user.GetName()=%v, got %v", k, testCase.ExpectedUser, user.GetName())
t.Errorf("%s: Expected user.GetName()=%v, got %v", k, testCase.ExpectedUser, user.GetName())
continue
}
}
Expand Down
147 changes: 0 additions & 147 deletions plugin/pkg/auth/authenticator/request/keystone/keystone_test.go

This file was deleted.

0 comments on commit 0a4ee95

Please sign in to comment.