@marcel91200 / caddy Mirror · read-only / commits / 43961b54
Fork 0

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

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

Synced Nov 14, 05:15 UTC

General cleanup and more godocs

Matthew Holt committed Apr 26, 2019 at 12:35 UTC 43961b542b077f99f78d64629348b9300d3cd4a3
5 files changed +129 -86
modules.go
+34 -5
@@ -11,15 +11,44 @@ import (
11
12 // Module represents a Caddy module.
13 type Module struct {
14 - Name string
15 - New func() (interface{}, error)
16 - OnLoad func(instances []interface{}, priorState interface{}) (newState interface{}, err error)
14 + // Name is the full name of the module. It
15 + // must be unique and properly namespaced.
16 + Name string
17 +
18 + // New returns a new, empty instance of
19 + // the module's type. The host module
20 + // which loads this module will likely
21 + // invoke methods on the returned value.
22 + // It must return a pointer; if not, it
23 + // is converted into one.
24 + New func() (interface{}, error)
25 +
26 + // OnLoad is invoked after all module
27 + // instances ave been loaded. It receives
28 + // pointers to each instance of this
29 + // module, and any state from a previous
30 + // running configuration, which may be
31 + // nil.
32 + //
33 + // If this module is to carry "global"
34 + // state between all instances through
35 + // reloads, you might find it helpful
36 + // to return it.
37 + // TODO: Is this really better/safer than a global variable?
38 + OnLoad func(instances []interface{}, priorState interface{}) (newState interface{}, err error)
39 +
40 + // OnUnload is called after all module
41 + // instances have been stopped, possibly
42 + // in favor of a new configuration. It
43 + // receives the state given by OnLoad (if
44 + // any).
45 OnUnload func(state interface{}) error
46 }
47
48 func (m Module) String() string { return m.Name }
49
22 -// RegisterModule registers a module.
50 +// RegisterModule registers a module. Modules must call
51 +// this function in the init phase of runtime.
52 func RegisterModule(mod Module) error {
53 if mod.Name == "caddy" {
54 return fmt.Errorf("modules cannot be named 'caddy'")
@@ -35,7 +64,7 @@ func RegisterModule(mod Module) error {
64 return nil
65 }
66
38 -// GetModule returns a module by name.
67 +// GetModule returns a module by its full name.
68 func GetModule(name string) (Module, error) {
69 modulesMu.Lock()
70 defer modulesMu.Unlock()
modules/caddytls/acmemanager.go
+66 -15
@@ -3,6 +3,7 @@ package caddytls
3 import (
4 "encoding/json"
5 "fmt"
6 + "time"
7
8 "github.com/go-acme/lego/certcrypto"
9
@@ -18,11 +19,6 @@ func init() {
19 })
20 }
21
21 -// ManagerMaker TODO: WIP...
22 -type ManagerMaker interface {
23 - newManager(interactive bool) (certmagic.Manager, error)
24 -}
25 -
22 // acmeManagerMaker makes an ACME manager
23 // for managinig certificates using ACME.
24 type acmeManagerMaker struct {
@@ -40,9 +36,11 @@ type acmeManagerMaker struct {
36 keyType certcrypto.KeyType
37 }
38
43 -func (m *acmeManagerMaker) Provision() error {
44 - m.setDefaults()
39 +func (m *acmeManagerMaker) newManager(interactive bool) (certmagic.Manager, error) {
40 + return nil, nil
41 +}
42
43 +func (m *acmeManagerMaker) Provision() error {
44 // DNS providers
45 if m.Challenges.DNS != nil {
46 val, err := caddy2.LoadModuleInline("provider", "tls.dns", m.Challenges.DNS)
@@ -67,18 +65,71 @@ func (m *acmeManagerMaker) Provision() error {
65 m.Storage = nil // allow GC to deallocate - TODO: Does this help?
66 }
67
68 + m.setDefaults()
69 +
70 return nil
71 }
72
73 -// setDefaults indiscriminately sets all the default values in m.
73 +// setDefaults sets necessary values that are
74 +// currently empty to their default values.
75 func (m *acmeManagerMaker) setDefaults() {
75 - m.CA = certmagic.LetsEncryptStagingCA // certmagic.Default.CA // TODO: When not testing, switch to production CA
76 - m.Email = certmagic.Default.Email
77 - m.RenewAhead = caddy2.Duration(certmagic.Default.RenewDurationBefore)
78 - m.keyType = certmagic.Default.KeyType
79 - m.storage = certmagic.Default.Storage
76 + if m.CA == "" {
77 + m.CA = certmagic.LetsEncryptStagingCA // certmagic.Default.CA // TODO: When not testing, switch to production CA
78 + }
79 + if m.Email == "" {
80 + m.Email = certmagic.Default.Email
81 + }
82 + if m.RenewAhead == 0 {
83 + m.RenewAhead = caddy2.Duration(certmagic.Default.RenewDurationBefore)
84 + }
85 + if m.keyType == "" {
86 + m.keyType = certmagic.Default.KeyType
87 + }
88 + if m.storage == nil {
89 + m.storage = certmagic.Default.Storage
90 + }
91 }
92
82 -func (m *acmeManagerMaker) newManager(interactive bool) (certmagic.Manager, error) {
83 - return nil, nil
93 +// makeCertMagicConfig converts m into a certmagic.Config, because
94 +// this is a special case where the default manager is the certmagic
95 +// Config and not a separate manager.
96 +func (m *acmeManagerMaker) makeCertMagicConfig() certmagic.Config {
97 + storage := m.storage
98 + if storage == nil {
99 + storage = caddy2.GetStorage()
100 + }
101 +
102 + var ond *certmagic.OnDemandConfig
103 + if m.OnDemand != nil {
104 + ond = &certmagic.OnDemandConfig{
105 + // TODO: fill this out
106 + }
107 + }
108 +
109 + return certmagic.Config{
110 + CA: certmagic.LetsEncryptStagingCA, //ap.CA, // TODO: Restore true value
111 + Email: m.Email,
112 + Agreed: true,
113 + DisableHTTPChallenge: m.Challenges.HTTP.Disabled,
114 + DisableTLSALPNChallenge: m.Challenges.TLSALPN.Disabled,
115 + RenewDurationBefore: time.Duration(m.RenewAhead),
116 + AltHTTPPort: m.Challenges.HTTP.AlternatePort,
117 + AltTLSALPNPort: m.Challenges.TLSALPN.AlternatePort,
118 + DNSProvider: m.Challenges.dns,
119 + KeyType: supportedCertKeyTypes[m.KeyType],
120 + CertObtainTimeout: time.Duration(m.ACMETimeout),
121 + OnDemand: ond,
122 + MustStaple: m.MustStaple,
123 + Storage: storage,
124 + // TODO: listenHost
125 + }
126 +}
127 +
128 +// supportedCertKeyTypes is all the key types that are supported
129 +// for certificates that are obtained through ACME.
130 +var supportedCertKeyTypes = map[string]certcrypto.KeyType{
131 + "RSA2048": certcrypto.RSA2048,
132 + "RSA4096": certcrypto.RSA4096,
133 + "P256": certcrypto.EC256,
134 + "P384": certcrypto.EC384,
135 }
modules/caddytls/matchers.go
+17 -3
@@ -7,13 +7,22 @@ import (
7 )
8
9 type (
10 + // MatchServerName matches based on SNI.
11 MatchServerName []string
12
13 // TODO: these others should be enterprise-only, probably
13 - MatchProtocol []string // TODO: version or protocol?
14 +
15 + // MatchProtocol matches based on protocol.
16 + MatchProtocol []string // TODO: Protocol or version?
17 +
18 + // MatchClientCert matches based on client certificate / client auth?
19 MatchClientCert struct{} // TODO: client certificate options
15 - MatchRemote []string
16 - MatchStarlark string
20 +
21 + // MatchRemote matches based on the remote address of the connection.
22 + MatchRemote []string
23 +
24 + // MatchStarlark matches based on a Starlark script.
25 + MatchStarlark string
26 )
27
28 func init() {
@@ -39,6 +48,7 @@ func init() {
48 })
49 }
50
51 +// Match matches hello based on SNI.
52 func (m MatchServerName) Match(hello *tls.ClientHelloInfo) bool {
53 for _, name := range m {
54 // TODO: support wildcards (and regex?)
@@ -49,21 +59,25 @@ func (m MatchServerName) Match(hello *tls.ClientHelloInfo) bool {
59 return false
60 }
61
62 +// Match matches hello based on protocol version.
63 func (m MatchProtocol) Match(hello *tls.ClientHelloInfo) bool {
64 // TODO: not implemented
65 return false
66 }
67
68 +// Match matches hello based on client certificate.
69 func (m MatchClientCert) Match(hello *tls.ClientHelloInfo) bool {
70 // TODO: not implemented
71 return false
72 }
73
74 +// Match matches hello based on remote address.
75 func (m MatchRemote) Match(hello *tls.ClientHelloInfo) bool {
76 // TODO: not implemented
77 return false
78 }
79
80 +// Match matches hello based on a Starlark script.
81 func (m MatchStarlark) Match(hello *tls.ClientHelloInfo) bool {
82 // TODO: not implemented
83 return false
modules/caddytls/tls.go
+8 -51
@@ -5,10 +5,8 @@ import (
5 "encoding/json"
6 "fmt"
7 "net/http"
8 - "time"
8
9 "bitbucket.org/lightcodelabs/caddy2"
11 - "github.com/go-acme/lego/certcrypto"
10 "github.com/go-acme/lego/challenge"
11 "github.com/klauspost/cpuid"
12 "github.com/mholt/certmagic"
@@ -30,8 +28,7 @@ type TLS struct {
28 certCache *certmagic.Cache
29 }
30
33 -// TODO: Finish stubbing out this two-phase setup process: prepare, then start...
34 -
31 +// Provision sets up the configuration for the TLS app.
32 func (t *TLS) Provision() error {
33 // set up the certificate cache
34 // TODO: this makes a new cache every time; better to only make a new
@@ -97,15 +94,6 @@ func (t *TLS) Start(handle caddy2.Handle) error {
94 if err != nil {
95 return fmt.Errorf("automate: managing %v: %v", names, err)
96 }
100 - // for _, name := range names {
101 - // t.Manage([]string{name)
102 - // ap := t.getAutomationPolicyForName(name)
103 - // magic := certmagic.New(t.certCache, ap.makeCertMagicConfig())
104 - // err := magic.Manage([]string{name})
105 - // if err != nil {
106 - // return fmt.Errorf("automate: manage %s: %v", name, err)
107 - // }
108 - // }
97 }
98 t.Certificates = nil // allow GC to deallocate - TODO: Does this help?
99
@@ -191,38 +179,11 @@ type AutomationPolicy struct {
179 }
180
181 func (ap AutomationPolicy) makeCertMagicConfig() certmagic.Config {
182 + // default manager (ACME) is a special case because of how CertMagic is designed
183 + // TODO: refactor certmagic so that ACME manager is not a special case by extracting
184 + // its config fields out of the certmagic.Config struct, or something...
185 if acmeMgmt, ok := ap.management.(*acmeManagerMaker); ok {
195 - // default, which is management via ACME
196 -
197 - storage := acmeMgmt.storage
198 - if storage == nil {
199 - storage = caddy2.GetStorage()
200 - }
201 -
202 - var ond *certmagic.OnDemandConfig
203 - if acmeMgmt.OnDemand != nil {
204 - ond = &certmagic.OnDemandConfig{
205 - // TODO: fill this out
206 - }
207 - }
208 -
209 - return certmagic.Config{
210 - CA: certmagic.LetsEncryptStagingCA, //ap.CA, // TODO: Restore true value
211 - Email: acmeMgmt.Email,
212 - Agreed: true,
213 - DisableHTTPChallenge: acmeMgmt.Challenges.HTTP.Disabled,
214 - DisableTLSALPNChallenge: acmeMgmt.Challenges.TLSALPN.Disabled,
215 - RenewDurationBefore: time.Duration(acmeMgmt.RenewAhead),
216 - AltHTTPPort: acmeMgmt.Challenges.HTTP.AlternatePort,
217 - AltTLSALPNPort: acmeMgmt.Challenges.TLSALPN.AlternatePort,
218 - DNSProvider: acmeMgmt.Challenges.dns,
219 - KeyType: supportedCertKeyTypes[acmeMgmt.KeyType],
220 - CertObtainTimeout: time.Duration(acmeMgmt.ACMETimeout),
221 - OnDemand: ond,
222 - MustStaple: acmeMgmt.MustStaple,
223 - Storage: storage,
224 - // TODO: listenHost
225 - }
186 + return acmeMgmt.makeCertMagicConfig()
187 }
188
189 return certmagic.Config{
@@ -260,13 +221,9 @@ type OnDemandConfig struct {
221 AskStarlark string `json:"ask_starlark,omitempty"`
222 }
223
263 -// supportedCertKeyTypes is all the key types that are supported
264 -// for certificates that are obtained through ACME.
265 -var supportedCertKeyTypes = map[string]certcrypto.KeyType{
266 - "RSA2048": certcrypto.RSA2048,
267 - "RSA4096": certcrypto.RSA4096,
268 - "P256": certcrypto.EC256,
269 - "P384": certcrypto.EC384,
224 +// ManagerMaker makes a certificate manager.
225 +type ManagerMaker interface {
226 + newManager(interactive bool) (certmagic.Manager, error)
227 }
228
229 // supportedCipherSuites is the unordered map of cipher suite
storage.go
+4 -12
@@ -16,22 +16,14 @@ func init() {
16 }
17
18 // StorageConverter is a type that can convert itself
19 -// to a valid, usable certmagic.Storage value. The
20 -// value might be short-lived.
19 +// to a valid, usable certmagic.Storage value. (The
20 +// value might be short-lived.) This interface allows
21 +// us to adapt any CertMagic storage implementation
22 +// into a consistent API for Caddy configuration.
23 type StorageConverter interface {
24 CertMagicStorage() (certmagic.Storage, error)
25 }
26
25 -// TODO: Wrappers other than file_system should be enterprise-only.
26 -
27 -// It may seem trivial to wrap these, but the benefits are:
28 -// 1. We don't need to change the actual CertMagic storage implementions
29 -// to a structure that is operable with Caddy's config (including JSON
30 -// tags), and
31 -// 2. We don't need to rely on rely on maintainers of third-party
32 -// certmagic.Storage implementations. We can make any certmagic.Storage
33 -// work with Caddy this way.
34 -
27 // fileStorage is a certmagic.Storage wrapper for certmagic.FileStorage.
28 type fileStorage struct {
29 Root string `json:"root"`