Skip to content

Commit ac5970b

Browse files
committed
authn: test against (non) nil CA
1 parent d0de5e3 commit ac5970b

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

pkg/authn/oidc_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package authn
2+
3+
import (
4+
"context"
5+
"crypto/tls"
6+
"encoding/pem"
7+
"fmt"
8+
"net/http"
9+
"net/http/httptest"
10+
"os"
11+
"testing"
12+
)
13+
14+
// newTestOIDCIssuer creates an HTTPS test server serving minimal OIDC discovery and JWKS endpoints.
15+
func newTestOIDCIssuer() *httptest.Server {
16+
var ts *httptest.Server
17+
ts = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
18+
switch r.URL.Path {
19+
case "/.well-known/openid-configuration":
20+
w.Header().Set("Content-Type", "application/json")
21+
// Use the test server's URL as issuer and JWKS URI.
22+
fmt.Fprintf(w, `{"issuer": "%s", "jwks_uri": "%s/jwks"}`, ts.URL, ts.URL)
23+
case "/jwks":
24+
w.Header().Set("Content-Type", "application/json")
25+
fmt.Fprint(w, `{"keys": []}`)
26+
default:
27+
http.NotFound(w, r)
28+
}
29+
}))
30+
return ts
31+
}
32+
33+
func TestNewOIDCAuthenticator(t *testing.T) {
34+
// Create a dummy OIDC issuer (HTTPS).
35+
ts := newTestOIDCIssuer()
36+
defer ts.Close()
37+
38+
// Override the default transport to skip TLS verification.
39+
// This is needed because ts uses a self-signed certificate.
40+
// This should be legit for testing purpose, even with parallel test cases run at the same time.
41+
origTransport := http.DefaultTransport
42+
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
43+
defer func() {
44+
http.DefaultTransport = origTransport
45+
}()
46+
47+
// common dummy configuration values.
48+
baseConfig := OIDCConfig{
49+
IssuerURL: ts.URL,
50+
ClientID: "test-client",
51+
UsernameClaim: "email",
52+
UsernamePrefix: "",
53+
GroupsClaim: "groups",
54+
GroupsPrefix: "",
55+
SupportedSigningAlgs: []string{"RS256"},
56+
}
57+
58+
t.Run("EmptyCAFile", func(t *testing.T) {
59+
// CAFile is empty; the authenticator should default to using the host's trust store.
60+
config := baseConfig
61+
config.CAFile = ""
62+
63+
auth, err := NewOIDCAuthenticator(context.Background(), &config)
64+
if err != nil {
65+
t.Fatalf("expected no error, got: %v", err)
66+
}
67+
if auth.dynamicClientCA != nil {
68+
t.Errorf("expected dynamicClientCA to be nil when CAFile is empty, got non-nil")
69+
}
70+
})
71+
72+
t.Run("ValidCAFile", func(t *testing.T) {
73+
// Extract the test server's certificate and write it to a temporary file.
74+
if ts.TLS == nil || len(ts.TLS.Certificates) == 0 {
75+
t.Fatal("test server does not have a TLS certificate")
76+
}
77+
certBytes := ts.TLS.Certificates[0].Certificate[0]
78+
validCAPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
79+
80+
tmpFile, err := os.CreateTemp("", "test-ca-*.pem")
81+
if err != nil {
82+
t.Fatalf("failed to create temporary file: %v", err)
83+
}
84+
defer os.Remove(tmpFile.Name())
85+
86+
if _, err = tmpFile.Write(validCAPEM); err != nil {
87+
t.Fatalf("failed to write certificate to temporary file: %v", err)
88+
}
89+
tmpFile.Close()
90+
91+
config := baseConfig
92+
config.CAFile = tmpFile.Name()
93+
94+
auth, err := NewOIDCAuthenticator(context.Background(), &config)
95+
if err != nil {
96+
t.Fatalf("expected no error, got: %v", err)
97+
}
98+
if auth.dynamicClientCA == nil {
99+
t.Errorf("expected dynamicClientCA to be non-nil when a valid CAFile is provided")
100+
}
101+
})
102+
103+
t.Run("InvalidCAFile", func(t *testing.T) {
104+
config := baseConfig
105+
config.CAFile = "non-existent-file.pem"
106+
107+
_, err := NewOIDCAuthenticator(context.Background(), &config)
108+
if err == nil {
109+
t.Errorf("expected error when using an invalid CAFile, got nil")
110+
}
111+
})
112+
}

0 commit comments

Comments
 (0)