You've already forked oauth2-proxy
mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-08-08 22:46:33 +02:00
feat(cookie): add feature support for cookie-secret-file (#3104)
* feat: add feature support for cookie-secret-file --------- Signed-off-by: Jan Larwig <jan@larwig.com> Co-Authored-By: Sandy Chen <Yuxuan.Chen@morganstanley.com> Co-authored-by: Jan Larwig <jan@larwig.com>
This commit is contained in:
@ -1,8 +1,11 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
@ -10,6 +13,7 @@ import (
|
||||
type Cookie struct {
|
||||
Name string `flag:"cookie-name" cfg:"cookie_name"`
|
||||
Secret string `flag:"cookie-secret" cfg:"cookie_secret"`
|
||||
SecretFile string `flag:"cookie-secret-file" cfg:"cookie_secret_file"`
|
||||
Domains []string `flag:"cookie-domain" cfg:"cookie_domains"`
|
||||
Path string `flag:"cookie-path" cfg:"cookie_path"`
|
||||
Expire time.Duration `flag:"cookie-expire" cfg:"cookie_expire"`
|
||||
@ -18,8 +22,8 @@ type Cookie struct {
|
||||
HTTPOnly bool `flag:"cookie-httponly" cfg:"cookie_httponly"`
|
||||
SameSite string `flag:"cookie-samesite" cfg:"cookie_samesite"`
|
||||
CSRFPerRequest bool `flag:"cookie-csrf-per-request" cfg:"cookie_csrf_per_request"`
|
||||
CSRFExpire time.Duration `flag:"cookie-csrf-expire" cfg:"cookie_csrf_expire"`
|
||||
CSRFPerRequestLimit int `flag:"cookie-csrf-per-request-limit" cfg:"cookie_csrf_per_request_limit"`
|
||||
CSRFExpire time.Duration `flag:"cookie-csrf-expire" cfg:"cookie_csrf_expire"`
|
||||
}
|
||||
|
||||
func cookieFlagSet() *pflag.FlagSet {
|
||||
@ -27,6 +31,7 @@ func cookieFlagSet() *pflag.FlagSet {
|
||||
|
||||
flagSet.String("cookie-name", "_oauth2_proxy", "the name of the cookie that the oauth_proxy creates")
|
||||
flagSet.String("cookie-secret", "", "the seed string for secure cookies (optionally base64 encoded)")
|
||||
flagSet.String("cookie-secret-file", "", "For defining a separate cookie secret file to read the encryption key from")
|
||||
flagSet.StringSlice("cookie-domain", []string{}, "Optional cookie domains to force cookies to (ie: `.yourcompany.com`). The longest domain matching the request's host will be used (or the shortest cookie domain if there is no match).")
|
||||
flagSet.String("cookie-path", "/", "an optional cookie path to force cookies to (ie: /poc/)*")
|
||||
flagSet.Duration("cookie-expire", time.Duration(168)*time.Hour, "expire timeframe for cookie")
|
||||
@ -43,16 +48,33 @@ func cookieFlagSet() *pflag.FlagSet {
|
||||
// cookieDefaults creates a Cookie populating each field with its default value
|
||||
func cookieDefaults() Cookie {
|
||||
return Cookie{
|
||||
Name: "_oauth2_proxy",
|
||||
Secret: "",
|
||||
Domains: nil,
|
||||
Path: "/",
|
||||
Expire: time.Duration(168) * time.Hour,
|
||||
Refresh: time.Duration(0),
|
||||
Secure: true,
|
||||
HTTPOnly: true,
|
||||
SameSite: "",
|
||||
CSRFPerRequest: false,
|
||||
CSRFExpire: time.Duration(15) * time.Minute,
|
||||
Name: "_oauth2_proxy",
|
||||
Secret: "",
|
||||
SecretFile: "",
|
||||
Domains: nil,
|
||||
Path: "/",
|
||||
Expire: time.Duration(168) * time.Hour,
|
||||
Refresh: time.Duration(0),
|
||||
Secure: true,
|
||||
HTTPOnly: true,
|
||||
SameSite: "",
|
||||
CSRFPerRequest: false,
|
||||
CSRFPerRequestLimit: 0,
|
||||
CSRFExpire: time.Duration(15) * time.Minute,
|
||||
}
|
||||
}
|
||||
|
||||
// GetSecret returns the cookie secret, reading from file if SecretFile is set
|
||||
func (c *Cookie) GetSecret() (secret string, err error) {
|
||||
if c.Secret != "" || c.SecretFile == "" {
|
||||
return c.Secret, nil
|
||||
}
|
||||
|
||||
fileSecret, err := os.ReadFile(c.SecretFile)
|
||||
if err != nil {
|
||||
logger.Errorf("error reading cookie secret file %s: %s", c.SecretFile, err)
|
||||
return "", errors.New("could not read cookie secret file")
|
||||
}
|
||||
|
||||
return string(fileSecret), nil
|
||||
}
|
||||
|
70
pkg/apis/options/cookie_test.go
Normal file
70
pkg/apis/options/cookie_test.go
Normal file
@ -0,0 +1,70 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCookieGetSecret(t *testing.T) {
|
||||
t.Run("returns secret when Secret is set", func(t *testing.T) {
|
||||
c := &Cookie{
|
||||
Secret: "my-secret",
|
||||
SecretFile: "",
|
||||
}
|
||||
secret, err := c.GetSecret()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "my-secret", secret)
|
||||
})
|
||||
|
||||
t.Run("returns secret when both Secret and SecretFile are set", func(t *testing.T) {
|
||||
c := &Cookie{
|
||||
Secret: "my-secret",
|
||||
SecretFile: "/some/file",
|
||||
}
|
||||
secret, err := c.GetSecret()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "my-secret", secret)
|
||||
})
|
||||
|
||||
t.Run("reads from file when only SecretFile is set", func(t *testing.T) {
|
||||
// Create a temporary file
|
||||
tmpfile, err := os.CreateTemp("", "cookie-secret-test")
|
||||
assert.NoError(t, err)
|
||||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
_, err = tmpfile.Write([]byte("file-secret"))
|
||||
assert.NoError(t, err)
|
||||
tmpfile.Close()
|
||||
|
||||
c := &Cookie{
|
||||
Secret: "",
|
||||
SecretFile: tmpfile.Name(),
|
||||
}
|
||||
secret, err := c.GetSecret()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "file-secret", secret)
|
||||
})
|
||||
|
||||
t.Run("returns error when file does not exist", func(t *testing.T) {
|
||||
c := &Cookie{
|
||||
Secret: "",
|
||||
SecretFile: "/nonexistent/file",
|
||||
}
|
||||
secret, err := c.GetSecret()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "", secret)
|
||||
assert.Contains(t, err.Error(), "could not read cookie secret file")
|
||||
})
|
||||
|
||||
t.Run("returns empty when both Secret and SecretFile are empty", func(t *testing.T) {
|
||||
c := &Cookie{
|
||||
Secret: "",
|
||||
SecretFile: "",
|
||||
}
|
||||
secret, err := c.GetSecret()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "", secret)
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user