Move to auth package in faas-provider

The basic-auth middleware and credentials-loading code has been
moved into the faas-provider project. This has now been brought
back into the faas project via vendoring.

Signed-off-by: Alex Ellis (VMware) <alexellis2@gmail.com>
This commit is contained in:
Alex Ellis (VMware)
2018-09-06 16:14:53 +01:00
parent c821585b39
commit 6937bc4d7f
16 changed files with 279 additions and 21 deletions

View File

@ -0,0 +1,26 @@
// Copyright (c) OpenFaaS Author(s). All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
package auth
import (
"net/http"
)
// DecorateWithBasicAuth enforces basic auth as a middleware with given credentials
func DecorateWithBasicAuth(next http.HandlerFunc, credentials *BasicAuthCredentials) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user, password, ok := r.BasicAuth()
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
if !ok || !(credentials.Password == password && user == credentials.User) {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("invalid credentials"))
return
}
next.ServeHTTP(w, r)
}
}

View File

@ -0,0 +1,66 @@
// Copyright (c) OpenFaaS Author(s). All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
package auth
import (
"io"
"net/http"
"net/http/httptest"
"testing"
)
func Test_AuthWithValidPassword_Gives200(t *testing.T) {
handler := func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "<html><body>Hello World!</body></html>")
}
w := httptest.NewRecorder()
wantUser := "admin"
wantPassword := "password"
r := httptest.NewRequest(http.MethodGet, "http://localhost:8080", nil)
r.SetBasicAuth(wantUser, wantPassword)
wantCredentials := &BasicAuthCredentials{
User: wantUser,
Password: wantPassword,
}
decorated := DecorateWithBasicAuth(handler, wantCredentials)
decorated.ServeHTTP(w, r)
wantCode := http.StatusOK
if w.Code != wantCode {
t.Errorf("status code, want: %d, got: %d", wantCode, w.Code)
t.Fail()
}
}
func Test_AuthWithInvalidPassword_Gives403(t *testing.T) {
handler := func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "<html><body>Hello World!</body></html>")
}
w := httptest.NewRecorder()
wantUser := "admin"
wantPassword := "test"
r := httptest.NewRequest(http.MethodGet, "http://localhost:8080", nil)
r.SetBasicAuth(wantUser, wantPassword)
wantCredentials := &BasicAuthCredentials{
User: wantUser,
Password: "",
}
decorated := DecorateWithBasicAuth(handler, wantCredentials)
decorated.ServeHTTP(w, r)
wantCode := http.StatusUnauthorized
if w.Code != wantCode {
t.Errorf("status code, want: %d, got: %d", wantCode, w.Code)
t.Fail()
}
}

View File

@ -0,0 +1,52 @@
// Copyright (c) OpenFaaS Author(s). All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
package auth
import (
"fmt"
"io/ioutil"
"path"
"strings"
)
// BasicAuthCredentials for credentials
type BasicAuthCredentials struct {
User string
Password string
}
type ReadBasicAuth interface {
Read() (error, *BasicAuthCredentials)
}
type ReadBasicAuthFromDisk struct {
SecretMountPath string
}
func (r *ReadBasicAuthFromDisk) Read() (*BasicAuthCredentials, error) {
var credentials *BasicAuthCredentials
if len(r.SecretMountPath) == 0 {
return nil, fmt.Errorf("invalid SecretMountPath specified for reading secrets")
}
userPath := path.Join(r.SecretMountPath, "basic-auth-user")
user, userErr := ioutil.ReadFile(userPath)
if userErr != nil {
return nil, fmt.Errorf("unable to load %s", userPath)
}
userPassword := path.Join(r.SecretMountPath, "basic-auth-password")
password, passErr := ioutil.ReadFile(userPassword)
if passErr != nil {
return nil, fmt.Errorf("Unable to load %s", userPassword)
}
credentials = &BasicAuthCredentials{
User: strings.TrimSpace(string(user)),
Password: strings.TrimSpace(string(password)),
}
return credentials, nil
}