diff --git a/agent/consul/acl_endpoint_legacy.go b/agent/consul/acl_endpoint_legacy.go index 28163f1091..48867fdb3a 100644 --- a/agent/consul/acl_endpoint_legacy.go +++ b/agent/consul/acl_endpoint_legacy.go @@ -103,6 +103,15 @@ func aclApplyInternal(srv *Server, args *structs.ACLRequest, reply *string) erro return acl.PermissionDeniedError{Cause: "Cannot modify root ACL"} } + // Ensure that we allow more permissive rule formats for legacy tokens, + // but that we correct them on the way into the system. + // + // DEPRECATED (ACL-Legacy-Compat) + correctedRules := structs.SanitizeLegacyACLTokenRules(args.ACL.Rules) + if correctedRules != "" { + args.ACL.Rules = correctedRules + } + // Validate the rules compile _, err := acl.NewPolicyFromSource("", 0, args.ACL.Rules, acl.SyntaxLegacy, srv.sentinel) if err != nil { diff --git a/agent/consul/fsm/snapshot_oss.go b/agent/consul/fsm/snapshot_oss.go index cb45fff7e3..1d9f9963f7 100644 --- a/agent/consul/fsm/snapshot_oss.go +++ b/agent/consul/fsm/snapshot_oss.go @@ -541,6 +541,15 @@ func restoreToken(header *snapshotHeader, restore *state.Restore, decoder *codec if err := decoder.Decode(&req); err != nil { return err } + + // DEPRECATED (ACL-Legacy-Compat) + if req.Rules != "" { + // When we restore a snapshot we may have to correct old HCL in legacy + // tokens to prevent the in-memory representation from using an older + // syntax. + structs.SanitizeLegacyACLToken(&req) + } + return restore.ACLToken(&req) } diff --git a/agent/consul/state/acl.go b/agent/consul/state/acl.go index baab837f47..0ed96dde5e 100644 --- a/agent/consul/state/acl.go +++ b/agent/consul/state/acl.go @@ -316,6 +316,17 @@ func (s *Store) aclTokenSetTxn(tx *memdb.Txn, idx uint64, token *structs.ACLToke return ErrMissingACLTokenAccessor } + // DEPRECATED (ACL-Legacy-Compat) + if token.Rules != "" { + // When we update a legacy acl token we may have to correct old HCL to + // prevent the propagation of older syntax into the state store and + // into in-memory representations. + correctedRules := structs.SanitizeLegacyACLTokenRules(token.Rules) + if correctedRules != "" { + token.Rules = correctedRules + } + } + // Check for an existing ACL // DEPRECATED (ACL-Legacy-Compat) - transition to using accessor index instead of secret once v1 compat is removed existing, err := tx.First("acl-tokens", "id", token.SecretID) diff --git a/agent/structs/acl_legacy.go b/agent/structs/acl_legacy.go index 42b0c3aa11..ebd8ece82b 100644 --- a/agent/structs/acl_legacy.go +++ b/agent/structs/acl_legacy.go @@ -60,8 +60,18 @@ type ACLs []*ACL // Convert does a 1-1 mapping of the ACLCompat structure to its ACLToken // equivalent. This will NOT fill in the other ACLToken fields or perform any other -// upgrade. +// upgrade (other than correcting an older HCL syntax that is no longer +// supported). func (a *ACL) Convert() *ACLToken { + // Ensure that we correct any old HCL in legacy tokens to prevent old + // syntax from leaking elsewhere into the system. + // + // DEPRECATED (ACL-Legacy-Compat) + correctedRules := SanitizeLegacyACLTokenRules(a.Rules) + if correctedRules != "" { + a.Rules = correctedRules + } + return &ACLToken{ AccessorID: "", SecretID: a.ID, diff --git a/agent/structs/sanitize_oss.go b/agent/structs/sanitize_oss.go new file mode 100644 index 0000000000..e0f4355758 --- /dev/null +++ b/agent/structs/sanitize_oss.go @@ -0,0 +1,25 @@ +// +build !ent + +package structs + +// SanitizeLegacyACLToken does nothing in the OSS builds. It does not mutate +// the input argument at all. +// +// In enterprise builds this hook is necessary to support fixing old multiline +// HCL strings in legacy token Sentinel policies into heredocs. If the token +// was updated and previously had a Hash set, this will also update it. +// +// DEPRECATED (ACL-Legacy-Compat) +func SanitizeLegacyACLToken(token *ACLToken) { +} + +// SanitizeLegacyACLTokenRules does nothing in the OSS builds. It always +// returns an empty string. +// +// In enterprise builds this hook is necessary to support fixing any old +// multiline HCL strings in legacy token Sentinel policies into heredocs. +// +// DEPRECATED (ACL-Legacy-Compat) +func SanitizeLegacyACLTokenRules(rules string) string { + return "" +}