basic auth

This commit is contained in:
Yu Cao
2018-10-17 19:25:12 -04:00
parent 2a5f871d74
commit b5190d45cd
5 changed files with 104 additions and 1 deletions
+6 -1
View File
@@ -31,6 +31,7 @@ func init() {
// ProbeConfig contains all the info needed for a probe to do HTTP requests
type ProbeConfig struct {
BasicAuth bool
Token string
ProbeVersion string
ProbeID string
@@ -38,7 +39,11 @@ type ProbeConfig struct {
}
func (pc ProbeConfig) authorizeHeaders(headers http.Header) {
headers.Set("Authorization", fmt.Sprintf("Scope-Probe token=%s", pc.Token))
if pc.BasicAuth {
headers.Set("Authorization", fmt.Sprintf("Basic %s", pc.Token))
} else {
headers.Set("Authorization", fmt.Sprintf("Scope-Probe token=%s", pc.Token))
}
headers.Set(xfer.ScopeProbeIDHeader, pc.ProbeID)
headers.Set(xfer.ScopeProbeVersionHeader, pc.ProbeVersion)
}
+9
View File
@@ -299,6 +299,15 @@ func appMain(flags appFlags) {
}.Wrap(handler)
}
if flags.basicAuth {
log.Infof("Basic authentication enabled")
handler = BasicAuthentication{
Realm: "Restricted",
User: flags.username,
Password: flags.password,
}.Wrap(handler)
}
server := &graceful.Server{
// we want to manage the stop condition ourselves below
NoSignalHandling: true,
+66
View File
@@ -0,0 +1,66 @@
package main
import (
"bytes"
"crypto/sha256"
"crypto/subtle"
"encoding/base64"
"fmt"
"net/http"
"strings"
)
// BasicAuthentication middleware authenticate http request
type BasicAuthentication struct {
Realm string
User string
Password string
}
// Wrap implements Middleware
func (b BasicAuthentication) Wrap(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authenticated := b.authenticate(r)
if !authenticated {
b.requestAuth(w, r)
} else {
next.ServeHTTP(w, r)
}
})
}
func (b *BasicAuthentication) authenticate(r *http.Request) bool {
const basicScheme string = "Basic "
// Confirm the request is sending Basic Authentication credentials.
auth := r.Header.Get("Authorization")
if !strings.HasPrefix(auth, basicScheme) {
return false
}
str, err := base64.StdEncoding.DecodeString(auth[len(basicScheme):])
if err != nil {
return false
}
creds := bytes.SplitN(str, []byte(":"), 2)
if len(creds) != 2 {
return false
}
givenUser := sha256.Sum256([]byte(string(creds[0])))
givenPass := sha256.Sum256([]byte(string(creds[1])))
requiredUser := sha256.Sum256([]byte(b.User))
requiredPass := sha256.Sum256([]byte(b.Password))
// Compare the supplied credentials to those set in our options
if subtle.ConstantTimeCompare(givenUser[:], requiredUser[:]) == 1 &&
subtle.ConstantTimeCompare(givenPass[:], requiredPass[:]) == 1 {
return true
}
return false
}
func (b *BasicAuthentication) requestAuth(w http.ResponseWriter, r *http.Request) {
w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Basic realm=%q`, b.Realm))
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
+14
View File
@@ -94,6 +94,9 @@ type flags struct {
type probeFlags struct {
printOnStdout bool
basicAuth bool
username string
password string
token string
httpListen string
publishInterval time.Duration
@@ -147,6 +150,10 @@ type appFlags struct {
logHTTP bool
logHTTPHeaders bool
basicAuth bool
username string
password string
weaveEnabled bool
weaveAddr string
weaveHostname string
@@ -280,6 +287,9 @@ func setupFlags(flags *flags) {
// Probe flags
flag.BoolVar(&flags.probe.printOnStdout, "probe.publish.stdout", false, "Print reports on stdout instead of sending to app, for debugging")
flag.BoolVar(&flags.probe.basicAuth, "probe.basicAuth", true, "Use basic authentication to authenticate with app")
flag.StringVar(&flags.probe.username, "probe.basicAuth.username", "admin", "Username for basic authentication")
flag.StringVar(&flags.probe.password, "probe.basicAuth.password", "admin", "Password for basic authentication")
flag.StringVar(&flags.probe.token, serviceTokenFlag, "", "Token to authenticate with cloud.weave.works")
flag.StringVar(&flags.probe.token, probeTokenFlag, "", "Token to authenticate with cloud.weave.works")
flag.StringVar(&flags.probe.httpListen, "probe.http.listen", "", "listen address for HTTP profiling and instrumentation server")
@@ -349,6 +359,10 @@ func setupFlags(flags *flags) {
flag.BoolVar(&flags.app.logHTTP, "app.log.http", false, "Log individual HTTP requests")
flag.BoolVar(&flags.app.logHTTPHeaders, "app.log.httpHeaders", false, "Log HTTP headers. Needs app.log.http to be enabled.")
flag.BoolVar(&flags.app.basicAuth, "app.basicAuth", true, "Enable basic authentication for app")
flag.StringVar(&flags.app.username, "app.basicAuth.username", "admin", "Usrname for basic authentication")
flag.StringVar(&flags.app.password, "app.basicAuth.password", "admin", "Password for basic authentication")
flag.StringVar(&flags.app.weaveAddr, "app.weave.addr", app.DefaultWeaveURL, "Address on which to contact WeaveDNS")
flag.StringVar(&flags.app.weaveHostname, "app.weave.hostname", "", "Hostname to advertise in WeaveDNS")
flag.StringVar(&flags.app.containerName, "app.container.name", app.DefaultContainerName, "Name of this container (to lookup container ID)")
+9
View File
@@ -1,6 +1,8 @@
package main
import (
"encoding/base64"
"fmt"
"math/rand"
"net"
"net/http"
@@ -125,7 +127,14 @@ func probeMain(flags probeFlags, targets []appclient.Target) {
token = url.User.Username()
url.User = nil // erase credentials, as we use a special header
}
if flags.basicAuth {
log.Infof("Basic authentication enabled")
token = base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", flags.username, flags.password)))
}
probeConfig := appclient.ProbeConfig{
BasicAuth: flags.basicAuth,
Token: token,
ProbeVersion: version,
ProbeID: probeID,