acmeserver: warn when policy rules unset (#7469)
Some checks failed
Tests / test (./cmd/caddy/caddy, ~1.26.0, ubuntu-latest, 0, 1.26, linux) (push) Failing after 18s
Tests / test (s390x on IBM Z) (push) Has been skipped
Tests / goreleaser-check (push) Has been skipped
Cross-Build / build (~1.26.0, 1.26, aix) (push) Failing after 15s
Cross-Build / build (~1.26.0, 1.26, darwin) (push) Failing after 39s
Cross-Build / build (~1.26.0, 1.26, dragonfly) (push) Failing after 16s
Cross-Build / build (~1.26.0, 1.26, freebsd) (push) Failing after 14s
Cross-Build / build (~1.26.0, 1.26, illumos) (push) Failing after 15s
Cross-Build / build (~1.26.0, 1.26, linux) (push) Failing after 15s
Cross-Build / build (~1.26.0, 1.26, netbsd) (push) Failing after 15s
Cross-Build / build (~1.26.0, 1.26, openbsd) (push) Failing after 15s
Cross-Build / build (~1.26.0, 1.26, solaris) (push) Failing after 16s
Cross-Build / build (~1.26.0, 1.26, windows) (push) Failing after 15s
Lint / lint (ubuntu-latest, linux) (push) Failing after 19s
Lint / govulncheck (push) Successful in 1m43s
Lint / dependency-review (push) Failing after 16s
OpenSSF Scorecard supply-chain security / Scorecard analysis (push) Failing after 17s
Tests / test (./cmd/caddy/caddy, ~1.26.0, macos-14, 0, 1.26, mac) (push) Has been cancelled
Tests / test (./cmd/caddy/caddy.exe, ~1.26.0, windows-latest, True, 1.26, windows) (push) Has been cancelled
Lint / lint (macos-14, mac) (push) Has been cancelled
Lint / lint (windows-latest, windows) (push) Has been cancelled

This commit is contained in:
Oleh Konko | trust infra security audit & contribution | deterministic ai-augmented pipeline · human-verified 2026-02-11 18:54:51 +00:00 committed by GitHub
parent c0af7b665f
commit 0188ef2e62
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 111 additions and 0 deletions

View File

@ -140,6 +140,8 @@ func (ash *Handler) Provision(ctx caddy.Context) error {
}
}
ash.warnIfPolicyAllowsAll()
// get a reference to the configured CA
appModule, err := ctx.App("pki")
if err != nil {
@ -214,6 +216,21 @@ func (ash *Handler) Provision(ctx caddy.Context) error {
return nil
}
func (ash *Handler) warnIfPolicyAllowsAll() {
allow := ash.Policy.normalizeAllowRules()
deny := ash.Policy.normalizeDenyRules()
if allow != nil || deny != nil {
return
}
allowWildcardNames := ash.Policy != nil && ash.Policy.AllowWildcardNames
ash.logger.Warn(
"acme_server policy has no allow/deny rules; order identifiers are unrestricted (allow-all)",
zap.String("ca", ash.CA),
zap.Bool("allow_wildcard_names", allowWildcardNames),
)
}
func (ash Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
if strings.HasPrefix(r.URL.Path, ash.PathPrefix) {
acmeCtx := acme.NewContext(

View File

@ -0,0 +1,94 @@
package acmeserver
import (
"strings"
"testing"
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
)
func TestHandler_warnIfPolicyAllowsAll(t *testing.T) {
tests := []struct {
name string
policy *Policy
wantWarns int
wantAllowWildcard bool
}{
{
name: "warns when policy is nil",
policy: nil,
wantWarns: 1,
wantAllowWildcard: false,
},
{
name: "warns when allow/deny rules are empty",
policy: &Policy{},
wantWarns: 1,
wantAllowWildcard: false,
},
{
name: "warns when only allow_wildcard_names is true",
policy: &Policy{
AllowWildcardNames: true,
},
wantWarns: 1,
wantAllowWildcard: true,
},
{
name: "does not warn when allow rules are configured",
policy: &Policy{
Allow: &RuleSet{
Domains: []string{"example.com"},
},
},
wantWarns: 0,
wantAllowWildcard: false,
},
{
name: "does not warn when deny rules are configured",
policy: &Policy{
Deny: &RuleSet{
Domains: []string{"bad.example.com"},
},
},
wantWarns: 0,
wantAllowWildcard: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
core, logs := observer.New(zap.WarnLevel)
ash := &Handler{
CA: "local",
Policy: tt.policy,
logger: zap.New(core),
}
ash.warnIfPolicyAllowsAll()
if logs.Len() != tt.wantWarns {
t.Fatalf("expected %d warning logs, got %d", tt.wantWarns, logs.Len())
}
if tt.wantWarns == 0 {
return
}
entry := logs.All()[0]
if entry.Level != zap.WarnLevel {
t.Fatalf("expected warn level, got %v", entry.Level)
}
if !strings.Contains(entry.Message, "policy has no allow/deny rules") {
t.Fatalf("unexpected log message: %q", entry.Message)
}
ctx := entry.ContextMap()
if ctx["ca"] != "local" {
t.Fatalf("expected ca=local, got %v", ctx["ca"])
}
if ctx["allow_wildcard_names"] != tt.wantAllowWildcard {
t.Fatalf("expected allow_wildcard_names=%v, got %v", tt.wantAllowWildcard, ctx["allow_wildcard_names"])
}
})
}
}