mirror of
https://github.com/openfaas/faas.git
synced 2025-06-18 20:16:37 +00:00
Read secrets from variable path
This change enables secrets to be read from any mount on disk rather than hard-coding a certain location which suits Swarm or K8s. The default value if not specified will look in the Swarm location of /run/secrets/ README.md (docs) updated and set to off by default. Signed-off-by: Alex Ellis (VMware) <alexellis2@gmail.com>
This commit is contained in:
committed by
Alex Ellis
parent
a38931ce69
commit
8133414183
@ -15,6 +15,8 @@ services:
|
||||
faas_nats_port: 4222
|
||||
direct_functions: "true" # Functions are invoked directly over the overlay network
|
||||
direct_functions_suffix: ""
|
||||
basic_auth: "false"
|
||||
secret_mount_path: "/run/secrets/"
|
||||
deploy:
|
||||
resources:
|
||||
# limits: # uncomment to enable limits
|
||||
|
@ -16,6 +16,8 @@ services:
|
||||
faas_nats_port: 4222
|
||||
direct_functions: "true" # Functions are invoked directly over the overlay network
|
||||
direct_functions_suffix: ""
|
||||
basic_auth: "false"
|
||||
secret_mount_path: "/run/secrets/"
|
||||
deploy:
|
||||
resources:
|
||||
# limits: # Enable if you want to limit memory usage
|
||||
|
@ -54,3 +54,5 @@ The gateway can be configured through the following environment variables:
|
||||
| `faas_promethus_port` | Port to connect to Prometheus. Default: `9090` |
|
||||
| `direct_functions` | `true` or `false` - functions are invoked directly over overlay network without passing through provider |
|
||||
| `direct_functions_suffix` | Provide a DNS suffix for invoking functions directly over overlay network |
|
||||
| `basic_auth` | Set to `true` or `false` to enable embedded basic auth on the /system and /ui endpoints (recommended) |
|
||||
| `secret_mount_path` | Set a location where you have mounted `basic-auth-user` and `basic-auth-password`, default: `/run/secrets/`. |
|
||||
|
@ -2,10 +2,12 @@ package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/openfaas/faas/gateway/types"
|
||||
)
|
||||
|
||||
// DecorateWithBasicAuth enforces basic auth as a middleware with given credentials
|
||||
func DecorateWithBasicAuth(next http.HandlerFunc, credentials *BasicAuthCredentials) http.HandlerFunc {
|
||||
func DecorateWithBasicAuth(next http.HandlerFunc, credentials *types.BasicAuthCredentials) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
user, password, ok := r.BasicAuth()
|
||||
@ -21,9 +23,3 @@ func DecorateWithBasicAuth(next http.HandlerFunc, credentials *BasicAuthCredenti
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// BasicAuthCredentials for credentials
|
||||
type BasicAuthCredentials struct {
|
||||
User string
|
||||
Password string
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/openfaas/faas/gateway/types"
|
||||
)
|
||||
|
||||
func Test_AuthWithValidPassword_Gives200(t *testing.T) {
|
||||
@ -18,7 +20,7 @@ func Test_AuthWithValidPassword_Gives200(t *testing.T) {
|
||||
wantPassword := "password"
|
||||
r := httptest.NewRequest(http.MethodGet, "http://localhost:8080", nil)
|
||||
r.SetBasicAuth(wantUser, wantPassword)
|
||||
wantCredentials := &BasicAuthCredentials{
|
||||
wantCredentials := &types.BasicAuthCredentials{
|
||||
User: wantUser,
|
||||
Password: wantPassword,
|
||||
}
|
||||
@ -47,7 +49,7 @@ func Test_AuthWithInvalidPassword_Gives403(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "http://localhost:8080", nil)
|
||||
r.SetBasicAuth(wantUser, wantPassword)
|
||||
|
||||
wantCredentials := &BasicAuthCredentials{
|
||||
wantCredentials := &types.BasicAuthCredentials{
|
||||
User: wantUser,
|
||||
Password: "",
|
||||
}
|
||||
|
@ -5,10 +5,8 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
@ -35,24 +33,17 @@ func main() {
|
||||
|
||||
log.Printf("Binding to external function provider: %s", config.FunctionsProviderURL)
|
||||
|
||||
var credentials *handlers.BasicAuthCredentials
|
||||
var credentials *types.BasicAuthCredentials
|
||||
|
||||
if config.UseBasicAuth {
|
||||
userPath := "/var/secrets/basic_auth_user"
|
||||
user, userErr := ioutil.ReadFile(userPath)
|
||||
if userErr != nil {
|
||||
log.Panicf("Unable to load %s", userPath)
|
||||
var readErr error
|
||||
reader := types.ReadBasicAuthFromDisk{
|
||||
SecretMountPath: config.SecretMountPath,
|
||||
}
|
||||
credentials, readErr = reader.Read()
|
||||
|
||||
userPassword := "/var/secrets/basic_auth_password"
|
||||
password, passErr := ioutil.ReadFile(userPassword)
|
||||
if passErr != nil {
|
||||
log.Panicf("Unable to load %s", userPassword)
|
||||
}
|
||||
|
||||
credentials = &handlers.BasicAuthCredentials{
|
||||
User: strings.TrimSpace(string(user)),
|
||||
Password: strings.TrimSpace(string(password)),
|
||||
if readErr != nil {
|
||||
log.Panicf(readErr.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
49
gateway/types/load_credentials.go
Normal file
49
gateway/types/load_credentials.go
Normal file
@ -0,0 +1,49 @@
|
||||
package types
|
||||
|
||||
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
|
||||
}
|
@ -107,6 +107,12 @@ func (ReadConfig) Read(hasEnv HasEnv) GatewayConfig {
|
||||
|
||||
cfg.UseBasicAuth = parseBoolValue(hasEnv.Getenv("basic_auth"))
|
||||
|
||||
secretPath := hasEnv.Getenv("secret_mount_path")
|
||||
if len(secretPath) == 0 {
|
||||
secretPath = "/run/secrets/"
|
||||
}
|
||||
cfg.SecretMountPath = secretPath
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
@ -145,6 +151,9 @@ type GatewayConfig struct {
|
||||
|
||||
// If set, reads secrets from file-system for enabling basic auth.
|
||||
UseBasicAuth bool
|
||||
|
||||
// SecretMountPath specifies where to read secrets from for embedded basic auth
|
||||
SecretMountPath string
|
||||
}
|
||||
|
||||
// UseNATS Use NATSor not
|
||||
|
@ -209,11 +209,18 @@ func TestRead_BasicAuthDefaults(t *testing.T) {
|
||||
t.Logf("config.UseBasicAuth, want: %t, got: %t\n", false, config.UseBasicAuth)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
wantSecretsMount := "/run/secrets/"
|
||||
if config.SecretMountPath != wantSecretsMount {
|
||||
t.Logf("config.SecretMountPath, want: %s, got: %s\n", wantSecretsMount, config.SecretMountPath)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestRead_BasicAuth_SetTrue(t *testing.T) {
|
||||
defaults := NewEnvBucket()
|
||||
defaults.Setenv("basic_auth", "true")
|
||||
defaults.Setenv("secret_mount_path", "/etc/openfaas/")
|
||||
|
||||
readConfig := ReadConfig{}
|
||||
|
||||
@ -223,4 +230,10 @@ func TestRead_BasicAuth_SetTrue(t *testing.T) {
|
||||
t.Logf("config.UseBasicAuth, want: %t, got: %t\n", true, config.UseBasicAuth)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
wantSecretsMount := "/etc/openfaas/"
|
||||
if config.SecretMountPath != wantSecretsMount {
|
||||
t.Logf("config.SecretMountPath, want: %s, got: %s\n", wantSecretsMount, config.SecretMountPath)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user