summaryrefslogtreecommitdiff
path: root/modules/caddytls/acmemanager.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/caddytls/acmemanager.go')
-rw-r--r--modules/caddytls/acmemanager.go252
1 files changed, 0 insertions, 252 deletions
diff --git a/modules/caddytls/acmemanager.go b/modules/caddytls/acmemanager.go
deleted file mode 100644
index df73545..0000000
--- a/modules/caddytls/acmemanager.go
+++ /dev/null
@@ -1,252 +0,0 @@
-// 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 (
- "crypto/x509"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/url"
- "time"
-
- "github.com/caddyserver/caddy/v2"
- "github.com/go-acme/lego/v3/challenge"
- "github.com/mholt/certmagic"
-)
-
-func init() {
- caddy.RegisterModule(ACMEManagerMaker{})
-}
-
-// ACMEManagerMaker makes an ACME manager
-// for managing certificates using ACME.
-// If crafting one manually rather than
-// through the config-unmarshal process
-// (provisioning), be sure to call
-// SetDefaults to ensure sane defaults
-// after you have configured this struct
-// to your liking.
-type ACMEManagerMaker struct {
- // The URL to the CA's ACME directory endpoint.
- CA string `json:"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"`
-
- // How long before a certificate's expiration to try renewing it.
- // Should usually be about 1/3 of certificate lifetime, but long
- // enough to give yourself time to troubleshoot problems before
- // expiration. Default: 30d
- RenewAhead caddy.Duration `json:"renew_ahead,omitempty"`
-
- // The type of key to generate for the certificate.
- // Supported values: `rsa2048`, `rsa4096`, `p256`, `p384`.
- KeyType string `json:"key_type,omitempty"`
-
- // Time to wait before timing out an ACME operation.
- ACMETimeout caddy.Duration `json:"acme_timeout,omitempty"`
-
- // If true, certificates will be requested with MustStaple. Not all
- // CAs support this, and there are potentially serious consequences
- // of enabling this feature without proper threat modeling.
- MustStaple bool `json:"must_staple,omitempty"`
-
- // Configures the various ACME challenge types.
- Challenges *ChallengesConfig `json:"challenges,omitempty"`
-
- // If true, certificates will be managed "on demand", that is, during
- // TLS handshakes or when needed, as opposed to at startup or config
- // load.
- OnDemand bool `json:"on_demand,omitempty"`
-
- // Optionally configure a separate storage module associated with this
- // manager, instead of using Caddy's global/default-configured storage.
- Storage json.RawMessage `json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"`
-
- // 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"`
-
- storage certmagic.Storage
- rootPool *x509.CertPool
-}
-
-// CaddyModule returns the Caddy module information.
-func (ACMEManagerMaker) CaddyModule() caddy.ModuleInfo {
- return caddy.ModuleInfo{
- ID: "tls.management.acme",
- New: func() caddy.Module { return new(ACMEManagerMaker) },
- }
-}
-
-// NewManager is a no-op to satisfy the ManagerMaker interface,
-// because this manager type is a special case.
-func (m ACMEManagerMaker) NewManager(interactive bool) (certmagic.Manager, error) {
- return nil, nil
-}
-
-// Provision sets up m.
-func (m *ACMEManagerMaker) Provision(ctx caddy.Context) error {
- // DNS providers
- if m.Challenges != nil && m.Challenges.DNSRaw != nil {
- val, err := ctx.LoadModule(m.Challenges, "DNSRaw")
- if err != nil {
- return fmt.Errorf("loading DNS provider module: %v", err)
- }
- prov, err := val.(DNSProviderMaker).NewDNSProvider()
- if err != nil {
- return fmt.Errorf("making DNS provider: %v", err)
- }
- m.Challenges.DNS = prov
- }
-
- // policy-specific storage implementation
- if m.Storage != nil {
- val, err := ctx.LoadModule(m, "Storage")
- if err != nil {
- return fmt.Errorf("loading TLS storage module: %v", err)
- }
- cmStorage, err := val.(caddy.StorageConverter).CertMagicStorage()
- if err != nil {
- return fmt.Errorf("creating TLS storage configuration: %v", err)
- }
- m.storage = cmStorage
- }
-
- // add any custom CAs to trust store
- if len(m.TrustedRootsPEMFiles) > 0 {
- m.rootPool = x509.NewCertPool()
- for _, pemFile := range m.TrustedRootsPEMFiles {
- pemData, err := ioutil.ReadFile(pemFile)
- if err != nil {
- return fmt.Errorf("loading trusted root CA's PEM file: %s: %v", pemFile, err)
- }
- if !m.rootPool.AppendCertsFromPEM(pemData) {
- return fmt.Errorf("unable to add %s to trust pool: %v", pemFile, err)
- }
- }
- }
-
- return nil
-}
-
-// makeCertMagicConfig converts m into a certmagic.Config, because
-// this is a special case where the default manager is the certmagic
-// Config and not a separate manager.
-func (m *ACMEManagerMaker) makeCertMagicConfig(ctx caddy.Context) certmagic.Config {
- storage := m.storage
- if storage == nil {
- storage = ctx.Storage()
- }
-
- var ond *certmagic.OnDemandConfig
- if m.OnDemand {
- var onDemand *OnDemandConfig
- appVal, err := ctx.App("tls")
- if err == nil && appVal.(*TLS).Automation != nil {
- onDemand = appVal.(*TLS).Automation.OnDemand
- }
-
- ond = &certmagic.OnDemandConfig{
- DecisionFunc: func(name string) error {
- if onDemand != nil {
- if onDemand.Ask != "" {
- err := onDemandAskRequest(onDemand.Ask, name)
- if err != nil {
- return err
- }
- }
- // check the rate limiter last because
- // doing so makes a reservation
- if !onDemandRateLimiter.Allow() {
- return fmt.Errorf("on-demand rate limit exceeded")
- }
- }
- return nil
- },
- }
- }
-
- cfg := certmagic.Config{
- CA: m.CA,
- Email: m.Email,
- Agreed: true,
- RenewDurationBefore: time.Duration(m.RenewAhead),
- KeyType: supportedCertKeyTypes[m.KeyType],
- CertObtainTimeout: time.Duration(m.ACMETimeout),
- OnDemand: ond,
- MustStaple: m.MustStaple,
- Storage: storage,
- TrustedRoots: m.rootPool,
- // TODO: listenHost
- }
-
- if m.Challenges != nil {
- if m.Challenges.HTTP != nil {
- cfg.DisableHTTPChallenge = m.Challenges.HTTP.Disabled
- cfg.AltHTTPPort = m.Challenges.HTTP.AlternatePort
- }
- if m.Challenges.TLSALPN != nil {
- cfg.DisableTLSALPNChallenge = m.Challenges.TLSALPN.Disabled
- cfg.AltTLSALPNPort = m.Challenges.TLSALPN.AlternatePort
- }
- cfg.DNSProvider = m.Challenges.DNS
- }
-
- return cfg
-}
-
-// 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 {
- return fmt.Errorf("error checking %v to deterine if certificate for hostname '%s' should be allowed: %v",
- 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
-}
-
-// DNSProviderMaker is a type that can create a new DNS provider.
-// Modules in the tls.dns namespace should implement this interface.
-type DNSProviderMaker interface {
- NewDNSProvider() (challenge.Provider, error)
-}
-
-// Interface guard
-var _ ManagerMaker = (*ACMEManagerMaker)(nil)