@marcel91200 / caddy Mirror · read-only / commits / 51db7f03
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 07:15 UTC

pki: honor skip_install_trust for explicit tls internal issuers (#7894)

Gautam R committed Aug 25, 2026 at 09:49 UTC 51db7f0313b98e047345343a939bb2a3bd975602
2 files changed +119
caddyconfig/httpcaddyfile/pkiapp.go
+29
@@ -22,6 +22,7 @@ import (
22 "github.com/caddyserver/caddy/v2/caddyconfig"
23 "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
24 "github.com/caddyserver/caddy/v2/modules/caddypki"
25 + "github.com/caddyserver/caddy/v2/modules/caddytls"
26 )
27
28 func init() {
@@ -260,5 +261,33 @@ func (st ServerType) buildPKIApp(
261 pkiApp.CAs[ca.ID] = ca
262 }
263
264 + // an explicit site-level internal issuer creates its own CA
265 + // regardless of `auto_https`, so make sure `skip_install_trust`
266 + // is honored for it too; otherwise the CA is created later at
267 + // runtime with trust installation left on
268 + if skipInstallTrust {
269 + for _, p := range pairings {
270 + for _, sblock := range p.serverBlocks {
271 + for _, issuerCfgValue := range sblock.pile["tls.cert_issuer"] {
272 + internalIssuer, ok := issuerCfgValue.Value.(*caddytls.InternalIssuer)
273 + if !ok {
274 + continue
275 + }
276 + caID := internalIssuer.CA
277 + if caID == "" {
278 + caID = caddypki.DefaultCAID
279 + }
280 + if _, ok := pkiApp.CAs[caID]; ok {
281 + continue
282 + }
283 + ca := new(caddypki.CA)
284 + ca.ID = caID
285 + ca.InstallTrust = &falseBool
286 + pkiApp.CAs[ca.ID] = ca
287 + }
288 + }
289 + }
290 + }
291 +
292 return pkiApp, warnings, nil
293 }
caddyconfig/httpcaddyfile/pkiapp_test.go
+90
@@ -67,6 +67,96 @@ func TestParsePKIApp_maintenanceIntervalAndRenewalWindowRatio(t *testing.T) {
67 }
68 }
69
70 +// adaptedPKIConfig runs the given Caddyfile through the adapter and
71 +// returns just the parts of the resulting JSON this test cares about:
72 +// which CAs got a certificate_authorities entry, and whether install_trust
73 +// was set to false for each.
74 +func adaptedPKIConfig(t *testing.T, input string) map[string]struct {
75 + InstallTrust *bool `json:"install_trust,omitempty"`
76 +} {
77 + t.Helper()
78 +
79 + adapter := caddyfile.Adapter{ServerType: ServerType{}}
80 + out, _, err := adapter.Adapt([]byte(input), nil)
81 + if err != nil {
82 + t.Fatalf("Adapt failed: %v", err)
83 + }
84 +
85 + var cfg struct {
86 + Apps struct {
87 + PKI struct {
88 + CertificateAuthorities map[string]struct {
89 + InstallTrust *bool `json:"install_trust,omitempty"`
90 + } `json:"certificate_authorities,omitempty"`
91 + } `json:"pki,omitempty"`
92 + } `json:"apps"`
93 + }
94 + if err := json.Unmarshal(out, &cfg); err != nil {
95 + t.Fatalf("unmarshal config: %v", err)
96 + }
97 + return cfg.Apps.PKI.CertificateAuthorities
98 +}
99 +
100 +func TestParsePKIApp_skipInstallTrustHonoredForInternalTLSDefaultCA(t *testing.T) {
101 + input := `{
102 + auto_https off
103 + skip_install_trust
104 + }
105 + internal.example.com {
106 + tls internal
107 + }
108 + `
109 + cas := adaptedPKIConfig(t, input)
110 +
111 + ca, ok := cas["local"]
112 + if !ok {
113 + t.Fatal("expected certificate_authorities.local to exist")
114 + }
115 + if ca.InstallTrust == nil || *ca.InstallTrust != false {
116 + t.Errorf("install_trust = %v, want false", ca.InstallTrust)
117 + }
118 +}
119 +
120 +func TestParsePKIApp_skipInstallTrustHonoredForInternalTLSCustomCA(t *testing.T) {
121 + input := `{
122 + auto_https off
123 + skip_install_trust
124 + }
125 + internal.example.com {
126 + tls {
127 + issuer internal {
128 + ca mycustomca
129 + }
130 + }
131 + }
132 + `
133 + cas := adaptedPKIConfig(t, input)
134 +
135 + ca, ok := cas["mycustomca"]
136 + if !ok {
137 + t.Fatal("expected certificate_authorities.mycustomca to exist")
138 + }
139 + if ca.InstallTrust == nil || *ca.InstallTrust != false {
140 + t.Errorf("install_trust = %v, want false", ca.InstallTrust)
141 + }
142 +}
143 +
144 +func TestParsePKIApp_noPKIAppWhenNoInternalIssuerConfigured(t *testing.T) {
145 + input := `{
146 + auto_https off
147 + skip_install_trust
148 + }
149 + localhost:8080 {
150 + respond "no tls internal used anywhere"
151 + }
152 + `
153 + cas := adaptedPKIConfig(t, input)
154 +
155 + if len(cas) != 0 {
156 + t.Errorf("expected no certificate_authorities, got %v", cas)
157 + }
158 +}
159 +
160 func TestParsePKIApp_renewalWindowRatioInvalid(t *testing.T) {
161 input := `{
162 pki {