Make config more docker friendly

This commit is contained in:
Bolke de Bruin 2022-08-16 14:52:22 +02:00
parent 3ca05cbf16
commit 40d9cdda57
6 changed files with 140 additions and 24 deletions

View file

@ -1,6 +1,7 @@
package config
import (
"github.com/bolkedebruin/rdpgw/cmd/rdpgw/security"
"github.com/knadh/koanf"
"github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/confmap"
@ -30,7 +31,7 @@ type ServerConfig struct {
SessionStore string `koanf:"sessionstore"`
SendBuf int `koanf:"sendbuf"`
ReceiveBuf int `koanf:"recievebuf"`
DisableTLS bool `koanf:"disabletls"`
DisableTLS bool `koanf:"disabletls"`
}
type OpenIDConfig struct {
@ -114,13 +115,13 @@ func Load(configFile string) Configuration {
k.Load(confmap.Provider(map[string]interface{}{
"Server.CertFile": "server.pem",
"Server.KeyFile": "key.pem",
"Server.TlsDisabled": false,
"Server.TlsDisabled": false,
"Server.Port": 443,
"Server.SessionStore": "cookie",
"Server.SessionStore": "cookie",
"Client.NetworkAutoDetect": 1,
"Client.BandwidthAutoDetect": 1,
"Security.VerifyClientIp": true,
"Caps.TokenAuth": true,
"Caps.TokenAuth": true,
}, "."), nil)
if err := k.Load(file.Provider(configFile), yaml.Parser()); err != nil {
@ -142,6 +143,36 @@ func Load(configFile string) Configuration {
k.UnmarshalWithConf("Security", &Conf.Security, koanfTag)
k.UnmarshalWithConf("Client", &Conf.Client, koanfTag)
if len(Conf.Security.PAATokenEncryptionKey) != 32 {
Conf.Security.PAATokenEncryptionKey, _ = security.GenerateRandomString(32)
log.Printf("No valid `security.paatokenencryptionkey` specified (empty or not 32 characters). Setting to random")
}
if len(Conf.Security.PAATokenSigningKey) != 32 {
Conf.Security.PAATokenSigningKey, _ = security.GenerateRandomString(32)
log.Printf("No valid `security.paatokensigningkey` specified (empty or not 32 characters). Setting to random")
}
if len(Conf.Security.UserTokenEncryptionKey) != 32 {
Conf.Security.UserTokenEncryptionKey, _ = security.GenerateRandomString(32)
log.Printf("No valid `security.usertokenencryptionkey` specified (empty or not 32 characters). Setting to random")
}
if len(Conf.Security.UserTokenSigningKey) != 32 {
Conf.Security.UserTokenSigningKey, _ = security.GenerateRandomString(32)
log.Printf("No valid `security.usertokensigningkey` specified (empty or not 32 characters). Setting to random")
}
if len(Conf.Server.SessionKey) != 32 {
Conf.Server.SessionKey, _ = security.GenerateRandomString(32)
log.Printf("No valid `server.sessionkey` specified (empty or not 32 characters). Setting to random")
}
if len(Conf.Server.SessionEncryptionKey) != 32 {
Conf.Server.SessionEncryptionKey, _ = security.GenerateRandomString(32)
log.Printf("No valid `server.sessionencryptionkey` specified (empty or not 32 characters). Setting to random")
}
return Conf
}
}

View file

@ -3,7 +3,6 @@ package main
import (
"context"
"crypto/tls"
"github.com/thought-machine/go-flags"
"github.com/bolkedebruin/rdpgw/cmd/rdpgw/api"
"github.com/bolkedebruin/rdpgw/cmd/rdpgw/common"
"github.com/bolkedebruin/rdpgw/cmd/rdpgw/config"
@ -11,9 +10,11 @@ import (
"github.com/bolkedebruin/rdpgw/cmd/rdpgw/security"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/thought-machine/go-flags"
"golang.org/x/oauth2"
"log"
"net/http"
"net/url"
"os"
"strconv"
)
@ -50,18 +51,25 @@ func main() {
}
verifier := provider.Verifier(oidcConfig)
// get callback url and external advertised gateway address
url, err := url.Parse(conf.Server.GatewayAddress)
if url.Scheme == "" {
url.Scheme = "https"
}
url.Path = "callback"
oauthConfig := oauth2.Config{
ClientID: conf.OpenId.ClientId,
ClientID: conf.OpenId.ClientId,
ClientSecret: conf.OpenId.ClientSecret,
RedirectURL: "https://" + conf.Server.GatewayAddress + "/callback",
Endpoint: provider.Endpoint(),
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
RedirectURL: url.String(),
Endpoint: provider.Endpoint(),
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
}
security.OIDCProvider = provider
security.Oauth2Config = oauthConfig
api := &api.Config{
GatewayAddress: conf.Server.GatewayAddress,
GatewayAddress: url.Host,
OAuth2Config: &oauthConfig,
OIDCTokenVerifier: verifier,
PAATokenGenerator: security.GeneratePAAToken,
@ -69,7 +77,7 @@ func main() {
EnableUserToken: conf.Security.EnableUserToken,
SessionKey: []byte(conf.Server.SessionKey),
SessionEncryptionKey: []byte(conf.Server.SessionEncryptionKey),
SessionStore: conf.Server.SessionStore,
SessionStore: conf.Server.SessionStore,
Hosts: conf.Server.Hosts,
NetworkAutoDetect: conf.Client.NetworkAutoDetect,
UsernameTemplate: conf.Client.UsernameTemplate,
@ -84,7 +92,7 @@ func main() {
cfg := &tls.Config{}
if conf.Server.DisableTLS {
log.Printf("TLS disabled - rdp gw connections require tls make sure to have a terminator")
log.Printf("TLS disabled - rdp gw connections require tls, make sure to have a terminator")
} else {
if conf.Server.CertFile == "" || conf.Server.KeyFile == "" {
log.Fatal("Both certfile and keyfile need to be specified")
@ -108,24 +116,24 @@ func main() {
}
server := http.Server{
Addr: ":" + strconv.Itoa(conf.Server.Port),
TLSConfig: cfg,
Addr: ":" + strconv.Itoa(conf.Server.Port),
TLSConfig: cfg,
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)), // disable http2
}
// create the gateway
handlerConfig := protocol.ServerConf{
IdleTimeout: conf.Caps.IdleTimeout,
TokenAuth: conf.Caps.TokenAuth,
IdleTimeout: conf.Caps.IdleTimeout,
TokenAuth: conf.Caps.TokenAuth,
SmartCardAuth: conf.Caps.SmartCardAuth,
RedirectFlags: protocol.RedirectFlags{
Clipboard: conf.Caps.EnableClipboard,
Drive: conf.Caps.EnableDrive,
Printer: conf.Caps.EnablePrinter,
Port: conf.Caps.EnablePort,
Pnp: conf.Caps.EnablePnp,
Clipboard: conf.Caps.EnableClipboard,
Drive: conf.Caps.EnableDrive,
Printer: conf.Caps.EnablePrinter,
Port: conf.Caps.EnablePort,
Pnp: conf.Caps.EnablePnp,
DisableAll: conf.Caps.DisableRedirect,
EnableAll: conf.Caps.RedirectAll,
EnableAll: conf.Caps.RedirectAll,
},
VerifyTunnelCreate: security.VerifyPAAToken,
VerifyServerFunc: security.VerifyServerFunc,

View file

@ -0,0 +1,39 @@
package security
import (
"crypto/rand"
"math/big"
)
// GenerateRandomBytes returns securely generated random bytes.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
// Note that err == nil only if we read len(b) bytes.
if err != nil {
return nil, err
}
return b, nil
}
// GenerateRandomString returns a securely generated random string.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomString(n int) (string, error) {
const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
ret := make([]byte, n)
for i := 0; i < n; i++ {
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
if err != nil {
return "", err
}
ret = append(ret, letters[num.Int64()])
}
return string(ret), nil
}