1 // Package acme contains all objects related the ACME endpoints.
2 // https://www.rfc-editor.org/rfc/rfc8555.html
3 package acme
4 5 import (
6 "encoding/json"
7 "time"
8 )
9 10 // ACME status values of Account, Order, Authorization and Challenge objects.
11 // See https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.6 for details.
12 const (
13 StatusDeactivated = "deactivated"
14 StatusExpired = "expired"
15 StatusInvalid = "invalid"
16 StatusPending = "pending"
17 StatusProcessing = "processing"
18 StatusReady = "ready"
19 StatusRevoked = "revoked"
20 StatusUnknown = "unknown"
21 StatusValid = "valid"
22 )
23 24 // CRL reason codes as defined in RFC 5280.
25 // https://datatracker.ietf.org/doc/html/rfc5280#section-5.3.1
26 const (
27 CRLReasonUnspecified uint = 0
28 CRLReasonKeyCompromise uint = 1
29 CRLReasonCACompromise uint = 2
30 CRLReasonAffiliationChanged uint = 3
31 CRLReasonSuperseded uint = 4
32 CRLReasonCessationOfOperation uint = 5
33 CRLReasonCertificateHold uint = 6
34 CRLReasonRemoveFromCRL uint = 8
35 CRLReasonPrivilegeWithdrawn uint = 9
36 CRLReasonAACompromise uint = 10
37 )
38 39 // Directory the ACME directory object.
40 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.1
41 // - https://www.rfc-editor.org/rfc/rfc9773.html
42 type Directory struct {
43 NewNonceURL string `json:"newNonce"`
44 NewAccountURL string `json:"newAccount"`
45 NewOrderURL string `json:"newOrder"`
46 NewAuthzURL string `json:"newAuthz"`
47 RevokeCertURL string `json:"revokeCert"`
48 KeyChangeURL string `json:"keyChange"`
49 Meta Meta `json:"meta"`
50 RenewalInfo string `json:"renewalInfo"`
51 }
52 53 // Meta the ACME meta object (related to Directory).
54 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.1
55 type Meta struct {
56 // termsOfService (optional, string):
57 // A URL identifying the current terms of service.
58 TermsOfService string `json:"termsOfService"`
59 60 // website (optional, string):
61 // An HTTP or HTTPS URL locating a website providing more information about the ACME server.
62 Website string `json:"website"`
63 64 // caaIdentities (optional, array of string):
65 // The hostnames that the ACME server recognizes as referring to itself
66 // for the purposes of CAA record validation as defined in [RFC6844].
67 // Each string MUST represent the same sequence of ASCII code points
68 // that the server will expect to see as the "Issuer Domain Name" in a CAA issue or issuewild property tag.
69 // This allows clients to determine the correct issuer domain name to use when configuring CAA records.
70 CaaIdentities []string `json:"caaIdentities"`
71 72 // externalAccountRequired (optional, boolean):
73 // If this field is present and set to "true",
74 // then the CA requires that all new-account requests include an "externalAccountBinding" field
75 // associating the new account with an external account.
76 ExternalAccountRequired bool `json:"externalAccountRequired"`
77 78 // profiles (optional, object):
79 // A map of profile names to human-readable descriptions of those profiles.
80 // https://www.ietf.org/id/draft-ietf-acme-profiles-00.html#section-3
81 Profiles map[string]string `json:"profiles"`
82 }
83 84 // ExtendedAccount an extended Account.
85 type ExtendedAccount struct {
86 Account
87 88 // Contains the value of the response header `Location`
89 Location string `json:"-"`
90 }
91 92 // Account the ACME account Object.
93 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.2
94 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.3
95 type Account struct {
96 // status (required, string):
97 // The status of this account.
98 // Possible values are: "valid", "deactivated", and "revoked".
99 // The value "deactivated" should be used to indicate client-initiated deactivation
100 // whereas "revoked" should be used to indicate server-initiated deactivation. (See Section 7.1.6)
101 Status string `json:"status,omitempty"`
102 103 // contact (optional, array of string):
104 // An array of URLs that the server can use to contact the client for issues related to this account.
105 // For example, the server may wish to notify the client about server-initiated revocation or certificate expiration.
106 // For information on supported URL schemes, see Section 7.3
107 Contact []string `json:"contact,omitempty"`
108 109 // termsOfServiceAgreed (optional, boolean):
110 // Including this field in a new-account request,
111 // with a value of true, indicates the client's agreement with the terms of service.
112 // This field is not updateable by the client.
113 TermsOfServiceAgreed bool `json:"termsOfServiceAgreed,omitempty"`
114 115 // orders (required, string):
116 // A URL from which a list of orders submitted by this account can be fetched via a POST-as-GET request,
117 // as described in Section 7.1.2.1.
118 Orders string `json:"orders,omitempty"`
119 120 // onlyReturnExisting (optional, boolean):
121 // If this field is present with the value "true",
122 // then the server MUST NOT create a new account if one does not already exist.
123 // This allows a client to look up an account URL based on an account key (see Section 7.3.1).
124 OnlyReturnExisting bool `json:"onlyReturnExisting,omitempty"`
125 126 // externalAccountBinding (optional, object):
127 // An optional field for binding the new account with an existing non-ACME account (see Section 7.3.4).
128 ExternalAccountBinding json.RawMessage `json:"externalAccountBinding,omitempty"`
129 }
130 131 // ExtendedOrder a extended Order.
132 type ExtendedOrder struct {
133 Order
134 135 // The order URL, contains the value of the response header `Location`
136 Location string `json:"-"`
137 }
138 139 // Order the ACME order Object.
140 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.3
141 type Order struct {
142 // status (required, string):
143 // The status of this order.
144 // Possible values are: "pending", "ready", "processing", "valid", and "invalid".
145 Status string `json:"status,omitempty"`
146 147 // expires (optional, string):
148 // The timestamp after which the server will consider this order invalid,
149 // encoded in the format specified in RFC 3339 [RFC3339].
150 // This field is REQUIRED for objects with "pending" or "valid" in the status field.
151 Expires string `json:"expires,omitempty"`
152 153 // identifiers (required, array of object):
154 // An array of identifier objects that the order pertains to.
155 Identifiers []Identifier `json:"identifiers"`
156 157 // profile (string, optional):
158 // A string uniquely identifying the profile
159 // which will be used to affect issuance of the certificate requested by this Order.
160 // https://www.ietf.org/id/draft-ietf-acme-profiles-00.html#section-4
161 Profile string `json:"profile,omitempty"`
162 163 // notBefore (optional, string):
164 // The requested value of the notBefore field in the certificate,
165 // in the date format defined in [RFC3339].
166 NotBefore string `json:"notBefore,omitempty"`
167 168 // notAfter (optional, string):
169 // The requested value of the notAfter field in the certificate,
170 // in the date format defined in [RFC3339].
171 NotAfter string `json:"notAfter,omitempty"`
172 173 // error (optional, object):
174 // The error that occurred while processing the order, if any.
175 // This field is structured as a problem document [RFC7807].
176 Error *ProblemDetails `json:"error,omitempty"`
177 178 // authorizations (required, array of string):
179 // For pending orders,
180 // the authorizations that the client needs to complete before the requested certificate can be issued (see Section 7.5),
181 // including unexpired authorizations that the client has completed in the past for identifiers specified in the order.
182 // The authorizations required are dictated by server policy
183 // and there may not be a 1:1 relationship between the order identifiers and the authorizations required.
184 // For final orders (in the "valid" or "invalid" state), the authorizations that were completed.
185 // Each entry is a URL from which an authorization can be fetched with a POST-as-GET request.
186 Authorizations []string `json:"authorizations,omitempty"`
187 188 // finalize (required, string):
189 // A URL that a CSR must be POSTed to once all of the order's authorizations are satisfied to finalize the order.
190 // The result of a successful finalization will be the population of the certificate URL for the order.
191 Finalize string `json:"finalize,omitempty"`
192 193 // certificate (optional, string):
194 // A URL for the certificate that has been issued in response to this order
195 Certificate string `json:"certificate,omitempty"`
196 197 // replaces (optional, string):
198 // replaces (string, optional): A string uniquely identifying a
199 // previously-issued certificate which this order is intended to replace.
200 // - https://www.rfc-editor.org/rfc/rfc9773.html#section-5
201 Replaces string `json:"replaces,omitempty"`
202 }
203 204 func (r *Order) Err() error {
205 if r.Error != nil {
206 return r.Error
207 }
208 209 return nil
210 }
211 212 // Authorization the ACME authorization object.
213 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.4
214 type Authorization struct {
215 // status (required, string):
216 // The status of this authorization.
217 // Possible values are: "pending", "valid", "invalid", "deactivated", "expired", and "revoked".
218 Status string `json:"status"`
219 220 // expires (optional, string):
221 // The timestamp after which the server will consider this authorization invalid,
222 // encoded in the format specified in RFC 3339 [RFC3339].
223 // This field is REQUIRED for objects with "valid" in the "status" field.
224 Expires time.Time `json:"expires,omitzero"`
225 226 // identifier (required, object):
227 // The identifier that the account is authorized to represent
228 Identifier Identifier `json:"identifier"`
229 230 // challenges (required, array of objects):
231 // For pending authorizations, the challenges that the client can fulfill in order to prove possession of the identifier.
232 // For valid authorizations, the challenge that was validated.
233 // For invalid authorizations, the challenge that was attempted and failed.
234 // Each array entry is an object with parameters required to validate the challenge.
235 // A client should attempt to fulfill one of these challenges,
236 // and a server should consider any one of the challenges sufficient to make the authorization valid.
237 Challenges []Challenge `json:"challenges,omitempty"`
238 239 // wildcard (optional, boolean):
240 // For authorizations created as a result of a newOrder request containing a DNS identifier
241 // with a value that contained a wildcard prefix this field MUST be present, and true.
242 Wildcard bool `json:"wildcard,omitempty"`
243 }
244 245 // ExtendedChallenge a extended Challenge.
246 type ExtendedChallenge struct {
247 Challenge
248 249 // Contains the value of the response header `Retry-After`
250 RetryAfter string `json:"-"`
251 // Contains the value of the response header `Link` rel="up"
252 AuthorizationURL string `json:"-"`
253 }
254 255 // Challenge the ACME challenge object.
256 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.5
257 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-8
258 type Challenge struct {
259 // type (required, string):
260 // The type of challenge encoded in the object.
261 Type string `json:"type"`
262 263 // url (required, string):
264 // The URL to which a response can be posted.
265 URL string `json:"url"`
266 267 // status (required, string):
268 // The status of this challenge. Possible values are: "pending", "processing", "valid", and "invalid".
269 Status string `json:"status"`
270 271 // validated (optional, string):
272 // The time at which the server validated this challenge,
273 // encoded in the format specified in RFC 3339 [RFC3339].
274 // This field is REQUIRED if the "status" field is "valid".
275 Validated time.Time `json:"validated,omitzero"`
276 277 // error (optional, object):
278 // Error that occurred while the server was validating the challenge, if any,
279 // structured as a problem document [RFC7807].
280 // Multiple errors can be indicated by using subproblems Section 6.7.1.
281 // A challenge object with an error MUST have status equal to "invalid".
282 Error *ProblemDetails `json:"error,omitempty"`
283 284 // token (required, string):
285 // A random value that uniquely identifies the challenge.
286 // This value MUST have at least 128 bits of entropy.
287 // It MUST NOT contain any characters outside the base64url alphabet,
288 // and MUST NOT include base64 padding characters ("=").
289 // See [RFC4086] for additional information on randomness requirements.
290 // https://www.rfc-editor.org/rfc/rfc8555.html#section-8.3
291 // https://www.rfc-editor.org/rfc/rfc8555.html#section-8.4
292 Token string `json:"token"`
293 294 // https://www.rfc-editor.org/rfc/rfc8555.html#section-8.1
295 KeyAuthorization string `json:"keyAuthorization"`
296 }
297 298 func (c *Challenge) Err() error {
299 if c.Error != nil {
300 return c.Error
301 }
302 303 return nil
304 }
305 306 // Identifier the ACME identifier object.
307 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-9.7.7
308 type Identifier struct {
309 Type string `json:"type"`
310 Value string `json:"value"`
311 }
312 313 // CSRMessage Certificate Signing Request.
314 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4
315 type CSRMessage struct {
316 // csr (required, string):
317 // A CSR encoding the parameters for the certificate being requested [RFC2986].
318 // The CSR is sent in the base64url-encoded version of the DER format.
319 // (Note: Because this field uses base64url, and does not include headers, it is different from PEM.).
320 Csr string `json:"csr"`
321 }
322 323 // RevokeCertMessage a certificate revocation message.
324 // - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.6
325 // - https://www.rfc-editor.org/rfc/rfc5280.html#section-5.3.1
326 type RevokeCertMessage struct {
327 // certificate (required, string):
328 // The certificate to be revoked, in the base64url-encoded version of the DER format.
329 // (Note: Because this field uses base64url, and does not include headers, it is different from PEM.)
330 Certificate string `json:"certificate"`
331 332 // reason (optional, int):
333 // One of the revocation reasonCodes defined in Section 5.3.1 of [RFC5280] to be used when generating OCSP responses and CRLs.
334 // If this field is not set the server SHOULD omit the reasonCode CRL entry extension when generating OCSP responses and CRLs.
335 // The server MAY disallow a subset of reasonCodes from being used by the user.
336 // If a request contains a disallowed reasonCode the server MUST reject it with the error type "urn:ietf:params:acme:error:badRevocationReason".
337 // The problem document detail SHOULD indicate which reasonCodes are allowed.
338 Reason *uint `json:"reason,omitempty"`
339 }
340 341 // RawCertificate raw data of a certificate.
342 type RawCertificate struct {
343 Cert []byte
344 Issuer []byte
345 }
346 347 // Window is a window of time.
348 type Window struct {
349 Start time.Time `json:"start"`
350 End time.Time `json:"end"`
351 }
352 353 // RenewalInfoResponse is the response to GET requests made the renewalInfo endpoint.
354 // - (4.1. Getting Renewal Information) https://www.rfc-editor.org/rfc/rfc9773.html
355 type RenewalInfoResponse struct {
356 // SuggestedWindow contains two fields, start and end,
357 // whose values are timestamps which bound the window of time in which the CA recommends renewing the certificate.
358 SuggestedWindow Window `json:"suggestedWindow"`
359 // ExplanationURL is an optional URL pointing to a page which may explain why the suggested renewal window is what it is.
360 // For example, it may be a page explaining the CA's dynamic load-balancing strategy,
361 // or a page documenting which certificates are affected by a mass revocation event.
362 // Callers SHOULD provide this URL to their operator, if present.
363 ExplanationURL string `json:"explanationURL"`
364 }
365 366 // RenewalInfoUpdateRequest is the JWS payload for POST requests made to the renewalInfo endpoint.
367 // - (4.2. RenewalInfo Objects) https://www.rfc-editor.org/rfc/rfc9773.html#section-4.2
368 type RenewalInfoUpdateRequest struct {
369 // CertID is a composite string in the format: base64url(AKI) || '.' || base64url(Serial), where AKI is the
370 // certificate's authority key identifier and Serial is the certificate's serial number. For details, see:
371 // https://www.rfc-editor.org/rfc/rfc9773.html#section-4.1
372 CertID string `json:"certID"`
373 // Replaced is required and indicates whether or not the client considers the certificate to have been replaced.
374 // A certificate is considered replaced when its revocation would not disrupt any ongoing services,
375 // for instance because it has been renewed and the new certificate is in use, or because it is no longer in use.
376 // Clients SHOULD NOT send a request where this value is false.
377 Replaced bool `json:"replaced"`
378 }
379