httpcaddyfile: New acme_eab option (#3492)

* Adds global options for external account bindings

* Maybe other people use ctags too?

* Use nested block to configure external account

* go format files

* Restore acme_ca directive in test file

* Change Caddyfile config syntax for acme_eab

* Update test

Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
This commit is contained in:
Chris Ortman 2020-06-12 14:37:56 -05:00 committed by GitHub
parent 7da32f493a
commit d84a5d8427
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 125 additions and 5 deletions

View file

@ -31,8 +31,9 @@ func init() {
RegisterGlobalOption("experimental_http3", parseOptTrue) RegisterGlobalOption("experimental_http3", parseOptTrue)
RegisterGlobalOption("storage", parseOptStorage) RegisterGlobalOption("storage", parseOptStorage)
RegisterGlobalOption("acme_ca", parseOptSingleString) RegisterGlobalOption("acme_ca", parseOptSingleString)
RegisterGlobalOption("acme_dns", parseOptSingleString)
RegisterGlobalOption("acme_ca_root", parseOptSingleString) RegisterGlobalOption("acme_ca_root", parseOptSingleString)
RegisterGlobalOption("acme_dns", parseOptSingleString)
RegisterGlobalOption("acme_eab", parseOptACMEEAB)
RegisterGlobalOption("email", parseOptSingleString) RegisterGlobalOption("email", parseOptSingleString)
RegisterGlobalOption("admin", parseOptAdmin) RegisterGlobalOption("admin", parseOptAdmin)
RegisterGlobalOption("on_demand_tls", parseOptOnDemand) RegisterGlobalOption("on_demand_tls", parseOptOnDemand)
@ -180,6 +181,34 @@ func parseOptStorage(d *caddyfile.Dispenser) (interface{}, error) {
return storage, nil return storage, nil
} }
func parseOptACMEEAB(d *caddyfile.Dispenser) (interface{}, error) {
eab := new(caddytls.ExternalAccountBinding)
for d.Next() {
if d.NextArg() {
return nil, d.ArgErr()
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
switch d.Val() {
case "key_id":
if !d.NextArg() {
return nil, d.ArgErr()
}
eab.KeyID = d.Val()
case "hmac":
if !d.NextArg() {
return nil, d.ArgErr()
}
eab.HMAC = d.Val()
default:
return nil, d.Errf("unrecognized parameter '%s'", d.Val())
}
}
}
return eab, nil
}
func parseOptSingleString(d *caddyfile.Dispenser) (interface{}, error) { func parseOptSingleString(d *caddyfile.Dispenser) (interface{}, error) {
d.Next() // consume parameter name d.Next() // consume parameter name
if !d.Next() { if !d.Next() {

View file

@ -348,13 +348,15 @@ func (st ServerType) buildTLSApp(
// true, a non-nil value will always be returned (unless there is an error). // true, a non-nil value will always be returned (unless there is an error).
func newBaseAutomationPolicy(options map[string]interface{}, warnings []caddyconfig.Warning, always bool) (*caddytls.AutomationPolicy, error) { func newBaseAutomationPolicy(options map[string]interface{}, warnings []caddyconfig.Warning, always bool) (*caddytls.AutomationPolicy, error) {
acmeCA, hasACMECA := options["acme_ca"] acmeCA, hasACMECA := options["acme_ca"]
acmeDNS, hasACMEDNS := options["acme_dns"]
acmeCARoot, hasACMECARoot := options["acme_ca_root"] acmeCARoot, hasACMECARoot := options["acme_ca_root"]
acmeDNS, hasACMEDNS := options["acme_dns"]
acmeEAB, hasACMEEAB := options["acme_eab"]
email, hasEmail := options["email"] email, hasEmail := options["email"]
localCerts, hasLocalCerts := options["local_certs"] localCerts, hasLocalCerts := options["local_certs"]
keyType, hasKeyType := options["key_type"] keyType, hasKeyType := options["key_type"]
hasGlobalAutomationOpts := hasACMECA || hasACMEDNS || hasACMECARoot || hasEmail || hasLocalCerts || hasKeyType hasGlobalAutomationOpts := hasACMECA || hasACMECARoot || hasACMEDNS || hasACMEEAB || hasEmail || hasLocalCerts || hasKeyType
// if there are no global options related to automation policies // if there are no global options related to automation policies
// set, then we can just return right away // set, then we can just return right away
@ -396,6 +398,9 @@ func newBaseAutomationPolicy(options map[string]interface{}, warnings []caddycon
if acmeCARoot != nil { if acmeCARoot != nil {
mgr.TrustedRootsPEMFiles = []string{acmeCARoot.(string)} mgr.TrustedRootsPEMFiles = []string{acmeCARoot.(string)}
} }
if acmeEAB != nil {
mgr.ExternalAccount = acmeEAB.(*caddytls.ExternalAccountBinding)
}
if keyType != nil { if keyType != nil {
ap.KeyType = keyType.(string) ap.KeyType = keyType.(string)
} }

View file

@ -9,6 +9,7 @@
} }
acme_ca https://example.com acme_ca https://example.com
acme_ca_root /path/to/ca.crt acme_ca_root /path/to/ca.crt
email test@example.com email test@example.com
admin off admin off
on_demand_tls { on_demand_tls {

View file

@ -0,0 +1,85 @@
{
debug
http_port 8080
https_port 8443
default_sni localhost
order root first
storage file_system {
root /data
}
acme_ca https://example.com
acme_eab {
key_id 4K2scIVbBpNd-78scadB2g
hmac abcdefghijklmnopqrstuvwx-abcdefghijklnopqrstuvwxyz12ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh
}
acme_ca_root /path/to/ca.crt
email test@example.com
admin off
on_demand_tls {
ask https://example.com
interval 30s
burst 20
}
key_type ed25519
}
:80
----------
{
"admin": {
"disabled": true
},
"logging": {
"logs": {
"default": {
"level": "DEBUG"
}
}
},
"storage": {
"module": "file_system",
"root": "/data"
},
"apps": {
"http": {
"http_port": 8080,
"https_port": 8443,
"servers": {
"srv0": {
"listen": [
":80"
]
}
}
},
"tls": {
"automation": {
"policies": [
{
"issuer": {
"ca": "https://example.com",
"email": "test@example.com",
"external_account": {
"hmac": "abcdefghijklmnopqrstuvwx-abcdefghijklnopqrstuvwxyz12ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh",
"key_id": "4K2scIVbBpNd-78scadB2g"
},
"module": "acme",
"trusted_roots_pem_files": [
"/path/to/ca.crt"
]
},
"key_type": "ed25519"
}
],
"on_demand": {
"rate_limit": {
"interval": 30000000000,
"burst": 20
},
"ask": "https://example.com"
}
}
}
}
}