Skip to content

Commit a747f61

Browse files
committed
Add OIDC client secret support to policy server
Allow the policy server to accept an OIDC client secret via CLI flag (--oidc-client-secret) or config file (policy.oidc.client_secret). The secret is included in the bootstrap response so clients can use it for authentication with confidential OIDC clients.
1 parent 18f0773 commit a747f61

5 files changed

Lines changed: 50 additions & 16 deletions

File tree

cmd/epithet/policy.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ import (
2222
// PolicyOIDCConfig holds OIDC configuration for the policy server.
2323
// This is embedded in PolicyServerCLI to enable nested config paths like policy.oidc.issuer
2424
type PolicyOIDCConfig struct {
25-
Issuer string `help:"OIDC issuer URL" name:"issuer"`
26-
ClientID string `help:"OIDC client ID" name:"client-id"`
25+
Issuer string `help:"OIDC issuer URL" name:"issuer"`
26+
ClientID string `help:"OIDC client ID" name:"client-id"`
27+
ClientSecret string `help:"OIDC client secret (for confidential clients)" name:"client-secret"`
2728
}
2829

2930
// PolicyServerCLI defines the CLI flags for the policy server.
@@ -171,6 +172,9 @@ func (c *PolicyServerCLI) applyOverrides(cfg *policyserver.PolicyRulesConfig) {
171172
if c.OIDC.ClientID != "" {
172173
cfg.OIDC.ClientID = c.OIDC.ClientID
173174
}
175+
if c.OIDC.ClientSecret != "" {
176+
cfg.OIDC.ClientSecret = c.OIDC.ClientSecret
177+
}
174178
if c.DefaultExpiration != "" {
175179
if cfg.Defaults == nil {
176180
cfg.Defaults = &policyserver.DefaultPolicy{}

pkg/broker/auth.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,18 @@ func AuthConfigToCommand(auth caclient.BootstrapAuth) (string, error) {
148148
return "", fmt.Errorf("failed to get executable path: %w", err)
149149
}
150150

151-
// Build command: <executable> auth oidc --issuer X --client-id Y --scopes A,B,C
151+
// Build command: <executable> auth oidc --issuer X --client-id Y [--client-secret Z] --scopes A,B,C
152152
parts := []string{
153153
executable,
154154
"auth", "oidc",
155155
"--issuer", auth.Issuer,
156156
"--client-id", auth.ClientID,
157157
}
158158

159+
if auth.ClientSecret != "" {
160+
parts = append(parts, "--client-secret", auth.ClientSecret)
161+
}
162+
159163
if len(auth.Scopes) > 0 {
160164
parts = append(parts, "--scopes", strings.Join(auth.Scopes, ","))
161165
}

pkg/broker/auth_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,28 @@ func TestAuthConfigToCommand_OIDC_NoScopes(t *testing.T) {
417417
require.NotContains(t, cmd, "--scopes")
418418
}
419419

420+
func TestAuthConfigToCommand_OIDC_WithClientSecret(t *testing.T) {
421+
t.Parallel()
422+
423+
auth := caclient.BootstrapAuth{
424+
Type: "oidc",
425+
Issuer: "https://example.com",
426+
ClientID: "test-client",
427+
ClientSecret: "super-secret",
428+
Scopes: []string{"openid"},
429+
}
430+
431+
cmd, err := AuthConfigToCommand(auth)
432+
require.NoError(t, err)
433+
434+
// Command should contain --client-secret when present
435+
require.Contains(t, cmd, "auth oidc")
436+
require.Contains(t, cmd, "--issuer https://example.com")
437+
require.Contains(t, cmd, "--client-id test-client")
438+
require.Contains(t, cmd, "--client-secret super-secret")
439+
require.Contains(t, cmd, "--scopes openid")
440+
}
441+
420442
func TestAuthConfigToCommand_Command(t *testing.T) {
421443
t.Parallel()
422444

pkg/caclient/caclient.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ type BootstrapAuth struct {
9797
Type string `json:"type"`
9898

9999
// OIDC fields (when type="oidc")
100-
Issuer string `json:"issuer,omitempty"`
101-
ClientID string `json:"client_id,omitempty"`
102-
Scopes []string `json:"scopes,omitempty"`
100+
Issuer string `json:"issuer,omitempty"`
101+
ClientID string `json:"client_id,omitempty"`
102+
ClientSecret string `json:"client_secret,omitempty"`
103+
Scopes []string `json:"scopes,omitempty"`
103104

104105
// Command field (when type="command") - opaque string
105106
Command string `json:"command,omitempty"`

pkg/policyserver/policy_config.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ type PolicyRulesConfig struct {
2121

2222
// OIDCConfig represents OIDC configuration for token validation
2323
type OIDCConfig struct {
24-
Issuer string `yaml:"issuer" json:"issuer"`
25-
ClientID string `yaml:"client_id" json:"client_id"`
26-
Scopes []string `yaml:"scopes,omitempty" json:"scopes,omitempty"` // Optional, defaults to ["openid", "profile", "email"]
24+
Issuer string `yaml:"issuer" json:"issuer"`
25+
ClientID string `yaml:"client_id" json:"client_id"`
26+
ClientSecret string `yaml:"client_secret,omitempty" json:"client_secret,omitempty"` // Optional, for confidential clients
27+
Scopes []string `yaml:"scopes,omitempty" json:"scopes,omitempty"` // Optional, defaults to ["openid", "profile", "email"]
2728
}
2829

2930
// DefaultScopes returns the default OIDC scopes
@@ -38,9 +39,10 @@ type BootstrapAuth struct {
3839
Type string `json:"type"`
3940

4041
// OIDC fields (when type="oidc")
41-
Issuer string `json:"issuer,omitempty"`
42-
ClientID string `json:"client_id,omitempty"`
43-
Scopes []string `json:"scopes,omitempty"`
42+
Issuer string `json:"issuer,omitempty"`
43+
ClientID string `json:"client_id,omitempty"`
44+
ClientSecret string `json:"client_secret,omitempty"`
45+
Scopes []string `json:"scopes,omitempty"`
4446

4547
// Command field (when type="command") - opaque string
4648
Command string `json:"command,omitempty"`
@@ -167,10 +169,11 @@ func (c *PolicyRulesConfig) BootstrapAuth() BootstrapAuth {
167169
}
168170

169171
return BootstrapAuth{
170-
Type: "oidc",
171-
Issuer: c.OIDC.Issuer,
172-
ClientID: c.OIDC.ClientID,
173-
Scopes: scopes,
172+
Type: "oidc",
173+
Issuer: c.OIDC.Issuer,
174+
ClientID: c.OIDC.ClientID,
175+
ClientSecret: c.OIDC.ClientSecret,
176+
Scopes: scopes,
174177
}
175178
}
176179

0 commit comments

Comments
 (0)