mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
Merge branch 'master' into log-request-body
This commit is contained in:
commit
8e8e2f596d
6 changed files with 90 additions and 4 deletions
23
caddy.go
23
caddy.go
|
@ -50,6 +50,14 @@ var (
|
||||||
// was started as part of an upgrade, where a parent
|
// was started as part of an upgrade, where a parent
|
||||||
// Caddy process started this one.
|
// Caddy process started this one.
|
||||||
isUpgrade bool
|
isUpgrade bool
|
||||||
|
|
||||||
|
// started will be set to true when the first
|
||||||
|
// instance is started; it never gets set to
|
||||||
|
// false after that.
|
||||||
|
started bool
|
||||||
|
|
||||||
|
// mu protects the variables 'isUpgrade' and 'started'.
|
||||||
|
mu sync.Mutex
|
||||||
)
|
)
|
||||||
|
|
||||||
// Instance contains the state of servers created as a result of
|
// Instance contains the state of servers created as a result of
|
||||||
|
@ -497,6 +505,10 @@ func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string]r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mu.Lock()
|
||||||
|
started = true
|
||||||
|
mu.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,9 +749,20 @@ func Upgrade() error {
|
||||||
// where a parent caddy process spawned this one to ugprade
|
// where a parent caddy process spawned this one to ugprade
|
||||||
// the binary.
|
// the binary.
|
||||||
func IsUpgrade() bool {
|
func IsUpgrade() bool {
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
return isUpgrade
|
return isUpgrade
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Started returns true if at least one instance has been
|
||||||
|
// started by this package. It never gets reset to false
|
||||||
|
// once it is set to true.
|
||||||
|
func Started() bool {
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
return started
|
||||||
|
}
|
||||||
|
|
||||||
// CaddyfileInput represents a Caddyfile as input
|
// CaddyfileInput represents a Caddyfile as input
|
||||||
// and is simply a convenient way to implement
|
// and is simply a convenient way to implement
|
||||||
// the Input interface.
|
// the Input interface.
|
||||||
|
|
|
@ -10,7 +10,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func activateHTTPS(cctx caddy.Context) error {
|
func activateHTTPS(cctx caddy.Context) error {
|
||||||
if !caddy.Quiet {
|
operatorPresent := !caddy.Started()
|
||||||
|
|
||||||
|
if !caddy.Quiet && operatorPresent {
|
||||||
fmt.Print("Activating privacy features...")
|
fmt.Print("Activating privacy features...")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +23,7 @@ func activateHTTPS(cctx caddy.Context) error {
|
||||||
|
|
||||||
// place certificates and keys on disk
|
// place certificates and keys on disk
|
||||||
for _, c := range ctx.siteConfigs {
|
for _, c := range ctx.siteConfigs {
|
||||||
err := c.TLS.ObtainCert(true)
|
err := c.TLS.ObtainCert(operatorPresent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -44,9 +46,10 @@ func activateHTTPS(cctx caddy.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !caddy.Quiet {
|
if !caddy.Quiet && operatorPresent {
|
||||||
fmt.Println(" done.")
|
fmt.Println(" done.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,9 +144,11 @@ var newACMEClient = func(config *Config, allowPrompts bool) (*ACMEClient, error)
|
||||||
func (c *ACMEClient) Obtain(names []string) error {
|
func (c *ACMEClient) Obtain(names []string) error {
|
||||||
Attempts:
|
Attempts:
|
||||||
for attempts := 0; attempts < 2; attempts++ {
|
for attempts := 0; attempts < 2; attempts++ {
|
||||||
|
namesObtaining.Add(names)
|
||||||
acmeMu.Lock()
|
acmeMu.Lock()
|
||||||
certificate, failures := c.ObtainCertificate(names, true, nil)
|
certificate, failures := c.ObtainCertificate(names, true, nil)
|
||||||
acmeMu.Unlock()
|
acmeMu.Unlock()
|
||||||
|
namesObtaining.Remove(names)
|
||||||
if len(failures) > 0 {
|
if len(failures) > 0 {
|
||||||
// Error - try to fix it or report it to the user and abort
|
// Error - try to fix it or report it to the user and abort
|
||||||
var errMsg string // we'll combine all the failures into a single error message
|
var errMsg string // we'll combine all the failures into a single error message
|
||||||
|
@ -234,9 +236,11 @@ func (c *ACMEClient) Renew(name string) error {
|
||||||
var newCertMeta acme.CertificateResource
|
var newCertMeta acme.CertificateResource
|
||||||
var success bool
|
var success bool
|
||||||
for attempts := 0; attempts < 2; attempts++ {
|
for attempts := 0; attempts < 2; attempts++ {
|
||||||
|
namesObtaining.Add([]string{name})
|
||||||
acmeMu.Lock()
|
acmeMu.Lock()
|
||||||
newCertMeta, err = c.RenewCertificate(certMeta, true)
|
newCertMeta, err = c.RenewCertificate(certMeta, true)
|
||||||
acmeMu.Unlock()
|
acmeMu.Unlock()
|
||||||
|
namesObtaining.Remove([]string{name})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
success = true
|
success = true
|
||||||
break
|
break
|
||||||
|
@ -294,3 +298,47 @@ func (c *ACMEClient) Revoke(name string) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// namesObtaining is a set of hostnames with thread-safe
|
||||||
|
// methods. A name should be in this set only while this
|
||||||
|
// package is in the process of obtaining a certificate
|
||||||
|
// for the name. ACME challenges that are received for
|
||||||
|
// names which are not in this set were not initiated by
|
||||||
|
// this package and probably should not be handled by
|
||||||
|
// this package.
|
||||||
|
var namesObtaining = nameCoordinator{names: make(map[string]struct{})}
|
||||||
|
|
||||||
|
type nameCoordinator struct {
|
||||||
|
names map[string]struct{}
|
||||||
|
mu sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds names to c. It is safe for concurrent use.
|
||||||
|
func (c *nameCoordinator) Add(names []string) {
|
||||||
|
c.mu.Lock()
|
||||||
|
for _, name := range names {
|
||||||
|
c.names[strings.ToLower(name)] = struct{}{}
|
||||||
|
}
|
||||||
|
c.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes names from c. It is safe for concurrent use.
|
||||||
|
func (c *nameCoordinator) Remove(names []string) {
|
||||||
|
c.mu.Lock()
|
||||||
|
for _, name := range names {
|
||||||
|
delete(c.names, strings.ToLower(name))
|
||||||
|
}
|
||||||
|
c.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has returns true if c has name. It is safe for concurrent use.
|
||||||
|
func (c *nameCoordinator) Has(name string) bool {
|
||||||
|
hostname, _, err := net.SplitHostPort(name)
|
||||||
|
if err != nil {
|
||||||
|
hostname = name
|
||||||
|
}
|
||||||
|
c.mu.RLock()
|
||||||
|
_, ok := c.names[strings.ToLower(hostname)]
|
||||||
|
c.mu.RUnlock()
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
|
@ -214,9 +214,11 @@ func (c *Config) renewCertName(name string, allowPrompts bool) error {
|
||||||
var newCertMeta acme.CertificateResource
|
var newCertMeta acme.CertificateResource
|
||||||
var success bool
|
var success bool
|
||||||
for attempts := 0; attempts < 2; attempts++ {
|
for attempts := 0; attempts < 2; attempts++ {
|
||||||
|
namesObtaining.Add([]string{name})
|
||||||
acmeMu.Lock()
|
acmeMu.Lock()
|
||||||
newCertMeta, err = client.RenewCertificate(certMeta, true)
|
newCertMeta, err = client.RenewCertificate(certMeta, true)
|
||||||
acmeMu.Unlock()
|
acmeMu.Unlock()
|
||||||
|
namesObtaining.Remove([]string{name})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
success = true
|
success = true
|
||||||
break
|
break
|
||||||
|
|
|
@ -19,6 +19,9 @@ func HTTPChallengeHandler(w http.ResponseWriter, r *http.Request, altPort string
|
||||||
if !strings.HasPrefix(r.URL.Path, challengeBasePath) {
|
if !strings.HasPrefix(r.URL.Path, challengeBasePath) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if !namesObtaining.Has(r.Host) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
scheme := "http"
|
scheme := "http"
|
||||||
if r.TLS != nil {
|
if r.TLS != nil {
|
||||||
|
|
|
@ -8,13 +8,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHTTPChallengeHandlerNoOp(t *testing.T) {
|
func TestHTTPChallengeHandlerNoOp(t *testing.T) {
|
||||||
// try base paths that aren't handled by this handler
|
namesObtaining.Add([]string{"localhost"})
|
||||||
|
|
||||||
|
// try base paths and host names that aren't
|
||||||
|
// handled by this handler
|
||||||
for _, url := range []string{
|
for _, url := range []string{
|
||||||
"http://localhost/",
|
"http://localhost/",
|
||||||
"http://localhost/foo.html",
|
"http://localhost/foo.html",
|
||||||
"http://localhost/.git",
|
"http://localhost/.git",
|
||||||
"http://localhost/.well-known/",
|
"http://localhost/.well-known/",
|
||||||
"http://localhost/.well-known/acme-challenging",
|
"http://localhost/.well-known/acme-challenging",
|
||||||
|
"http://other/.well-known/acme-challenge/foo",
|
||||||
} {
|
} {
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -46,6 +50,9 @@ func TestHTTPChallengeHandlerSuccess(t *testing.T) {
|
||||||
}
|
}
|
||||||
ts.Listener = ln
|
ts.Listener = ln
|
||||||
|
|
||||||
|
// Tell this package that we are handling a challenge for 127.0.0.1
|
||||||
|
namesObtaining.Add([]string{"127.0.0.1"})
|
||||||
|
|
||||||
// Start our engines and run the test
|
// Start our engines and run the test
|
||||||
ts.Start()
|
ts.Start()
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
Loading…
Reference in a new issue