mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-26 13:43:47 +03:00
httpcaddyfile: Add preferred_chains
global option and issuer subdirective (#4192)
* Added preferred_chains option to Caddyfile * Caddyfile adapt tests for preferred_chains
This commit is contained in:
parent
76913b19ff
commit
1e92258dd6
5 changed files with 187 additions and 1 deletions
|
@ -49,6 +49,7 @@ func init() {
|
|||
RegisterGlobalOption("servers", parseServerOptions)
|
||||
RegisterGlobalOption("ocsp_stapling", parseOCSPStaplingOptions)
|
||||
RegisterGlobalOption("log", parseLogOptions)
|
||||
RegisterGlobalOption("preferred_chains", parseOptPreferredChains)
|
||||
}
|
||||
|
||||
func parseOptTrue(d *caddyfile.Dispenser, _ interface{}) (interface{}, error) { return true, nil }
|
||||
|
@ -452,3 +453,8 @@ func parseLogOptions(d *caddyfile.Dispenser, existingVal interface{}) (interface
|
|||
|
||||
return configValues, nil
|
||||
}
|
||||
|
||||
func parseOptPreferredChains(d *caddyfile.Dispenser, _ interface{}) (interface{}, error) {
|
||||
d.Next()
|
||||
return caddytls.ParseCaddyfilePreferredChainsOptions(d)
|
||||
}
|
||||
|
|
|
@ -321,7 +321,8 @@ func (st ServerType) buildTLSApp(
|
|||
globalACMECARoot := options["acme_ca_root"]
|
||||
globalACMEDNS := options["acme_dns"]
|
||||
globalACMEEAB := options["acme_eab"]
|
||||
hasGlobalACMEDefaults := globalEmail != nil || globalACMECA != nil || globalACMECARoot != nil || globalACMEDNS != nil || globalACMEEAB != nil
|
||||
globalPreferredChains := options["preferred_chains"]
|
||||
hasGlobalACMEDefaults := globalEmail != nil || globalACMECA != nil || globalACMECARoot != nil || globalACMEDNS != nil || globalACMEEAB != nil || globalPreferredChains != nil
|
||||
if hasGlobalACMEDefaults {
|
||||
for _, ap := range tlsApp.Automation.Policies {
|
||||
if len(ap.Issuers) == 0 {
|
||||
|
@ -405,6 +406,7 @@ func fillInGlobalACMEDefaults(issuer certmagic.Issuer, options map[string]interf
|
|||
globalACMECARoot := options["acme_ca_root"]
|
||||
globalACMEDNS := options["acme_dns"]
|
||||
globalACMEEAB := options["acme_eab"]
|
||||
globalPreferredChains := options["preferred_chains"]
|
||||
|
||||
if globalEmail != nil && acmeIssuer.Email == "" {
|
||||
acmeIssuer.Email = globalEmail.(string)
|
||||
|
@ -425,6 +427,9 @@ func fillInGlobalACMEDefaults(issuer certmagic.Issuer, options map[string]interf
|
|||
if globalACMEEAB != nil && acmeIssuer.ExternalAccount == nil {
|
||||
acmeIssuer.ExternalAccount = globalACMEEAB.(*acme.EAB)
|
||||
}
|
||||
if globalPreferredChains != nil && acmeIssuer.PreferredChains == nil {
|
||||
acmeIssuer.PreferredChains = globalPreferredChains.(*caddytls.ChainPreference)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
preferred_chains smallest
|
||||
}
|
||||
|
||||
localhost
|
||||
----------
|
||||
{
|
||||
"apps": {
|
||||
"http": {
|
||||
"servers": {
|
||||
"srv0": {
|
||||
"listen": [
|
||||
":443"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"localhost"
|
||||
]
|
||||
}
|
||||
],
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tls": {
|
||||
"automation": {
|
||||
"policies": [
|
||||
{
|
||||
"subjects": [
|
||||
"localhost"
|
||||
],
|
||||
"issuers": [
|
||||
{
|
||||
"module": "acme",
|
||||
"preferred_chains": {
|
||||
"smallest": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"module": "zerossl",
|
||||
"preferred_chains": {
|
||||
"smallest": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
localhost
|
||||
|
||||
tls {
|
||||
issuer acme {
|
||||
preferred_chains {
|
||||
any_common_name "Generic CA 1" "Generic CA 2"
|
||||
}
|
||||
}
|
||||
}
|
||||
----------
|
||||
{
|
||||
"apps": {
|
||||
"http": {
|
||||
"servers": {
|
||||
"srv0": {
|
||||
"listen": [
|
||||
":443"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"localhost"
|
||||
]
|
||||
}
|
||||
],
|
||||
"terminal": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tls": {
|
||||
"automation": {
|
||||
"policies": [
|
||||
{
|
||||
"subjects": [
|
||||
"localhost"
|
||||
],
|
||||
"issuers": [
|
||||
{
|
||||
"module": "acme",
|
||||
"preferred_chains": {
|
||||
"any_common_name": [
|
||||
"Generic CA 1",
|
||||
"Generic CA 2"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -265,6 +265,10 @@ func (iss *ACMEIssuer) GetACMEIssuer() *ACMEIssuer { return iss }
|
|||
// trusted_roots <pem_files...>
|
||||
// dns <provider_name> [<options>]
|
||||
// resolvers <dns_servers...>
|
||||
// preferred_chains [smallest] {
|
||||
// root_common_name <common_names...>
|
||||
// any_common_name <common_names...>
|
||||
// }
|
||||
// }
|
||||
//
|
||||
func (iss *ACMEIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||
|
@ -416,6 +420,13 @@ func (iss *ACMEIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
|||
return d.ArgErr()
|
||||
}
|
||||
|
||||
case "preferred_chains":
|
||||
chainPref, err := ParseCaddyfilePreferredChainsOptions(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
iss.PreferredChains = chainPref
|
||||
|
||||
default:
|
||||
return d.Errf("unrecognized ACME issuer property: %s", d.Val())
|
||||
}
|
||||
|
@ -452,6 +463,57 @@ func onDemandAskRequest(ask string, name string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func ParseCaddyfilePreferredChainsOptions(d *caddyfile.Dispenser) (*ChainPreference, error) {
|
||||
chainPref := new(ChainPreference)
|
||||
if d.NextArg() {
|
||||
smallestOpt := d.Val()
|
||||
if smallestOpt == "smallest" {
|
||||
trueBool := true
|
||||
chainPref.Smallest = &trueBool
|
||||
if d.NextArg() { // Only one argument allowed
|
||||
return nil, d.ArgErr()
|
||||
}
|
||||
if d.NextBlock(d.Nesting()) { // Don't allow other options when smallest == true
|
||||
return nil, d.Err("No more options are accepted when using the 'smallest' option")
|
||||
}
|
||||
} else { // Smallest option should always be 'smallest' or unset
|
||||
return nil, d.Errf("Invalid argument '%s'", smallestOpt)
|
||||
}
|
||||
}
|
||||
for nesting := d.Nesting(); d.NextBlock(nesting); {
|
||||
switch d.Val() {
|
||||
case "root_common_name":
|
||||
rootCommonNameOpt := d.RemainingArgs()
|
||||
chainPref.RootCommonName = rootCommonNameOpt
|
||||
if rootCommonNameOpt == nil {
|
||||
return nil, d.ArgErr()
|
||||
}
|
||||
if chainPref.AnyCommonName != nil {
|
||||
return nil, d.Err("Can't set root_common_name when any_common_name is already set")
|
||||
}
|
||||
|
||||
case "any_common_name":
|
||||
anyCommonNameOpt := d.RemainingArgs()
|
||||
chainPref.AnyCommonName = anyCommonNameOpt
|
||||
if anyCommonNameOpt == nil {
|
||||
return nil, d.ArgErr()
|
||||
}
|
||||
if chainPref.RootCommonName != nil {
|
||||
return nil, d.Err("Can't set any_common_name when root_common_name is already set")
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, d.Errf("Received unrecognized parameter '%s'", d.Val())
|
||||
}
|
||||
}
|
||||
|
||||
if chainPref.Smallest == nil && chainPref.RootCommonName == nil && chainPref.AnyCommonName == nil {
|
||||
return nil, d.Err("No options for preferred_chains received")
|
||||
}
|
||||
|
||||
return chainPref, nil
|
||||
}
|
||||
|
||||
// ChainPreference describes the client's preferred certificate chain,
|
||||
// useful if the CA offers alternate chains. The first matching chain
|
||||
// will be selected.
|
||||
|
|
Loading…
Reference in a new issue