summaryrefslogtreecommitdiff
path: root/sysutils/docker-registry/files/patch-pr3943
blob: f24c07350ed354ae2eeedd352b85803fcc5db499 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
Adapted from the https://github.com/distribution/distribution/pull/3943

	-mi

From 9b4f2caaf89c63b015bbed3e710501df5cf2f75a Mon Sep 17 00:00:00 2001
From: Alex Lavallee <73203142+lavalleeale@users.noreply.github.com>
Date: Sun, 18 Jun 2023 09:52:12 -0700
Subject: [PATCH] Add support for modern ACME

Signed-off-by: Alex Lavallee <73203142+lavalleeale@users.noreply.github.com>
---
 configuration/configuration.go                |    4 +
 configuration/configuration_test.go           |   14 +-
 docs/configuration.md                         |   12 +-
 registry/registry.go                          |   29 +-
...

--- configuration/configuration.go
+++ configuration/configuration.go
@@ -129,6 +129,10 @@ type Configuration struct {
 				// Hosts specifies the hosts which are allowed to obtain Let's
 				// Encrypt certificates.
 				Hosts []string `yaml:"hosts,omitempty"`
+
+				// DirectoryURL points to the CA directory endpoint.
+				// If empty, LetsEncrypt is used.
+				DirectoryURL string `yaml:"directoryurl,omitempty"`
 			} `yaml:"letsencrypt,omitempty"`
 		} `yaml:"tls,omitempty"`
 
--- configuration/configuration_test.go
+++ configuration/configuration_test.go
@@ -89,9 +89,10 @@ var configStruct = Configuration{
 			MinimumTLS   string   `yaml:"minimumtls,omitempty"`
 			CipherSuites []string `yaml:"ciphersuites,omitempty"`
 			LetsEncrypt  struct {
-				CacheFile string   `yaml:"cachefile,omitempty"`
-				Email     string   `yaml:"email,omitempty"`
-				Hosts     []string `yaml:"hosts,omitempty"`
+				CacheFile    string   `yaml:"cachefile,omitempty"`
+				Email        string   `yaml:"email,omitempty"`
+				Hosts        []string `yaml:"hosts,omitempty"`
+				DirectoryURL string   `yaml:"directoryurl,omitempty"`
 			} `yaml:"letsencrypt,omitempty"`
 		} `yaml:"tls,omitempty"`
 		Headers http.Header `yaml:"headers,omitempty"`
@@ -113,9 +114,10 @@ var configStruct = Configuration{
 			MinimumTLS   string   `yaml:"minimumtls,omitempty"`
 			CipherSuites []string `yaml:"ciphersuites,omitempty"`
 			LetsEncrypt  struct {
-				CacheFile string   `yaml:"cachefile,omitempty"`
-				Email     string   `yaml:"email,omitempty"`
-				Hosts     []string `yaml:"hosts,omitempty"`
+				CacheFile    string   `yaml:"cachefile,omitempty"`
+				Email        string   `yaml:"email,omitempty"`
+				Hosts        []string `yaml:"hosts,omitempty"`
+				DirectoryURL string   `yaml:"directoryurl,omitempty"`
 			} `yaml:"letsencrypt,omitempty"`
 		}{
 			ClientCAs: []string{"/path/to/ca.pem"},
--- docs/configuration.md
+++ docs/configuration.md
@@ -229,6 +229,7 @@ http:
       cachefile: /path/to/cache-file
       email: emailused@letsencrypt.com
       hosts: [myregistryaddress.org]
+      directoryurl: https://acme-v02.api.letsencrypt.org/directory
   debug:
     addr: localhost:5001
     prometheus:
@@ -879,11 +880,12 @@ TLS certificates provided by
 > that are valid for this registry to avoid trying to get certificates for random
 > hostnames due to malicious clients connecting with bogus SNI hostnames.
 
-| Parameter | Required | Description                                           |
-|-----------|----------|-------------------------------------------------------|
-| `cachefile` | yes    | Absolute path to a file where the Let's Encrypt agent can cache data. |
-| `email`   | yes      | The email address used to register with Let's Encrypt. |
-| `hosts`   | no       | The hostnames allowed for Let's Encrypt certificates. |
+| Parameter      | Required | Description                                                           |
+|----------------|----------|-----------------------------------------------------------------------|
+| `cachefile`    | yes      | Absolute path to a file where the Let's Encrypt agent can cache data. |
+| `email`        | yes      | The email address used to register with Let's Encrypt.                |
+| `hosts`        | no       | The hostnames allowed for Let's Encrypt certificates.                 |
+| `directoryurl` | no       | The url to use for the ACME server.                                   |
 
 ### `debug`
 
--- registry/registry.go
+++ registry/registry.go
@@ -13,7 +13,8 @@ import (
 	"syscall"
 	"time"
 
-	"rsc.io/letsencrypt"
+	"golang.org/x/crypto/acme"
+	"golang.org/x/crypto/acme/autocert"
 
 	logrus_bugsnag "github.com/Shopify/logrus-bugsnag"
 
@@ -210,6 +211,14 @@ func getCipherSuiteNames(ids []uint16) []string {
 	return names
 }
 
+// set ACME-server/DirectoryURL, if provided
+func setDirectoryURL(directoryurl string) *acme.Client {
+	if len(directoryurl) > 0 {
+		return &acme.Client{DirectoryURL: directoryurl}
+	}
+	return nil
+}
+
 // ListenAndServe runs the registry's HTTP server.
 func (registry *Registry) ListenAndServe() error {
 	config := registry.config
@@ -247,19 +256,15 @@ func (registry *Registry) ListenAndServe() error {
 			if config.HTTP.TLS.Certificate != "" {
 				return fmt.Errorf("cannot specify both certificate and Let's Encrypt")
 			}
-			var m letsencrypt.Manager
-			if err := m.CacheFile(config.HTTP.TLS.LetsEncrypt.CacheFile); err != nil {
-				return err
-			}
-			if !m.Registered() {
-				if err := m.Register(config.HTTP.TLS.LetsEncrypt.Email, nil); err != nil {
-					return err
-				}
-			}
-			if len(config.HTTP.TLS.LetsEncrypt.Hosts) > 0 {
-				m.SetHosts(config.HTTP.TLS.LetsEncrypt.Hosts)
+			m := &autocert.Manager{
+				HostPolicy: autocert.HostWhitelist(config.HTTP.TLS.LetsEncrypt.Hosts...),
+				Cache:      autocert.DirCache(config.HTTP.TLS.LetsEncrypt.CacheFile),
+				Email:      config.HTTP.TLS.LetsEncrypt.Email,
+				Prompt:     autocert.AcceptTOS,
+				Client:     setDirectoryURL(config.HTTP.TLS.LetsEncrypt.DirectoryURL),
 			}
 			tlsConf.GetCertificate = m.GetCertificate
+			tlsConf.NextProtos = append(tlsConf.NextProtos, acme.ALPNProto)
 		} else {
 			tlsConf.Certificates = make([]tls.Certificate, 1)
 			tlsConf.Certificates[0], err = tls.LoadX509KeyPair(config.HTTP.TLS.Certificate, config.HTTP.TLS.Key)