Skip to content

Commit

Permalink
Merge pull request #7 from jcrood/cfg-session-salt
Browse files Browse the repository at this point in the history
Add sessionSalt to override hard-coded salt
  • Loading branch information
jcrood authored Jun 6, 2022
2 parents e0dff3f + b90d1e4 commit 8bd1c14
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 14 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ when the IDP uses a self-signed CA. Merged from https://github.com/vmware-archiv
Adds the `customAssetsDir` config option to override the contents of /assets/ for use in
custom templates.


### Override hard-coded session salt

Adds the `sessionSalt` config option to override the hard-coded salt. Min. length is 8 characters.
Fixes https://github.com/vmware-archive/gangway/issues/71

### todo

...
Expand Down
4 changes: 2 additions & 2 deletions cmd/gangway/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import (
)

func testInit() {
gangwayUserSession = session.New("test")
gangwayUserSession = session.New("test", "0123456789")
transportConfig = config.NewTransportConfig("")

oauth2Cfg = &oauth2.Config{
Expand Down Expand Up @@ -434,7 +434,7 @@ func TestUnauthedCommandlineHandlerRedirect(t *testing.T) {
t.Fatal(err)
}

session.New("test")
session.New("test", "0123456789")

rr := httptest.NewRecorder()
handler := http.HandlerFunc(commandlineHandler)
Expand Down
2 changes: 1 addition & 1 deletion cmd/gangway/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func main() {
}

transportConfig = config.NewTransportConfig(cfg.TrustedCAPath)
gangwayUserSession = session.New(cfg.SessionSecurityKey)
gangwayUserSession = session.New(cfg.SessionSecurityKey, cfg.SessionSalt)

var assetFs http.FileSystem
if cfg.CustomAssetsDir != "" {
Expand Down
9 changes: 6 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ While this is called a secret, based on the way that OAuth2 works with command l
This will be divulged to any client that is configured through gangway.
As such, it is probably acceptable to keep that secret in the config file and not worry about managing it as a true secret.

We also have a secret string that is used to as a way to encrypt the cookies that are returned to the users.
If using the example YAML, create a secret to hold this value with the following command line:
We also have a secret string and salt that is used to as a way to encrypt the cookies that are returned
to the users. If using the example YAML, create a secret to hold these values with the following command line:

```
kubectl -n gangway create secret generic gangway-key \
--from-literal=sessionkey=$(openssl rand -base64 32)
--from-literal=sessionkey=$(openssl rand -base64 32) \
--from-literal=sessionsalt=$(openssl rand -base64 32)
```

Setting a salt is optional; if the config variable is not set a default baked in salt will be used.

## Path Prefix

Gangway takes an optional path prefix if you want to host it at a url other than '/' (e.g. `https://example.com/gangway`).
Expand Down
5 changes: 5 additions & 0 deletions docs/yaml/03-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ spec:
secretKeyRef:
name: gangway-key
key: sessionkey
- name: GANGWAY_SESSION_SALT
valueFrom:
secretKeyRef:
name: gangway-key
key: sessionsalt
ports:
- name: http
containerPort: 8080
Expand Down
5 changes: 5 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
"sigs.k8s.io/yaml"
)

const hardCodedDefaultSalt = "MkmfuPNHnZBBivy0L0aW"

// Config the configuration field for gangway
type Config struct {
Host string `yaml:"host"`
Expand All @@ -48,6 +50,7 @@ type Config struct {
HTTPPath string `yaml:"httpPath" envconfig:"http_path"`
ShowClaims bool `yaml:"showClaims" envconfig:"show_claims"`
SessionSecurityKey string `yaml:"sessionSecurityKey" envconfig:"SESSION_SECURITY_KEY"`
SessionSalt string `yaml:"sessionSalt" envconfig:"SESSION_SALT"`
CustomHTMLTemplatesDir string `yaml:"customHTMLTemplatesDir" envconfig:"custom_html_templates_dir"`
CustomAssetsDir string `yaml:"customAssetsDir" envconfig:"custom_assets_dir"`
}
Expand All @@ -68,6 +71,7 @@ func NewConfig(configFile string) (*Config, error) {
ClusterCAPath: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
HTTPPath: "",
ShowClaims: false,
SessionSalt: hardCodedDefaultSalt,
}

if configFile != "" {
Expand Down Expand Up @@ -111,6 +115,7 @@ func (cfg *Config) Validate() error {
{cfg.RedirectURL == "", "no redirectURL specified"},
{cfg.SessionSecurityKey == "", "no SessionSecurityKey specified"},
{cfg.APIServerURL == "", "no apiServerURL specified"},
{len(cfg.SessionSalt) < 8, "salt needs to be min. 8 characters"},
}

for _, check := range checks {
Expand Down
24 changes: 24 additions & 0 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestConfigNotFound(t *testing.T) {
}

func TestEnvionmentOverrides(t *testing.T) {
salt := "randombanana"
os.Setenv("GANGWAY_AUTHORIZE_URL", "https://foo.bar/authorize")
os.Setenv("GANGWAY_APISERVER_URL", "https://k8s-api.foo.baz")
os.Setenv("GANGWAY_CLIENT_ID", "foo")
Expand All @@ -39,6 +40,7 @@ func TestEnvionmentOverrides(t *testing.T) {
os.Setenv("GANGWAY_AUDIENCE", "foo")
os.Setenv("GANGWAY_SCOPES", "groups,sub")
os.Setenv("GANGWAY_SHOW_CLAIMS", "false")
os.Setenv("GANGWAY_SESSION_SALT", salt)
cfg, err := NewConfig("")
if err != nil {
t.Errorf("Failed to test config overrides with error: %s", err)
Expand All @@ -59,6 +61,28 @@ func TestEnvionmentOverrides(t *testing.T) {
if cfg.ShowClaims != false {
t.Errorf("Failed to disable showing of claims. Expected %t but got %t", false, cfg.ShowClaims)
}
if cfg.SessionSalt != salt {
t.Errorf("Failed to override session salt. Expected %s but got %s", salt, cfg.SessionSalt)
}
}

func TestSessionSaltLength(t *testing.T) {
salt := "2short"
os.Setenv("GANGWAY_AUTHORIZE_URL", "https://foo.bar/authorize")
os.Setenv("GANGWAY_APISERVER_URL", "https://k8s-api.foo.baz")
os.Setenv("GANGWAY_CLIENT_ID", "foo")
os.Setenv("GANGWAY_CLIENT_SECRET", "bar")
os.Setenv("GANGWAY_REDIRECT_URL", "https://foo.baz/callback")
os.Setenv("GANGWAY_SESSION_SECURITY_KEY", "testing")
os.Setenv("GANGWAY_TOKEN_URL", "https://foo.bar/token")
os.Setenv("GANGWAY_SESSION_SALT", salt)
_, err := NewConfig("")
if err == nil {
t.Errorf("Expected error but got none")
}
if err.Error() != "invalid config: salt needs to be min. 8 characters" {
t.Errorf("Wrong error. Expected %v but got %v", "salt needs to be min. 8 characters", err)
}
}

func TestGetRootPathPrefix(t *testing.T) {
Expand Down
8 changes: 3 additions & 5 deletions internal/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,20 @@ import (
"golang.org/x/crypto/pbkdf2"
)

const salt = "MkmfuPNHnZBBivy0L0aW"

// Session defines a Gangway session
type Session struct {
Session *CustomCookieStore
}

// New inits a Session with CookieStore
func New(sessionSecurityKey string) *Session {
func New(sessionSecurityKey string, sessionSalt string) *Session {
return &Session{
Session: NewCustomCookieStore(generateSessionKeys(sessionSecurityKey)),
Session: NewCustomCookieStore(generateSessionKeys(sessionSecurityKey, sessionSalt)),
}
}

// generateSessionKeys creates a signed encryption key for the cookie store
func generateSessionKeys(sessionSecurityKey string) ([]byte, []byte) {
func generateSessionKeys(sessionSecurityKey string, salt string) ([]byte, []byte) {
// Take the configured security key and generate 96 bytes of data. This is
// used as the signing and encryption keys for the cookie store. For details
// on the PBKDF2 function: https://en.wikipedia.org/wiki/PBKDF2
Expand Down
6 changes: 3 additions & 3 deletions internal/session/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
)

func TestGenerateSessionKeys(t *testing.T) {
b1, b2 := generateSessionKeys("testing")
b1, b2 := generateSessionKeys("testing", "0123456789")

if len(b1) != 64 || len(b2) != 32 {
t.Errorf("Wrong byte length's returned")
Expand All @@ -33,7 +33,7 @@ func TestGenerateSessionKeys(t *testing.T) {
}

func TestInitSessionStore(t *testing.T) {
s := New("testing")
s := New("testing", "0123456789")
if s.Session == nil {
t.Errorf("Session Store is nil. Did not get initialized")
return
Expand All @@ -42,7 +42,7 @@ func TestInitSessionStore(t *testing.T) {
}

func TestCleanupSession(t *testing.T) {
s := New("testing")
s := New("testing", "0123456789")
session := &sessions.Session{}
// create a test http server
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand Down

0 comments on commit 8bd1c14

Please sign in to comment.