mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-03 19:17:29 -05:00 
			
		
		
		
	
		
			Some checks are pending
		
		
	
	Tests / test (./cmd/caddy/caddy, ~1.22.3, macos-14, 0, 1.22, mac) (push) Waiting to run
				
			Tests / test (./cmd/caddy/caddy, ~1.22.3, ubuntu-latest, 0, 1.22, linux) (push) Waiting to run
				
			Tests / test (./cmd/caddy/caddy, ~1.23.0, macos-14, 0, 1.23, mac) (push) Waiting to run
				
			Tests / test (./cmd/caddy/caddy, ~1.23.0, ubuntu-latest, 0, 1.23, linux) (push) Waiting to run
				
			Tests / test (./cmd/caddy/caddy.exe, ~1.22.3, windows-latest, True, 1.22, windows) (push) Waiting to run
				
			Tests / test (./cmd/caddy/caddy.exe, ~1.23.0, windows-latest, True, 1.23, windows) (push) Waiting to run
				
			Tests / test (s390x on IBM Z) (push) Waiting to run
				
			Tests / goreleaser-check (push) Waiting to run
				
			Cross-Build / build (~1.22.3, 1.22, aix) (push) Waiting to run
				
			Cross-Build / build (~1.22.3, 1.22, darwin) (push) Waiting to run
				
			Cross-Build / build (~1.22.3, 1.22, dragonfly) (push) Waiting to run
				
			Cross-Build / build (~1.22.3, 1.22, freebsd) (push) Waiting to run
				
			Cross-Build / build (~1.22.3, 1.22, illumos) (push) Waiting to run
				
			Cross-Build / build (~1.22.3, 1.22, linux) (push) Waiting to run
				
			Cross-Build / build (~1.22.3, 1.22, netbsd) (push) Waiting to run
				
			Cross-Build / build (~1.22.3, 1.22, openbsd) (push) Waiting to run
				
			Cross-Build / build (~1.22.3, 1.22, solaris) (push) Waiting to run
				
			Cross-Build / build (~1.22.3, 1.22, windows) (push) Waiting to run
				
			Cross-Build / build (~1.23.0, 1.23, aix) (push) Waiting to run
				
			Cross-Build / build (~1.23.0, 1.23, darwin) (push) Waiting to run
				
			Cross-Build / build (~1.23.0, 1.23, dragonfly) (push) Waiting to run
				
			Cross-Build / build (~1.23.0, 1.23, freebsd) (push) Waiting to run
				
			Cross-Build / build (~1.23.0, 1.23, illumos) (push) Waiting to run
				
			Cross-Build / build (~1.23.0, 1.23, linux) (push) Waiting to run
				
			Cross-Build / build (~1.23.0, 1.23, netbsd) (push) Waiting to run
				
			Cross-Build / build (~1.23.0, 1.23, openbsd) (push) Waiting to run
				
			Cross-Build / build (~1.23.0, 1.23, solaris) (push) Waiting to run
				
			Cross-Build / build (~1.23.0, 1.23, windows) (push) Waiting to run
				
			Lint / lint (macos-14, mac) (push) Waiting to run
				
			Lint / lint (ubuntu-latest, linux) (push) Waiting to run
				
			Lint / lint (windows-latest, windows) (push) Waiting to run
				
			Lint / govulncheck (push) Waiting to run
				
			
		
			
				
	
	
		
			207 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package integration
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"crypto/ecdsa"
 | 
						|
	"crypto/elliptic"
 | 
						|
	"crypto/rand"
 | 
						|
	"log/slog"
 | 
						|
	"strings"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/caddyserver/caddy/v2/caddytest"
 | 
						|
	"github.com/mholt/acmez/v3"
 | 
						|
	"github.com/mholt/acmez/v3/acme"
 | 
						|
	"go.uber.org/zap"
 | 
						|
	"go.uber.org/zap/exp/zapslog"
 | 
						|
)
 | 
						|
 | 
						|
func TestACMEServerDirectory(t *testing.T) {
 | 
						|
	tester := caddytest.NewTester(t)
 | 
						|
	tester.InitServer(`
 | 
						|
	{
 | 
						|
		skip_install_trust
 | 
						|
		local_certs
 | 
						|
		admin localhost:2999
 | 
						|
		http_port     9080
 | 
						|
		https_port    9443
 | 
						|
		pki {
 | 
						|
			ca local {
 | 
						|
				name "Caddy Local Authority"
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	acme.localhost:9443 {
 | 
						|
		acme_server
 | 
						|
	}
 | 
						|
  `, "caddyfile")
 | 
						|
	tester.AssertGetResponse(
 | 
						|
		"https://acme.localhost:9443/acme/local/directory",
 | 
						|
		200,
 | 
						|
		`{"newNonce":"https://acme.localhost:9443/acme/local/new-nonce","newAccount":"https://acme.localhost:9443/acme/local/new-account","newOrder":"https://acme.localhost:9443/acme/local/new-order","revokeCert":"https://acme.localhost:9443/acme/local/revoke-cert","keyChange":"https://acme.localhost:9443/acme/local/key-change"}
 | 
						|
`)
 | 
						|
}
 | 
						|
 | 
						|
func TestACMEServerAllowPolicy(t *testing.T) {
 | 
						|
	tester := caddytest.NewTester(t)
 | 
						|
	tester.InitServer(`
 | 
						|
	{
 | 
						|
		skip_install_trust
 | 
						|
		local_certs
 | 
						|
		admin localhost:2999
 | 
						|
		http_port     9080
 | 
						|
		https_port    9443
 | 
						|
		pki {
 | 
						|
			ca local {
 | 
						|
				name "Caddy Local Authority"
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	acme.localhost {
 | 
						|
		acme_server {
 | 
						|
			challenges http-01
 | 
						|
			allow {
 | 
						|
				domains localhost
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
  `, "caddyfile")
 | 
						|
 | 
						|
	ctx := context.Background()
 | 
						|
	logger, err := zap.NewDevelopment()
 | 
						|
	if err != nil {
 | 
						|
		t.Error(err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	client := acmez.Client{
 | 
						|
		Client: &acme.Client{
 | 
						|
			Directory:  "https://acme.localhost:9443/acme/local/directory",
 | 
						|
			HTTPClient: tester.Client,
 | 
						|
			Logger:     slog.New(zapslog.NewHandler(logger.Core())),
 | 
						|
		},
 | 
						|
		ChallengeSolvers: map[string]acmez.Solver{
 | 
						|
			acme.ChallengeTypeHTTP01: &naiveHTTPSolver{logger: logger},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	accountPrivateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("generating account key: %v", err)
 | 
						|
	}
 | 
						|
	account := acme.Account{
 | 
						|
		Contact:              []string{"mailto:you@example.com"},
 | 
						|
		TermsOfServiceAgreed: true,
 | 
						|
		PrivateKey:           accountPrivateKey,
 | 
						|
	}
 | 
						|
	account, err = client.NewAccount(ctx, account)
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("new account: %v", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// Every certificate needs a key.
 | 
						|
	certPrivateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("generating certificate key: %v", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	{
 | 
						|
		certs, err := client.ObtainCertificateForSANs(ctx, account, certPrivateKey, []string{"localhost"})
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("obtaining certificate for allowed domain: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		// ACME servers should usually give you the entire certificate chain
 | 
						|
		// in PEM format, and sometimes even alternate chains! It's up to you
 | 
						|
		// which one(s) to store and use, but whatever you do, be sure to
 | 
						|
		// store the certificate and key somewhere safe and secure, i.e. don't
 | 
						|
		// lose them!
 | 
						|
		for _, cert := range certs {
 | 
						|
			t.Logf("Certificate %q:\n%s\n\n", cert.URL, cert.ChainPEM)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	{
 | 
						|
		_, err := client.ObtainCertificateForSANs(ctx, account, certPrivateKey, []string{"not-matching.localhost"})
 | 
						|
		if err == nil {
 | 
						|
			t.Errorf("obtaining certificate for 'not-matching.localhost' domain")
 | 
						|
		} else if err != nil && !strings.Contains(err.Error(), "urn:ietf:params:acme:error:rejectedIdentifier") {
 | 
						|
			t.Logf("unexpected error: %v", err)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestACMEServerDenyPolicy(t *testing.T) {
 | 
						|
	tester := caddytest.NewTester(t)
 | 
						|
	tester.InitServer(`
 | 
						|
	{
 | 
						|
		skip_install_trust
 | 
						|
		local_certs
 | 
						|
		admin localhost:2999
 | 
						|
		http_port     9080
 | 
						|
		https_port    9443
 | 
						|
		pki {
 | 
						|
			ca local {
 | 
						|
				name "Caddy Local Authority"
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	acme.localhost {
 | 
						|
		acme_server {
 | 
						|
			deny {
 | 
						|
				domains deny.localhost
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
  `, "caddyfile")
 | 
						|
 | 
						|
	ctx := context.Background()
 | 
						|
	logger, err := zap.NewDevelopment()
 | 
						|
	if err != nil {
 | 
						|
		t.Error(err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	client := acmez.Client{
 | 
						|
		Client: &acme.Client{
 | 
						|
			Directory:  "https://acme.localhost:9443/acme/local/directory",
 | 
						|
			HTTPClient: tester.Client,
 | 
						|
			Logger:     slog.New(zapslog.NewHandler(logger.Core())),
 | 
						|
		},
 | 
						|
		ChallengeSolvers: map[string]acmez.Solver{
 | 
						|
			acme.ChallengeTypeHTTP01: &naiveHTTPSolver{logger: logger},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	accountPrivateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("generating account key: %v", err)
 | 
						|
	}
 | 
						|
	account := acme.Account{
 | 
						|
		Contact:              []string{"mailto:you@example.com"},
 | 
						|
		TermsOfServiceAgreed: true,
 | 
						|
		PrivateKey:           accountPrivateKey,
 | 
						|
	}
 | 
						|
	account, err = client.NewAccount(ctx, account)
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("new account: %v", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// Every certificate needs a key.
 | 
						|
	certPrivateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("generating certificate key: %v", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	{
 | 
						|
		_, err := client.ObtainCertificateForSANs(ctx, account, certPrivateKey, []string{"deny.localhost"})
 | 
						|
		if err == nil {
 | 
						|
			t.Errorf("obtaining certificate for 'deny.localhost' domain")
 | 
						|
		} else if err != nil && !strings.Contains(err.Error(), "urn:ietf:params:acme:error:rejectedIdentifier") {
 | 
						|
			t.Logf("unexpected error: %v", err)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |