cmd/promerium : support TLS configuration from environmental variables (#12)

* Add ability to set TLS configuration from environmental variables.
* Add support for enabling debug mode from environmental variables.
This commit is contained in:
Bobby 2019-01-15 15:24:05 -08:00 committed by GitHub
parent 0766725ff8
commit 074bc0e63c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 189 additions and 23 deletions

View file

@ -6,6 +6,7 @@ import (
"net/http"
"os"
"github.com/pomerium/envconfig"
"github.com/pomerium/pomerium/internal/https"
"github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/internal/options"
@ -16,20 +17,25 @@ import (
)
var (
debugFlag = flag.Bool("debug", false, "run server in debug mode, changes log output to STDOUT and level to info")
versionFlag = flag.Bool("version", false, "prints the version")
debugFlag = flag.Bool("debug", false, "run server in debug mode, changes log output to STDOUT and level to info")
versionFlag = flag.Bool("version", false, "prints the version")
// validServics = []string{"all", "proxy", "authenticate"}
)
func main() {
mainOpts, err := optionsFromEnvConfig()
if err != nil {
log.Fatal().Err(err).Msg("cmd/pomerium : failed to parse authenticator settings")
}
flag.Parse()
if *debugFlag {
if *debugFlag || mainOpts.Debug {
log.SetDebugMode()
}
if *versionFlag {
fmt.Printf("%s", version.FullVersion())
os.Exit(0)
}
log.Info().Str("version", version.FullVersion()).Str("user-agent", version.UserAgent()).Msg("cmd/pomerium")
log.Debug().Str("version", version.FullVersion()).Str("user-agent", version.UserAgent()).Msg("cmd/pomerium")
authOpts, err := authenticate.OptionsFromEnvConfig()
if err != nil {
log.Fatal().Err(err).Msg("cmd/pomerium : failed to parse authenticator settings")
@ -57,6 +63,61 @@ func main() {
topMux := http.NewServeMux()
topMux.Handle(authOpts.RedirectURL.Host+"/", authenticator.Handler())
topMux.Handle("/", p.Handler())
log.Fatal().Err(https.ListenAndServeTLS(nil, topMux))
httpOpts := &https.Options{
Addr: mainOpts.Addr,
Cert: mainOpts.Cert,
Key: mainOpts.Key,
CertFile: mainOpts.CertFile,
KeyFile: mainOpts.KeyFile,
}
log.Fatal().Err(https.ListenAndServeTLS(httpOpts, topMux)).Msg("cmd/pomerium : fatal")
}
// Options are the global environmental flags used to set up pomerium's services.
// If a base64 encoded certificate and key are not provided as environmental variables,
// or if a file location is not provided, the server will attempt to find a matching keypair
// in the local directory as `./cert.pem` and `./privkey.pem` respectively.
type Options struct {
// Debug enables more verbose logging, and outputs human-readable logs to Stdout.
// Set with POMERIUM_DEBUG
Debug bool `envconfig:"POMERIUM_DEBUG"`
// Services is a list enabled service mode. If none are selected, "all" is used.
// Available options are : "all", "authenticate", "proxy".
Services string `envconfig:"SERVICES"`
// Addr specifies the host and port on which the server should serve
// HTTPS requests. If empty, ":https" is used.
Addr string `envconfig:"ADDRESS"`
// Cert and Key specifies the base64 encoded TLS certificates to use.
Cert string `envconfig:"CERTIFICATE"`
Key string `envconfig:"CERTIFICATE_KEY"`
// CertFile and KeyFile specifies the TLS certificates to use.
CertFile string `envconfig:"CERTIFICATE_FILE"`
KeyFile string `envconfig:"CERTIFICATE_KEY_FILE"`
}
var defaultOptions = &Options{
Debug: false,
Services: "all",
}
// optionsFromEnvConfig builds the authentication service's configuration
// options from provided environmental variables
func optionsFromEnvConfig() (*Options, error) {
o := defaultOptions
if err := envconfig.Process("", o); err != nil {
return nil, err
}
return o, nil
}
// isValidService checks to see if a service is a valid service mode
func isValidService(service string) bool {
switch service {
case
"all",
"proxy",
"authenticate":
return true
}
return false
}

62
cmd/pomerium/main_test.go Normal file
View file

@ -0,0 +1,62 @@
package main
import (
"os"
"reflect"
"testing"
)
func init() {
os.Clearenv()
}
func Test_optionsFromEnvConfig(t *testing.T) {
tests := []struct {
name string
want *Options
envKey string
envValue string
wantErr bool
}{
{"good default with no env settings", defaultOptions, "", "", false},
{"good service", defaultOptions, "SERVICES", "all", false},
{"bad debug boolean", nil, "POMERIUM_DEBUG", "yes", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.envKey != "" {
os.Setenv(tt.envKey, tt.envValue)
defer os.Unsetenv(tt.envKey)
}
got, err := optionsFromEnvConfig()
if (err != nil) != tt.wantErr {
t.Errorf("optionsFromEnvConfig() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("optionsFromEnvConfig() = got %v, want %v", got, tt.want)
}
})
}
}
func Test_isValidService(t *testing.T) {
tests := []struct {
name string
service string
want bool
}{
{"proxy", "proxy", true},
{"all", "all", true},
{"authenticate", "authenticate", true},
{"authenticate bad case", "AuThenticate", false},
{"authorize not yet implemented", "authorize", false},
{"jiberish", "xd23", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := isValidService(tt.service); got != tt.want {
t.Errorf("isValidService() = %v, want %v", got, tt.want)
}
})
}
}