mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
auth: redact auth method client secret (#25328)
OIDC client secrets that users provide in auth method configuration are, well, secret, so we should hide them from API calls and event streams.
This commit is contained in:
3
.changelog/25328.txt
Normal file
3
.changelog/25328.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
```release-note:security
|
||||
auth: Redact OIDC client secret from API responses and event stream ([CVE-2025-1296](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-1296))
|
||||
```
|
||||
@@ -2084,7 +2084,7 @@ func (a *ACL) GetAuthMethod(
|
||||
|
||||
// We didn't encounter an error looking up the index; set the auth
|
||||
// method on the reply and exit successfully.
|
||||
reply.AuthMethod = out
|
||||
reply.AuthMethod = out.Sanitize()
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
@@ -110,6 +110,7 @@ func eventFromChange(change memdb.Change) (structs.Event, bool) {
|
||||
if !ok {
|
||||
return structs.Event{}, false
|
||||
}
|
||||
before = before.Sanitize()
|
||||
return structs.Event{
|
||||
Topic: structs.TopicACLAuthMethod,
|
||||
Key: before.Name,
|
||||
@@ -283,6 +284,7 @@ func eventFromChange(change memdb.Change) (structs.Event, bool) {
|
||||
if !ok {
|
||||
return structs.Event{}, false
|
||||
}
|
||||
after = after.Sanitize()
|
||||
return structs.Event{
|
||||
Topic: structs.TopicACLAuthMethod,
|
||||
Key: after.Name,
|
||||
|
||||
@@ -978,6 +978,21 @@ func (a *ACLAuthMethod) Validate(minTTL, maxTTL time.Duration) error {
|
||||
return mErr.ErrorOrNil()
|
||||
}
|
||||
|
||||
// Sanitize returns a copy of the ACLAuthMethod with any secrets redacted
|
||||
func (a *ACLAuthMethod) Sanitize() *ACLAuthMethod {
|
||||
if a == nil || a.Config == nil {
|
||||
return a
|
||||
}
|
||||
// copy to ensure we do not mutate a pointer pulled directly out of state.
|
||||
clean := a.Copy()
|
||||
// clean nested structs here, so it's obvious what all is being cleaned
|
||||
// in one spot, rather than follow a stack of sanitization calls.
|
||||
if clean.Config.OIDCClientSecret != "" {
|
||||
clean.Config.OIDCClientSecret = "redacted"
|
||||
}
|
||||
return clean
|
||||
}
|
||||
|
||||
// TokenLocalityIsGlobal returns whether the auth method creates global ACL
|
||||
// tokens or not.
|
||||
func (a *ACLAuthMethod) TokenLocalityIsGlobal() bool {
|
||||
|
||||
@@ -1263,6 +1263,24 @@ func TestACLAuthMethod_Validate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize method should redact sensitive values
|
||||
func TestACLAuthMethod_Sanitize(t *testing.T) {
|
||||
// these just shouldn't nil panic
|
||||
am := &ACLAuthMethod{}
|
||||
am.Sanitize()
|
||||
am.Config = &ACLAuthMethodConfig{}
|
||||
am.Sanitize()
|
||||
|
||||
t.Run("client secret", func(t *testing.T) {
|
||||
am := am.Copy()
|
||||
am.Config.OIDCClientSecret = "very private secret"
|
||||
dirty := am.Config.OIDCClientSecret
|
||||
clean := am.Sanitize().Config.OIDCClientSecret
|
||||
must.Eq(t, "very private secret", dirty)
|
||||
must.Eq(t, "redacted", clean)
|
||||
})
|
||||
}
|
||||
|
||||
func TestACLAuthMethod_Merge(t *testing.T) {
|
||||
ci.Parallel(t)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user