Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 46 additions & 7 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import (

"k8s.io/apiserver/pkg/server/dynamiccertificates"

oscrypto "github.com/openshift/library-go/pkg/crypto"

"github.com/openshift/oauth-proxy/util"
)

Expand Down Expand Up @@ -72,14 +70,55 @@ func (s *Server) ServeHTTP() {
log.Printf("HTTP: closing %s", listener.Addr())
}

func (s *Server) ServeHTTPS(ctx context.Context) {
addr := s.Opts.HttpsAddress
func (s *Server) buildTLSConfig() *tls.Config {
config := &tls.Config{
MinVersion: tls.VersionTLS13,
NextProtos: []string{"http/1.1"},
}

if s.Opts.TLSMinVersion != "" {
if v, ok := tlsVersionMap[s.Opts.TLSMinVersion]; ok {
config.MinVersion = v
}
}

config := oscrypto.SecureTLSConfig(&tls.Config{})
if config.NextProtos == nil {
config.NextProtos = []string{"http/1.1"}
if len(s.Opts.TLSCipherSuites) > 0 {
suites := make([]uint16, 0, len(s.Opts.TLSCipherSuites))
for _, name := range s.Opts.TLSCipherSuites {
if id, ok := tlsCipherSuiteMap[name]; ok {
suites = append(suites, id)
}
}
if len(suites) > 0 {
config.CipherSuites = suites
}
}

return config
}

var tlsVersionMap = map[string]uint16{
"VersionTLS10": tls.VersionTLS10,
"VersionTLS11": tls.VersionTLS11,
"VersionTLS12": tls.VersionTLS12,
"VersionTLS13": tls.VersionTLS13,
}

var tlsCipherSuiteMap = func() map[string]uint16 {
m := make(map[string]uint16)
for _, cs := range tls.CipherSuites() {
m[cs.Name] = cs.ID
}
for _, cs := range tls.InsecureCipherSuites() {
m[cs.Name] = cs.ID
}
return m
}()

func (s *Server) ServeHTTPS(ctx context.Context) {
addr := s.Opts.HttpsAddress
config := s.buildTLSConfig()

var err error
servingCertProvider, err := dynamiccertificates.NewDynamicServingContentFromFiles("serving", s.Opts.TLSCertFile, s.Opts.TLSKeyFile)
if err != nil {
Expand Down
85 changes: 85 additions & 0 deletions http_test.go
Comment thread
coleenquadros marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package main

import (
"crypto/tls"
"testing"
)

func TestBuildTLSConfig_Defaults(t *testing.T) {
s := &Server{Opts: &Options{}}
config := s.buildTLSConfig()

if config.MinVersion != tls.VersionTLS13 {
t.Errorf("Expected default MinVersion TLS 1.3 (%d), got %d", tls.VersionTLS13, config.MinVersion)
}
}

func TestBuildTLSConfig_MinVersion(t *testing.T) {
tests := []struct {
name string
minVersion string
expected uint16
}{
{
name: "VersionTLS12",
minVersion: "VersionTLS12",
expected: tls.VersionTLS12,
},
{
name: "VersionTLS13",
minVersion: "VersionTLS13",
expected: tls.VersionTLS13,
},
{
name: "unknown version keeps default",
minVersion: "VersionTLS99",
expected: tls.VersionTLS13,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &Server{Opts: &Options{TLSMinVersion: tt.minVersion}}
config := s.buildTLSConfig()

if config.MinVersion != tt.expected {
t.Errorf("Expected MinVersion %d, got %d", tt.expected, config.MinVersion)
}
})
}
}

func TestBuildTLSConfig_CipherSuites(t *testing.T) {
tests := []struct {
name string
cipherSuites []string
expectCount int
}{
{
name: "single valid cipher",
cipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"},
expectCount: 1,
},
{
name: "multiple valid ciphers",
cipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"},
expectCount: 2,
},
{
name: "unknown cipher is skipped",
cipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_INVALID_CIPHER"},
expectCount: 1,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &Server{Opts: &Options{TLSCipherSuites: tt.cipherSuites}}
config := s.buildTLSConfig()

if len(config.CipherSuites) != tt.expectCount {
t.Errorf("Expected %d cipher suites, got %d", tt.expectCount, len(config.CipherSuites))
}
})
}
}
15 changes: 15 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func main() {
openshiftCAs := NewStringArray()
clientCA := ""
upstreamCAs := NewStringArray()
tlsCipherSuitesStr := ""

config := flagSet.String("config", "", "path to config file")
showVersion := flagSet.Bool("version", false, "print version string")
Expand All @@ -42,6 +43,8 @@ func main() {
flagSet.String("tls-cert", "", "path to certificate file")
flagSet.String("tls-key", "", "path to private key file")
flagSet.StringVar(&clientCA, "tls-client-ca", clientCA, "path to a CA file for admitting client certificates.")
flagSet.String("tls-min-version", "", "minimum TLS version (e.g., VersionTLS12, VersionTLS13). Defaults to TLS 1.3")
flagSet.StringVar(&tlsCipherSuitesStr, "tls-cipher-suites", "", "comma-separated list of TLS cipher suites")
flagSet.String("redirect-url", "", "the OAuth Redirect URL. ie: \"https://internalapp.yourcompany.com/oauth/callback\"")
flagSet.Bool("set-xauthrequest", false, "set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode)")
flagSet.Var(upstreams, "upstream", "the http url(s) of the upstream endpoint or file:// paths for static files. Routing is based on the path")
Expand Down Expand Up @@ -131,6 +134,18 @@ func main() {
cfg.LoadEnvForStruct(opts)
options.Resolve(opts, flagSet, cfg)

// Parse comma-separated TLS cipher suites from CLI (overrides config file)
if tlsCipherSuitesStr != "" {
cipherSuites := strings.Split(tlsCipherSuitesStr, ",")
opts.TLSCipherSuites = make([]string, 0, len(cipherSuites))
for _, cipher := range cipherSuites {
trimmed := strings.TrimSpace(cipher)
if trimmed != "" {
opts.TLSCipherSuites = append(opts.TLSCipherSuites, trimmed)
}
}
}

var p providers.Provider
switch opts.Provider {
case "openshift":
Expand Down
2 changes: 2 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ type Options struct {
TLSCertFile string `flag:"tls-cert" cfg:"tls_cert_file"`
TLSKeyFile string `flag:"tls-key" cfg:"tls_key_file"`
TLSClientCAFile string `flag:"tls-client-ca" cfg:"tls_client_ca"`
TLSMinVersion string `flag:"tls-min-version" cfg:"tls_min_version"`
TLSCipherSuites []string `cfg:"tls_cipher_suites"` // No flag tag - manually parsed after Resolve()

AuthenticatedEmailsFile string `flag:"authenticated-emails-file" cfg:"authenticated_emails_file"`
EmailDomains []string `flag:"email-domain" cfg:"email_domains"`
Expand Down