2020-03-07 14:15:25 +08:00
|
|
|
// Copyright 2015 Matthew Holt and The Caddy Authors
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package caddytls
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/x509"
|
|
|
|
"fmt"
|
|
|
|
"net/url"
|
2021-09-30 01:17:48 +08:00
|
|
|
"os"
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
"strconv"
|
2020-03-07 14:15:25 +08:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/caddyserver/caddy/v2"
|
2020-09-09 01:36:46 +08:00
|
|
|
"github.com/caddyserver/caddy/v2/caddyconfig"
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
2020-03-07 14:15:25 +08:00
|
|
|
"github.com/caddyserver/certmagic"
|
2020-07-31 05:18:14 +08:00
|
|
|
"github.com/mholt/acmez"
|
|
|
|
"github.com/mholt/acmez/acme"
|
|
|
|
"go.uber.org/zap"
|
2020-03-07 14:15:25 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
caddy.RegisterModule(ACMEIssuer{})
|
|
|
|
}
|
|
|
|
|
2021-09-25 08:31:01 +08:00
|
|
|
// ACMEIssuer manages certificates using the ACME protocol (RFC 8555).
|
2020-03-07 14:15:25 +08:00
|
|
|
type ACMEIssuer struct {
|
2021-09-25 08:31:01 +08:00
|
|
|
// The URL to the CA's ACME directory endpoint. Default:
|
|
|
|
// https://acme-v02.api.letsencrypt.org/directory
|
2020-03-07 14:15:25 +08:00
|
|
|
CA string `json:"ca,omitempty"`
|
|
|
|
|
|
|
|
// The URL to the test CA's ACME directory endpoint.
|
|
|
|
// This endpoint is only used during retries if there
|
2021-09-25 08:31:01 +08:00
|
|
|
// is a failure using the primary CA. Default:
|
|
|
|
// https://acme-staging-v02.api.letsencrypt.org/directory
|
2020-03-07 14:15:25 +08:00
|
|
|
TestCA string `json:"test_ca,omitempty"`
|
|
|
|
|
|
|
|
// Your email address, so the CA can contact you if necessary.
|
|
|
|
// Not required, but strongly recommended to provide one so
|
|
|
|
// you can be reached if there is a problem. Your email is
|
|
|
|
// not sent to any Caddy mothership or used for any purpose
|
|
|
|
// other than ACME transactions.
|
|
|
|
Email string `json:"email,omitempty"`
|
|
|
|
|
admin: Identity management, remote admin, config loaders (#3994)
This commits dds 3 separate, but very related features:
1. Automated server identity management
How do you know you're connecting to the server you think you are? How do you know the server connecting to you is the server instance you think it is? Mutually-authenticated TLS (mTLS) answers both of these questions. Using TLS to authenticate requires a public/private key pair (and the peer must trust the certificate you present to it).
Fortunately, Caddy is really good at managing certificates by now. We tap into that power to make it possible for Caddy to obtain and renew its own identity credentials, or in other words, a certificate that can be used for both server verification when clients connect to it, and client verification when it connects to other servers. Its associated private key is essentially its identity, and TLS takes care of possession proofs.
This configuration is simply a list of identifiers and an optional list of custom certificate issuers. Identifiers are things like IP addresses or DNS names that can be used to access the Caddy instance. The default issuers are ZeroSSL and Let's Encrypt, but these are public CAs, so they won't issue certs for private identifiers. Caddy will simply manage credentials for these, which other parts of Caddy can use, for example: remote administration or dynamic config loading (described below).
2. Remote administration over secure connection
This feature adds generic remote admin functionality that is safe to expose on a public interface.
- The "remote" (or "secure") endpoint is optional. It does not affect the standard/local/plaintext endpoint.
- It's the same as the [API endpoint on localhost:2019](https://caddyserver.com/docs/api), but over TLS.
- TLS cannot be disabled on this endpoint.
- TLS mutual auth is required, and cannot be disabled.
- The server's certificate _must_ be obtained and renewed via automated means, such as ACME. It cannot be manually loaded.
- The TLS server takes care of verifying the client.
- The admin handler takes care of application-layer permissions (methods and paths that each client is allowed to use).\
- Sensible defaults are still WIP.
- Config fields subject to change/renaming.
3. Dyanmic config loading at startup
Since this feature was planned in tandem with remote admin, and depends on its changes, I am combining them into one PR.
Dynamic config loading is where you tell Caddy how to load its config, and then it loads and runs that. First, it will load the config you give it (and persist that so it can be optionally resumed later). Then, it will try pulling its _actual_ config using the module you've specified (dynamically loaded configs are _not_ persisted to storage, since resuming them doesn't make sense).
This PR comes with a standard config loader module called `caddy.config_loaders.http`.
Caddyfile config for all of this can probably be added later.
COMMITS:
* admin: Secure socket for remote management
Functional, but still WIP.
Optional secure socket for the admin endpoint is designed
for remote management, i.e. to be exposed on a public
port. It enforces TLS mutual authentication which cannot
be disabled. The default port for this is :2021. The server
certificate cannot be specified manually, it MUST be
obtained from a certificate issuer (i.e. ACME).
More polish and sensible defaults are still in development.
Also cleaned up and consolidated the code related to
quitting the process.
* Happy lint
* Implement dynamic config loading; HTTP config loader module
This allows Caddy to load a dynamic config when it starts.
Dynamically-loaded configs are intentionally not persisted to storage.
Includes an implementation of the standard config loader, HTTPLoader.
Can be used to download configs over HTTP(S).
* Refactor and cleanup; prevent recursive config pulls
Identity management is now separated from remote administration.
There is no need to enable remote administration if all you want is identity
management, but you will need to configure identity management
if you want remote administration.
* Fix lint warnings
* Rename identities->identifiers for consistency
2021-01-28 07:16:04 +08:00
|
|
|
// If you have an existing account with the ACME server, put
|
|
|
|
// the private key here in PEM format. The ACME client will
|
|
|
|
// look up your account information with this key first before
|
|
|
|
// trying to create a new one. You can use placeholders here,
|
|
|
|
// for example if you have it in an environment variable.
|
|
|
|
AccountKey string `json:"account_key,omitempty"`
|
|
|
|
|
2020-04-01 11:08:02 +08:00
|
|
|
// If using an ACME CA that requires an external account
|
|
|
|
// binding, specify the CA-provided credentials here.
|
2020-07-31 05:18:14 +08:00
|
|
|
ExternalAccount *acme.EAB `json:"external_account,omitempty"`
|
2020-04-01 11:08:02 +08:00
|
|
|
|
2020-03-07 14:15:25 +08:00
|
|
|
// Time to wait before timing out an ACME operation.
|
2021-09-25 08:31:01 +08:00
|
|
|
// Default: 0 (no timeout)
|
2020-03-07 14:15:25 +08:00
|
|
|
ACMETimeout caddy.Duration `json:"acme_timeout,omitempty"`
|
|
|
|
|
|
|
|
// Configures the various ACME challenge types.
|
|
|
|
Challenges *ChallengesConfig `json:"challenges,omitempty"`
|
|
|
|
|
|
|
|
// An array of files of CA certificates to accept when connecting to the
|
|
|
|
// ACME CA. Generally, you should only use this if the ACME CA endpoint
|
|
|
|
// is internal or for development/testing purposes.
|
|
|
|
TrustedRootsPEMFiles []string `json:"trusted_roots_pem_files,omitempty"`
|
|
|
|
|
2020-12-16 03:16:04 +08:00
|
|
|
// Preferences for selecting alternate certificate chains, if offered
|
|
|
|
// by the CA. By default, the first offered chain will be selected.
|
|
|
|
// If configured, the chains may be sorted and the first matching chain
|
|
|
|
// will be selected.
|
|
|
|
PreferredChains *ChainPreference `json:"preferred_chains,omitempty"`
|
2020-11-13 06:02:35 +08:00
|
|
|
|
2020-03-07 14:15:25 +08:00
|
|
|
rootPool *x509.CertPool
|
2020-07-31 05:18:14 +08:00
|
|
|
logger *zap.Logger
|
2022-07-06 08:12:25 +08:00
|
|
|
|
|
|
|
template certmagic.ACMEIssuer // set at Provision
|
|
|
|
magic *certmagic.Config // set at PreCheck
|
|
|
|
issuer *certmagic.ACMEIssuer // set at PreCheck; result of template + magic
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// CaddyModule returns the Caddy module information.
|
|
|
|
func (ACMEIssuer) CaddyModule() caddy.ModuleInfo {
|
|
|
|
return caddy.ModuleInfo{
|
|
|
|
ID: "tls.issuance.acme",
|
|
|
|
New: func() caddy.Module { return new(ACMEIssuer) },
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
// Provision sets up iss.
|
|
|
|
func (iss *ACMEIssuer) Provision(ctx caddy.Context) error {
|
|
|
|
iss.logger = ctx.Logger(iss)
|
2020-07-31 05:18:14 +08:00
|
|
|
|
admin: Identity management, remote admin, config loaders (#3994)
This commits dds 3 separate, but very related features:
1. Automated server identity management
How do you know you're connecting to the server you think you are? How do you know the server connecting to you is the server instance you think it is? Mutually-authenticated TLS (mTLS) answers both of these questions. Using TLS to authenticate requires a public/private key pair (and the peer must trust the certificate you present to it).
Fortunately, Caddy is really good at managing certificates by now. We tap into that power to make it possible for Caddy to obtain and renew its own identity credentials, or in other words, a certificate that can be used for both server verification when clients connect to it, and client verification when it connects to other servers. Its associated private key is essentially its identity, and TLS takes care of possession proofs.
This configuration is simply a list of identifiers and an optional list of custom certificate issuers. Identifiers are things like IP addresses or DNS names that can be used to access the Caddy instance. The default issuers are ZeroSSL and Let's Encrypt, but these are public CAs, so they won't issue certs for private identifiers. Caddy will simply manage credentials for these, which other parts of Caddy can use, for example: remote administration or dynamic config loading (described below).
2. Remote administration over secure connection
This feature adds generic remote admin functionality that is safe to expose on a public interface.
- The "remote" (or "secure") endpoint is optional. It does not affect the standard/local/plaintext endpoint.
- It's the same as the [API endpoint on localhost:2019](https://caddyserver.com/docs/api), but over TLS.
- TLS cannot be disabled on this endpoint.
- TLS mutual auth is required, and cannot be disabled.
- The server's certificate _must_ be obtained and renewed via automated means, such as ACME. It cannot be manually loaded.
- The TLS server takes care of verifying the client.
- The admin handler takes care of application-layer permissions (methods and paths that each client is allowed to use).\
- Sensible defaults are still WIP.
- Config fields subject to change/renaming.
3. Dyanmic config loading at startup
Since this feature was planned in tandem with remote admin, and depends on its changes, I am combining them into one PR.
Dynamic config loading is where you tell Caddy how to load its config, and then it loads and runs that. First, it will load the config you give it (and persist that so it can be optionally resumed later). Then, it will try pulling its _actual_ config using the module you've specified (dynamically loaded configs are _not_ persisted to storage, since resuming them doesn't make sense).
This PR comes with a standard config loader module called `caddy.config_loaders.http`.
Caddyfile config for all of this can probably be added later.
COMMITS:
* admin: Secure socket for remote management
Functional, but still WIP.
Optional secure socket for the admin endpoint is designed
for remote management, i.e. to be exposed on a public
port. It enforces TLS mutual authentication which cannot
be disabled. The default port for this is :2021. The server
certificate cannot be specified manually, it MUST be
obtained from a certificate issuer (i.e. ACME).
More polish and sensible defaults are still in development.
Also cleaned up and consolidated the code related to
quitting the process.
* Happy lint
* Implement dynamic config loading; HTTP config loader module
This allows Caddy to load a dynamic config when it starts.
Dynamically-loaded configs are intentionally not persisted to storage.
Includes an implementation of the standard config loader, HTTPLoader.
Can be used to download configs over HTTP(S).
* Refactor and cleanup; prevent recursive config pulls
Identity management is now separated from remote administration.
There is no need to enable remote administration if all you want is identity
management, but you will need to configure identity management
if you want remote administration.
* Fix lint warnings
* Rename identities->identifiers for consistency
2021-01-28 07:16:04 +08:00
|
|
|
repl := caddy.NewReplacer()
|
|
|
|
|
2020-11-17 02:05:55 +08:00
|
|
|
// expand email address, if non-empty
|
|
|
|
if iss.Email != "" {
|
admin: Identity management, remote admin, config loaders (#3994)
This commits dds 3 separate, but very related features:
1. Automated server identity management
How do you know you're connecting to the server you think you are? How do you know the server connecting to you is the server instance you think it is? Mutually-authenticated TLS (mTLS) answers both of these questions. Using TLS to authenticate requires a public/private key pair (and the peer must trust the certificate you present to it).
Fortunately, Caddy is really good at managing certificates by now. We tap into that power to make it possible for Caddy to obtain and renew its own identity credentials, or in other words, a certificate that can be used for both server verification when clients connect to it, and client verification when it connects to other servers. Its associated private key is essentially its identity, and TLS takes care of possession proofs.
This configuration is simply a list of identifiers and an optional list of custom certificate issuers. Identifiers are things like IP addresses or DNS names that can be used to access the Caddy instance. The default issuers are ZeroSSL and Let's Encrypt, but these are public CAs, so they won't issue certs for private identifiers. Caddy will simply manage credentials for these, which other parts of Caddy can use, for example: remote administration or dynamic config loading (described below).
2. Remote administration over secure connection
This feature adds generic remote admin functionality that is safe to expose on a public interface.
- The "remote" (or "secure") endpoint is optional. It does not affect the standard/local/plaintext endpoint.
- It's the same as the [API endpoint on localhost:2019](https://caddyserver.com/docs/api), but over TLS.
- TLS cannot be disabled on this endpoint.
- TLS mutual auth is required, and cannot be disabled.
- The server's certificate _must_ be obtained and renewed via automated means, such as ACME. It cannot be manually loaded.
- The TLS server takes care of verifying the client.
- The admin handler takes care of application-layer permissions (methods and paths that each client is allowed to use).\
- Sensible defaults are still WIP.
- Config fields subject to change/renaming.
3. Dyanmic config loading at startup
Since this feature was planned in tandem with remote admin, and depends on its changes, I am combining them into one PR.
Dynamic config loading is where you tell Caddy how to load its config, and then it loads and runs that. First, it will load the config you give it (and persist that so it can be optionally resumed later). Then, it will try pulling its _actual_ config using the module you've specified (dynamically loaded configs are _not_ persisted to storage, since resuming them doesn't make sense).
This PR comes with a standard config loader module called `caddy.config_loaders.http`.
Caddyfile config for all of this can probably be added later.
COMMITS:
* admin: Secure socket for remote management
Functional, but still WIP.
Optional secure socket for the admin endpoint is designed
for remote management, i.e. to be exposed on a public
port. It enforces TLS mutual authentication which cannot
be disabled. The default port for this is :2021. The server
certificate cannot be specified manually, it MUST be
obtained from a certificate issuer (i.e. ACME).
More polish and sensible defaults are still in development.
Also cleaned up and consolidated the code related to
quitting the process.
* Happy lint
* Implement dynamic config loading; HTTP config loader module
This allows Caddy to load a dynamic config when it starts.
Dynamically-loaded configs are intentionally not persisted to storage.
Includes an implementation of the standard config loader, HTTPLoader.
Can be used to download configs over HTTP(S).
* Refactor and cleanup; prevent recursive config pulls
Identity management is now separated from remote administration.
There is no need to enable remote administration if all you want is identity
management, but you will need to configure identity management
if you want remote administration.
* Fix lint warnings
* Rename identities->identifiers for consistency
2021-01-28 07:16:04 +08:00
|
|
|
email, err := repl.ReplaceOrErr(iss.Email, true, true)
|
2020-11-17 02:05:55 +08:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("expanding email address '%s': %v", iss.Email, err)
|
|
|
|
}
|
|
|
|
iss.Email = email
|
|
|
|
}
|
|
|
|
|
admin: Identity management, remote admin, config loaders (#3994)
This commits dds 3 separate, but very related features:
1. Automated server identity management
How do you know you're connecting to the server you think you are? How do you know the server connecting to you is the server instance you think it is? Mutually-authenticated TLS (mTLS) answers both of these questions. Using TLS to authenticate requires a public/private key pair (and the peer must trust the certificate you present to it).
Fortunately, Caddy is really good at managing certificates by now. We tap into that power to make it possible for Caddy to obtain and renew its own identity credentials, or in other words, a certificate that can be used for both server verification when clients connect to it, and client verification when it connects to other servers. Its associated private key is essentially its identity, and TLS takes care of possession proofs.
This configuration is simply a list of identifiers and an optional list of custom certificate issuers. Identifiers are things like IP addresses or DNS names that can be used to access the Caddy instance. The default issuers are ZeroSSL and Let's Encrypt, but these are public CAs, so they won't issue certs for private identifiers. Caddy will simply manage credentials for these, which other parts of Caddy can use, for example: remote administration or dynamic config loading (described below).
2. Remote administration over secure connection
This feature adds generic remote admin functionality that is safe to expose on a public interface.
- The "remote" (or "secure") endpoint is optional. It does not affect the standard/local/plaintext endpoint.
- It's the same as the [API endpoint on localhost:2019](https://caddyserver.com/docs/api), but over TLS.
- TLS cannot be disabled on this endpoint.
- TLS mutual auth is required, and cannot be disabled.
- The server's certificate _must_ be obtained and renewed via automated means, such as ACME. It cannot be manually loaded.
- The TLS server takes care of verifying the client.
- The admin handler takes care of application-layer permissions (methods and paths that each client is allowed to use).\
- Sensible defaults are still WIP.
- Config fields subject to change/renaming.
3. Dyanmic config loading at startup
Since this feature was planned in tandem with remote admin, and depends on its changes, I am combining them into one PR.
Dynamic config loading is where you tell Caddy how to load its config, and then it loads and runs that. First, it will load the config you give it (and persist that so it can be optionally resumed later). Then, it will try pulling its _actual_ config using the module you've specified (dynamically loaded configs are _not_ persisted to storage, since resuming them doesn't make sense).
This PR comes with a standard config loader module called `caddy.config_loaders.http`.
Caddyfile config for all of this can probably be added later.
COMMITS:
* admin: Secure socket for remote management
Functional, but still WIP.
Optional secure socket for the admin endpoint is designed
for remote management, i.e. to be exposed on a public
port. It enforces TLS mutual authentication which cannot
be disabled. The default port for this is :2021. The server
certificate cannot be specified manually, it MUST be
obtained from a certificate issuer (i.e. ACME).
More polish and sensible defaults are still in development.
Also cleaned up and consolidated the code related to
quitting the process.
* Happy lint
* Implement dynamic config loading; HTTP config loader module
This allows Caddy to load a dynamic config when it starts.
Dynamically-loaded configs are intentionally not persisted to storage.
Includes an implementation of the standard config loader, HTTPLoader.
Can be used to download configs over HTTP(S).
* Refactor and cleanup; prevent recursive config pulls
Identity management is now separated from remote administration.
There is no need to enable remote administration if all you want is identity
management, but you will need to configure identity management
if you want remote administration.
* Fix lint warnings
* Rename identities->identifiers for consistency
2021-01-28 07:16:04 +08:00
|
|
|
// expand account key, if non-empty
|
|
|
|
if iss.AccountKey != "" {
|
|
|
|
accountKey, err := repl.ReplaceOrErr(iss.AccountKey, true, true)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("expanding account key PEM '%s': %v", iss.AccountKey, err)
|
|
|
|
}
|
|
|
|
iss.AccountKey = accountKey
|
|
|
|
}
|
|
|
|
|
2020-03-07 14:15:25 +08:00
|
|
|
// DNS providers
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
if iss.Challenges != nil && iss.Challenges.DNS != nil && iss.Challenges.DNS.ProviderRaw != nil {
|
|
|
|
val, err := ctx.LoadModule(iss.Challenges.DNS, "ProviderRaw")
|
2020-03-07 14:15:25 +08:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("loading DNS provider module: %v", err)
|
|
|
|
}
|
2020-07-31 05:18:14 +08:00
|
|
|
|
|
|
|
if deprecatedProvider, ok := val.(acmez.Solver); ok {
|
|
|
|
// TODO: For a temporary amount of time, we are allowing the use of DNS
|
|
|
|
// providers from go-acme/lego since there are so many providers implemented
|
|
|
|
// using that API -- they are adapted as an all-in-one Caddy module in this
|
|
|
|
// repository: https://github.com/caddy-dns/lego-deprecated - the module is a
|
|
|
|
// acmez.Solver type, so we use it directly. The user must set environment
|
|
|
|
// variables to configure it. Remove this shim once a sufficient number of
|
|
|
|
// DNS providers are implemented for the libdns APIs instead.
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
iss.Challenges.DNS.solver = deprecatedProvider
|
2020-05-03 07:23:36 +08:00
|
|
|
} else {
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
iss.Challenges.DNS.solver = &certmagic.DNS01Solver{
|
2020-07-31 05:18:14 +08:00
|
|
|
DNSProvider: val.(certmagic.ACMEDNSProvider),
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
TTL: time.Duration(iss.Challenges.DNS.TTL),
|
2022-04-23 06:09:11 +08:00
|
|
|
PropagationDelay: time.Duration(iss.Challenges.DNS.PropagationDelay),
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
PropagationTimeout: time.Duration(iss.Challenges.DNS.PropagationTimeout),
|
2020-08-22 10:30:14 +08:00
|
|
|
Resolvers: iss.Challenges.DNS.Resolvers,
|
2022-03-09 03:03:43 +08:00
|
|
|
OverrideDomain: iss.Challenges.DNS.OverrideDomain,
|
2020-05-03 07:23:36 +08:00
|
|
|
}
|
|
|
|
}
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// add any custom CAs to trust store
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
if len(iss.TrustedRootsPEMFiles) > 0 {
|
|
|
|
iss.rootPool = x509.NewCertPool()
|
|
|
|
for _, pemFile := range iss.TrustedRootsPEMFiles {
|
2021-09-30 01:17:48 +08:00
|
|
|
pemData, err := os.ReadFile(pemFile)
|
2020-03-07 14:15:25 +08:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("loading trusted root CA's PEM file: %s: %v", pemFile, err)
|
|
|
|
}
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
if !iss.rootPool.AppendCertsFromPEM(pemData) {
|
2020-03-07 14:15:25 +08:00
|
|
|
return fmt.Errorf("unable to add %s to trust pool: %v", pemFile, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-01 11:08:02 +08:00
|
|
|
var err error
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
iss.template, err = iss.makeIssuerTemplate()
|
2020-04-01 11:08:02 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-03-07 14:15:25 +08:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-03-26 01:28:54 +08:00
|
|
|
func (iss *ACMEIssuer) makeIssuerTemplate() (certmagic.ACMEIssuer, error) {
|
|
|
|
template := certmagic.ACMEIssuer{
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
CA: iss.CA,
|
|
|
|
TestCA: iss.TestCA,
|
|
|
|
Email: iss.Email,
|
admin: Identity management, remote admin, config loaders (#3994)
This commits dds 3 separate, but very related features:
1. Automated server identity management
How do you know you're connecting to the server you think you are? How do you know the server connecting to you is the server instance you think it is? Mutually-authenticated TLS (mTLS) answers both of these questions. Using TLS to authenticate requires a public/private key pair (and the peer must trust the certificate you present to it).
Fortunately, Caddy is really good at managing certificates by now. We tap into that power to make it possible for Caddy to obtain and renew its own identity credentials, or in other words, a certificate that can be used for both server verification when clients connect to it, and client verification when it connects to other servers. Its associated private key is essentially its identity, and TLS takes care of possession proofs.
This configuration is simply a list of identifiers and an optional list of custom certificate issuers. Identifiers are things like IP addresses or DNS names that can be used to access the Caddy instance. The default issuers are ZeroSSL and Let's Encrypt, but these are public CAs, so they won't issue certs for private identifiers. Caddy will simply manage credentials for these, which other parts of Caddy can use, for example: remote administration or dynamic config loading (described below).
2. Remote administration over secure connection
This feature adds generic remote admin functionality that is safe to expose on a public interface.
- The "remote" (or "secure") endpoint is optional. It does not affect the standard/local/plaintext endpoint.
- It's the same as the [API endpoint on localhost:2019](https://caddyserver.com/docs/api), but over TLS.
- TLS cannot be disabled on this endpoint.
- TLS mutual auth is required, and cannot be disabled.
- The server's certificate _must_ be obtained and renewed via automated means, such as ACME. It cannot be manually loaded.
- The TLS server takes care of verifying the client.
- The admin handler takes care of application-layer permissions (methods and paths that each client is allowed to use).\
- Sensible defaults are still WIP.
- Config fields subject to change/renaming.
3. Dyanmic config loading at startup
Since this feature was planned in tandem with remote admin, and depends on its changes, I am combining them into one PR.
Dynamic config loading is where you tell Caddy how to load its config, and then it loads and runs that. First, it will load the config you give it (and persist that so it can be optionally resumed later). Then, it will try pulling its _actual_ config using the module you've specified (dynamically loaded configs are _not_ persisted to storage, since resuming them doesn't make sense).
This PR comes with a standard config loader module called `caddy.config_loaders.http`.
Caddyfile config for all of this can probably be added later.
COMMITS:
* admin: Secure socket for remote management
Functional, but still WIP.
Optional secure socket for the admin endpoint is designed
for remote management, i.e. to be exposed on a public
port. It enforces TLS mutual authentication which cannot
be disabled. The default port for this is :2021. The server
certificate cannot be specified manually, it MUST be
obtained from a certificate issuer (i.e. ACME).
More polish and sensible defaults are still in development.
Also cleaned up and consolidated the code related to
quitting the process.
* Happy lint
* Implement dynamic config loading; HTTP config loader module
This allows Caddy to load a dynamic config when it starts.
Dynamically-loaded configs are intentionally not persisted to storage.
Includes an implementation of the standard config loader, HTTPLoader.
Can be used to download configs over HTTP(S).
* Refactor and cleanup; prevent recursive config pulls
Identity management is now separated from remote administration.
There is no need to enable remote administration if all you want is identity
management, but you will need to configure identity management
if you want remote administration.
* Fix lint warnings
* Rename identities->identifiers for consistency
2021-01-28 07:16:04 +08:00
|
|
|
AccountKeyPEM: iss.AccountKey,
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
CertObtainTimeout: time.Duration(iss.ACMETimeout),
|
|
|
|
TrustedRoots: iss.rootPool,
|
|
|
|
ExternalAccount: iss.ExternalAccount,
|
|
|
|
Logger: iss.logger,
|
2020-04-01 11:08:02 +08:00
|
|
|
}
|
|
|
|
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
if iss.Challenges != nil {
|
|
|
|
if iss.Challenges.HTTP != nil {
|
|
|
|
template.DisableHTTPChallenge = iss.Challenges.HTTP.Disabled
|
|
|
|
template.AltHTTPPort = iss.Challenges.HTTP.AlternatePort
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
if iss.Challenges.TLSALPN != nil {
|
|
|
|
template.DisableTLSALPNChallenge = iss.Challenges.TLSALPN.Disabled
|
|
|
|
template.AltTLSALPNPort = iss.Challenges.TLSALPN.AlternatePort
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
if iss.Challenges.DNS != nil {
|
|
|
|
template.DNS01Solver = iss.Challenges.DNS.solver
|
2020-05-01 06:15:20 +08:00
|
|
|
}
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
template.ListenHost = iss.Challenges.BindHost
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
|
|
|
|
2020-12-16 03:16:04 +08:00
|
|
|
if iss.PreferredChains != nil {
|
|
|
|
template.PreferredChains = certmagic.ChainPreference{
|
|
|
|
Smallest: iss.PreferredChains.Smallest,
|
|
|
|
AnyCommonName: iss.PreferredChains.AnyCommonName,
|
|
|
|
RootCommonName: iss.PreferredChains.RootCommonName,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-01 11:08:02 +08:00
|
|
|
return template, nil
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetConfig sets the associated certmagic config for this issuer.
|
|
|
|
// This is required because ACME needs values from the config in
|
|
|
|
// order to solve the challenges during issuance. This implements
|
|
|
|
// the ConfigSetter interface.
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
func (iss *ACMEIssuer) SetConfig(cfg *certmagic.Config) {
|
|
|
|
iss.magic = cfg
|
2022-07-06 08:12:25 +08:00
|
|
|
iss.issuer = certmagic.NewACMEIssuer(cfg, iss.template)
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// PreCheck implements the certmagic.PreChecker interface.
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
func (iss *ACMEIssuer) PreCheck(ctx context.Context, names []string, interactive bool) error {
|
2022-07-06 08:12:25 +08:00
|
|
|
return iss.issuer.PreCheck(ctx, names, interactive)
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Issue obtains a certificate for the given csr.
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
func (iss *ACMEIssuer) Issue(ctx context.Context, csr *x509.CertificateRequest) (*certmagic.IssuedCertificate, error) {
|
2022-07-06 08:12:25 +08:00
|
|
|
return iss.issuer.Issue(ctx, csr)
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// IssuerKey returns the unique issuer key for the configured CA endpoint.
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
func (iss *ACMEIssuer) IssuerKey() string {
|
2022-07-06 08:12:25 +08:00
|
|
|
return iss.issuer.IssuerKey()
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Revoke revokes the given certificate.
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
func (iss *ACMEIssuer) Revoke(ctx context.Context, cert certmagic.CertificateResource, reason int) error {
|
2022-07-06 08:12:25 +08:00
|
|
|
return iss.issuer.Revoke(ctx, cert, reason)
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetACMEIssuer returns iss. This is useful when other types embed ACMEIssuer, because
|
|
|
|
// type-asserting them to *ACMEIssuer will fail, but type-asserting them to an interface
|
|
|
|
// with only this method will succeed, and will still allow the embedded ACMEIssuer
|
|
|
|
// to be accessed and manipulated.
|
|
|
|
func (iss *ACMEIssuer) GetACMEIssuer() *ACMEIssuer { return iss }
|
|
|
|
|
|
|
|
// UnmarshalCaddyfile deserializes Caddyfile tokens into iss.
|
|
|
|
//
|
2021-01-08 02:01:58 +08:00
|
|
|
// ... acme [<directory_url>] {
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
// dir <directory_url>
|
|
|
|
// test_dir <test_directory_url>
|
|
|
|
// email <email>
|
|
|
|
// timeout <duration>
|
|
|
|
// disable_http_challenge
|
|
|
|
// disable_tlsalpn_challenge
|
|
|
|
// alt_http_port <port>
|
|
|
|
// alt_tlsalpn_port <port>
|
|
|
|
// eab <key_id> <mac_key>
|
|
|
|
// trusted_roots <pem_files...>
|
2020-09-09 01:36:46 +08:00
|
|
|
// dns <provider_name> [<options>]
|
2022-04-23 06:09:11 +08:00
|
|
|
// propagation_delay <duration>
|
|
|
|
// propagation_timeout <duration>
|
2020-09-01 03:23:26 +08:00
|
|
|
// resolvers <dns_servers...>
|
2022-04-23 06:09:11 +08:00
|
|
|
// dns_challenge_override_domain <domain>
|
2021-06-09 04:10:37 +08:00
|
|
|
// preferred_chains [smallest] {
|
2022-04-23 06:09:11 +08:00
|
|
|
// root_common_name <common_names...>
|
|
|
|
// any_common_name <common_names...>
|
2021-06-09 04:10:37 +08:00
|
|
|
// }
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
// }
|
|
|
|
//
|
|
|
|
func (iss *ACMEIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
|
|
|
for d.Next() {
|
2021-01-08 02:01:58 +08:00
|
|
|
if d.NextArg() {
|
|
|
|
iss.CA = d.Val()
|
|
|
|
if d.NextArg() {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
}
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
for nesting := d.Nesting(); d.NextBlock(nesting); {
|
|
|
|
switch d.Val() {
|
|
|
|
case "dir":
|
2021-01-08 02:01:58 +08:00
|
|
|
if iss.CA != "" {
|
|
|
|
return d.Errf("directory is already specified: %s", iss.CA)
|
|
|
|
}
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
if !d.AllArgs(&iss.CA) {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
|
|
|
|
case "test_dir":
|
|
|
|
if !d.AllArgs(&iss.TestCA) {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
|
|
|
|
case "email":
|
|
|
|
if !d.AllArgs(&iss.Email) {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
|
|
|
|
case "timeout":
|
|
|
|
var timeoutStr string
|
|
|
|
if !d.AllArgs(&timeoutStr) {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
timeout, err := caddy.ParseDuration(timeoutStr)
|
|
|
|
if err != nil {
|
|
|
|
return d.Errf("invalid timeout duration %s: %v", timeoutStr, err)
|
|
|
|
}
|
|
|
|
iss.ACMETimeout = caddy.Duration(timeout)
|
|
|
|
|
|
|
|
case "disable_http_challenge":
|
|
|
|
if d.NextArg() {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
if iss.Challenges == nil {
|
|
|
|
iss.Challenges = new(ChallengesConfig)
|
|
|
|
}
|
|
|
|
if iss.Challenges.HTTP == nil {
|
|
|
|
iss.Challenges.HTTP = new(HTTPChallengeConfig)
|
|
|
|
}
|
|
|
|
iss.Challenges.HTTP.Disabled = true
|
|
|
|
|
|
|
|
case "disable_tlsalpn_challenge":
|
|
|
|
if d.NextArg() {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
if iss.Challenges == nil {
|
|
|
|
iss.Challenges = new(ChallengesConfig)
|
|
|
|
}
|
|
|
|
if iss.Challenges.TLSALPN == nil {
|
|
|
|
iss.Challenges.TLSALPN = new(TLSALPNChallengeConfig)
|
|
|
|
}
|
|
|
|
iss.Challenges.TLSALPN.Disabled = true
|
|
|
|
|
|
|
|
case "alt_http_port":
|
|
|
|
if !d.NextArg() {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
port, err := strconv.Atoi(d.Val())
|
|
|
|
if err != nil {
|
|
|
|
return d.Errf("invalid port %s: %v", d.Val(), err)
|
|
|
|
}
|
|
|
|
if iss.Challenges == nil {
|
|
|
|
iss.Challenges = new(ChallengesConfig)
|
|
|
|
}
|
|
|
|
if iss.Challenges.HTTP == nil {
|
|
|
|
iss.Challenges.HTTP = new(HTTPChallengeConfig)
|
|
|
|
}
|
|
|
|
iss.Challenges.HTTP.AlternatePort = port
|
|
|
|
|
|
|
|
case "alt_tlsalpn_port":
|
|
|
|
if !d.NextArg() {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
port, err := strconv.Atoi(d.Val())
|
|
|
|
if err != nil {
|
|
|
|
return d.Errf("invalid port %s: %v", d.Val(), err)
|
|
|
|
}
|
|
|
|
if iss.Challenges == nil {
|
|
|
|
iss.Challenges = new(ChallengesConfig)
|
|
|
|
}
|
|
|
|
if iss.Challenges.TLSALPN == nil {
|
|
|
|
iss.Challenges.TLSALPN = new(TLSALPNChallengeConfig)
|
|
|
|
}
|
|
|
|
iss.Challenges.TLSALPN.AlternatePort = port
|
|
|
|
|
|
|
|
case "eab":
|
|
|
|
iss.ExternalAccount = new(acme.EAB)
|
|
|
|
if !d.AllArgs(&iss.ExternalAccount.KeyID, &iss.ExternalAccount.MACKey) {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
|
|
|
|
case "trusted_roots":
|
|
|
|
iss.TrustedRootsPEMFiles = d.RemainingArgs()
|
|
|
|
|
2020-09-09 01:36:46 +08:00
|
|
|
case "dns":
|
|
|
|
if !d.NextArg() {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
provName := d.Val()
|
|
|
|
if iss.Challenges == nil {
|
|
|
|
iss.Challenges = new(ChallengesConfig)
|
|
|
|
}
|
|
|
|
if iss.Challenges.DNS == nil {
|
|
|
|
iss.Challenges.DNS = new(DNSChallengeConfig)
|
|
|
|
}
|
2021-01-06 05:39:30 +08:00
|
|
|
unm, err := caddyfile.UnmarshalModule(d, "dns.providers."+provName)
|
2020-09-09 01:36:46 +08:00
|
|
|
if err != nil {
|
2021-01-06 05:39:30 +08:00
|
|
|
return err
|
2020-09-09 01:36:46 +08:00
|
|
|
}
|
2021-01-06 05:39:30 +08:00
|
|
|
iss.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, nil)
|
2022-04-23 06:09:11 +08:00
|
|
|
|
|
|
|
case "propagation_delay":
|
|
|
|
if !d.NextArg() {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
delayStr := d.Val()
|
|
|
|
delay, err := caddy.ParseDuration(delayStr)
|
|
|
|
if err != nil {
|
|
|
|
return d.Errf("invalid propagation_delay duration %s: %v", delayStr, err)
|
|
|
|
}
|
|
|
|
if iss.Challenges == nil {
|
|
|
|
iss.Challenges = new(ChallengesConfig)
|
|
|
|
}
|
|
|
|
if iss.Challenges.DNS == nil {
|
|
|
|
iss.Challenges.DNS = new(DNSChallengeConfig)
|
|
|
|
}
|
|
|
|
iss.Challenges.DNS.PropagationDelay = caddy.Duration(delay)
|
|
|
|
|
2021-06-08 02:25:12 +08:00
|
|
|
case "propagation_timeout":
|
|
|
|
if !d.NextArg() {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
timeoutStr := d.Val()
|
2022-04-23 06:09:11 +08:00
|
|
|
var timeout time.Duration
|
|
|
|
if timeoutStr == "-1" {
|
|
|
|
timeout = time.Duration(-1)
|
|
|
|
} else {
|
|
|
|
var err error
|
|
|
|
timeout, err = caddy.ParseDuration(timeoutStr)
|
|
|
|
if err != nil {
|
|
|
|
return d.Errf("invalid propagation_timeout duration %s: %v", timeoutStr, err)
|
|
|
|
}
|
2021-06-08 02:25:12 +08:00
|
|
|
}
|
|
|
|
if iss.Challenges == nil {
|
|
|
|
iss.Challenges = new(ChallengesConfig)
|
|
|
|
}
|
|
|
|
if iss.Challenges.DNS == nil {
|
|
|
|
iss.Challenges.DNS = new(DNSChallengeConfig)
|
|
|
|
}
|
|
|
|
iss.Challenges.DNS.PropagationTimeout = caddy.Duration(timeout)
|
2020-09-09 01:36:46 +08:00
|
|
|
|
2020-09-01 03:23:26 +08:00
|
|
|
case "resolvers":
|
|
|
|
if iss.Challenges == nil {
|
|
|
|
iss.Challenges = new(ChallengesConfig)
|
|
|
|
}
|
|
|
|
if iss.Challenges.DNS == nil {
|
|
|
|
iss.Challenges.DNS = new(DNSChallengeConfig)
|
|
|
|
}
|
|
|
|
iss.Challenges.DNS.Resolvers = d.RemainingArgs()
|
2020-09-10 00:21:59 +08:00
|
|
|
if len(iss.Challenges.DNS.Resolvers) == 0 {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
2020-09-01 03:23:26 +08:00
|
|
|
|
2022-03-09 03:03:43 +08:00
|
|
|
case "dns_challenge_override_domain":
|
|
|
|
arg := d.RemainingArgs()
|
|
|
|
if len(arg) != 1 {
|
|
|
|
return d.ArgErr()
|
|
|
|
}
|
|
|
|
if iss.Challenges == nil {
|
|
|
|
iss.Challenges = new(ChallengesConfig)
|
|
|
|
}
|
|
|
|
if iss.Challenges.DNS == nil {
|
|
|
|
iss.Challenges.DNS = new(DNSChallengeConfig)
|
|
|
|
}
|
|
|
|
iss.Challenges.DNS.OverrideDomain = arg[0]
|
|
|
|
|
2021-06-09 04:10:37 +08:00
|
|
|
case "preferred_chains":
|
|
|
|
chainPref, err := ParseCaddyfilePreferredChainsOptions(d)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
iss.PreferredChains = chainPref
|
|
|
|
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
default:
|
|
|
|
return d.Errf("unrecognized ACME issuer property: %s", d.Val())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
2020-03-07 14:15:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// onDemandAskRequest makes a request to the ask URL
|
|
|
|
// to see if a certificate can be obtained for name.
|
|
|
|
// The certificate request should be denied if this
|
|
|
|
// returns an error.
|
|
|
|
func onDemandAskRequest(ask string, name string) error {
|
|
|
|
askURL, err := url.Parse(ask)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("parsing ask URL: %v", err)
|
|
|
|
}
|
|
|
|
qs := askURL.Query()
|
|
|
|
qs.Set("domain", name)
|
|
|
|
askURL.RawQuery = qs.Encode()
|
|
|
|
|
|
|
|
resp, err := onDemandAskClient.Get(askURL.String())
|
|
|
|
if err != nil {
|
2020-04-26 00:34:56 +08:00
|
|
|
return fmt.Errorf("error checking %v to determine if certificate for hostname '%s' should be allowed: %v",
|
2020-03-07 14:15:25 +08:00
|
|
|
ask, name, err)
|
|
|
|
}
|
|
|
|
resp.Body.Close()
|
|
|
|
|
|
|
|
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
|
|
|
return fmt.Errorf("certificate for hostname '%s' not allowed; non-2xx status code %d returned from %v",
|
|
|
|
name, resp.StatusCode, ask)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-06-09 04:10:37 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2020-12-16 03:16:04 +08:00
|
|
|
// ChainPreference describes the client's preferred certificate chain,
|
|
|
|
// useful if the CA offers alternate chains. The first matching chain
|
|
|
|
// will be selected.
|
|
|
|
type ChainPreference struct {
|
|
|
|
// Prefer chains with the fewest number of bytes.
|
|
|
|
Smallest *bool `json:"smallest,omitempty"`
|
|
|
|
|
|
|
|
// Select first chain having a root with one of
|
|
|
|
// these common names.
|
|
|
|
RootCommonName []string `json:"root_common_name,omitempty"`
|
|
|
|
|
|
|
|
// Select first chain that has any issuer with one
|
|
|
|
// of these common names.
|
|
|
|
AnyCommonName []string `json:"any_common_name,omitempty"`
|
|
|
|
}
|
|
|
|
|
2020-03-07 14:15:25 +08:00
|
|
|
// Interface guards
|
|
|
|
var (
|
caddytls: Add support for ZeroSSL; add Caddyfile support for issuers (#3633)
* caddytls: Add support for ZeroSSL; add Caddyfile support for issuers
Configuring issuers explicitly in a Caddyfile is not easily compatible
with existing ACME-specific parameters such as email or acme_ca which
infer the kind of issuer it creates (this is complicated now because
the ZeroSSL issuer wraps the ACME issuer)... oh well, we can revisit
that later if we need to.
New Caddyfile global option:
{
cert_issuer <name> ...
}
Or, alternatively, as a tls subdirective:
tls {
issuer <name> ...
}
For example, to use ZeroSSL with an API key:
{
cert_issuser zerossl API_KEY
}
For now, that still uses ZeroSSL's ACME endpoint; it fetches EAB
credentials for you. You can also provide the EAB credentials directly
just like any other ACME endpoint:
{
cert_issuer acme {
eab KEY_ID MAC_KEY
}
}
All these examples use the new global option (or tls subdirective). You
can still use traditional/existing options with ZeroSSL, since it's
just another ACME endpoint:
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab KEY_ID MAC_KEY
}
That's all there is to it. You just can't mix-and-match acme_* options
with cert_issuer, because it becomes confusing/ambiguous/complicated to
merge the settings.
* Fix broken test
This test was asserting buggy behavior, oops - glad this branch both
discovers and fixes the bug at the same time!
* Fix broken test (post-merge)
* Update modules/caddytls/acmeissuer.go
Fix godoc comment
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
* Add support for ZeroSSL's EAB-by-email endpoint
Also transform the ACMEIssuer into ZeroSSLIssuer implicitly if set to
the ZeroSSL endpoint without EAB (the ZeroSSLIssuer is needed to
generate EAB if not already provided); this is now possible with either
an API key or an email address.
* go.mod: Use latest certmagic, acmez, and x/net
* Wrap underlying logic rather than repeating it
Oops, duh
* Form-encode email info into request body for EAB endpoint
Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2020-08-11 22:58:06 +08:00
|
|
|
_ certmagic.PreChecker = (*ACMEIssuer)(nil)
|
|
|
|
_ certmagic.Issuer = (*ACMEIssuer)(nil)
|
|
|
|
_ certmagic.Revoker = (*ACMEIssuer)(nil)
|
|
|
|
_ caddy.Provisioner = (*ACMEIssuer)(nil)
|
|
|
|
_ ConfigSetter = (*ACMEIssuer)(nil)
|
|
|
|
_ caddyfile.Unmarshaler = (*ACMEIssuer)(nil)
|
2020-03-07 14:15:25 +08:00
|
|
|
)
|