@alchemy.run/acme 0.0.0 → 2.0.0-beta.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +48 -4
- package/lib/Account.d.ts +121 -0
- package/lib/Account.d.ts.map +1 -0
- package/lib/Account.js +163 -0
- package/lib/Account.js.map +1 -0
- package/lib/Certificate.d.ts +138 -0
- package/lib/Certificate.d.ts.map +1 -0
- package/lib/Certificate.js +157 -0
- package/lib/Certificate.js.map +1 -0
- package/lib/CertificateAuthority.d.ts +25 -0
- package/lib/CertificateAuthority.d.ts.map +1 -0
- package/lib/CertificateAuthority.js +22 -0
- package/lib/CertificateAuthority.js.map +1 -0
- package/lib/Client.d.ts +89 -0
- package/lib/Client.d.ts.map +1 -0
- package/lib/Client.js +237 -0
- package/lib/Client.js.map +1 -0
- package/lib/Der.d.ts +43 -0
- package/lib/Der.d.ts.map +1 -0
- package/lib/Der.js +138 -0
- package/lib/Der.js.map +1 -0
- package/lib/Dns.d.ts +59 -0
- package/lib/Dns.d.ts.map +1 -0
- package/lib/Dns.js +104 -0
- package/lib/Dns.js.map +1 -0
- package/lib/DnsSolver.d.ts +60 -0
- package/lib/DnsSolver.d.ts.map +1 -0
- package/lib/DnsSolver.js +48 -0
- package/lib/DnsSolver.js.map +1 -0
- package/lib/Errors.d.ts +93 -0
- package/lib/Errors.d.ts.map +1 -0
- package/lib/Errors.js +51 -0
- package/lib/Errors.js.map +1 -0
- package/lib/IssueCertificate.d.ts +76 -0
- package/lib/IssueCertificate.d.ts.map +1 -0
- package/lib/IssueCertificate.js +3 -0
- package/lib/IssueCertificate.js.map +1 -0
- package/lib/IssueCertificateHttp.d.ts +24 -0
- package/lib/IssueCertificateHttp.d.ts.map +1 -0
- package/lib/IssueCertificateHttp.js +56 -0
- package/lib/IssueCertificateHttp.js.map +1 -0
- package/lib/Pki.d.ts +56 -0
- package/lib/Pki.d.ts.map +1 -0
- package/lib/Pki.js +182 -0
- package/lib/Pki.js.map +1 -0
- package/lib/Providers.d.ts +30 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +31 -0
- package/lib/Providers.js.map +1 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +12 -0
- package/lib/index.js.map +1 -0
- package/package.json +47 -3
- package/src/Account.ts +254 -0
- package/src/Certificate.ts +272 -0
- package/src/CertificateAuthority.ts +41 -0
- package/src/Client.ts +405 -0
- package/src/Der.ts +157 -0
- package/src/Dns.ts +227 -0
- package/src/DnsSolver.ts +109 -0
- package/src/Errors.ts +90 -0
- package/src/IssueCertificate.ts +89 -0
- package/src/IssueCertificateHttp.ts +67 -0
- package/src/Pki.ts +275 -0
- package/src/Providers.ts +39 -0
- package/src/index.ts +11 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import * as Provider from "alchemy/Provider";
|
|
2
|
+
import { Resource } from "alchemy/Resource";
|
|
3
|
+
import * as Duration from "effect/Duration";
|
|
4
|
+
import type * as Redacted from "effect/Redacted";
|
|
5
|
+
import type { Account } from "./Account.ts";
|
|
6
|
+
import type { PropagationOptions } from "./Dns.ts";
|
|
7
|
+
import { type DnsSolverDescriptor } from "./DnsSolver.ts";
|
|
8
|
+
import type { KeyAlgorithm } from "./Pki.ts";
|
|
9
|
+
import type { Providers } from "./Providers.ts";
|
|
10
|
+
export interface CertificateProps {
|
|
11
|
+
/** The {@link Account} that orders the certificate. Changing it replaces. */
|
|
12
|
+
account: Account;
|
|
13
|
+
/**
|
|
14
|
+
* DNS names the certificate covers. The first is the subject CN;
|
|
15
|
+
* wildcards (`*.example.com`) are allowed. Changing the set re-issues.
|
|
16
|
+
*/
|
|
17
|
+
identifiers: string[];
|
|
18
|
+
/**
|
|
19
|
+
* How `_acme-challenge` TXT records are published, e.g.
|
|
20
|
+
* `Cloudflare.ACME.ZoneSolver(zone)`. Changing the solver alone does not
|
|
21
|
+
* re-issue.
|
|
22
|
+
*/
|
|
23
|
+
solver: DnsSolverDescriptor;
|
|
24
|
+
/**
|
|
25
|
+
* Certificate key algorithm. Changing it re-issues the certificate.
|
|
26
|
+
* @default "ES256"
|
|
27
|
+
*/
|
|
28
|
+
keyAlgorithm?: KeyAlgorithm;
|
|
29
|
+
/**
|
|
30
|
+
* Re-issue when less than this remains before `notAfter`. Renewal is a
|
|
31
|
+
* `diff` result, so any `alchemy deploy` (a scheduled one, typically)
|
|
32
|
+
* renews.
|
|
33
|
+
* @default "30 days"
|
|
34
|
+
*/
|
|
35
|
+
renewBefore?: Duration.Input;
|
|
36
|
+
/**
|
|
37
|
+
* Revoke the certificate at the CA when the resource is deleted. By
|
|
38
|
+
* default deletion only forgets the certificate.
|
|
39
|
+
* @default false
|
|
40
|
+
*/
|
|
41
|
+
revokeOnDelete?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Issuer name to prefer (`CN=…` substring, e.g. `ISRG Root X1`) when the
|
|
44
|
+
* CA offers alternate chains.
|
|
45
|
+
*/
|
|
46
|
+
preferredChain?: string;
|
|
47
|
+
/** DNS propagation polling (resolvers, timeout, interval). */
|
|
48
|
+
propagation?: PropagationOptions;
|
|
49
|
+
}
|
|
50
|
+
export interface Certificate extends Resource<"ACME.Certificate", CertificateProps, {
|
|
51
|
+
/** Leaf certificate PEM. */
|
|
52
|
+
certificate: string;
|
|
53
|
+
/** Full chain PEM, leaf first. */
|
|
54
|
+
chain: string;
|
|
55
|
+
/** PKCS#8 private key PEM. Sensitive; persisted in stack state. */
|
|
56
|
+
privateKey: Redacted.Redacted<string>;
|
|
57
|
+
/** Serial number, hex. */
|
|
58
|
+
serial: string;
|
|
59
|
+
/** ISO 8601 validity start. */
|
|
60
|
+
notBefore: string;
|
|
61
|
+
/** ISO 8601 expiry. Renewal is scheduled against it. */
|
|
62
|
+
notAfter: string;
|
|
63
|
+
/** Issuer distinguished name. */
|
|
64
|
+
issuer: string;
|
|
65
|
+
/** The DNS names covered. */
|
|
66
|
+
identifiers: string[];
|
|
67
|
+
/** The CA's certificate URL. */
|
|
68
|
+
certificateUrl: string;
|
|
69
|
+
/** The CA's order URL. */
|
|
70
|
+
orderUrl: string;
|
|
71
|
+
/** Key algorithm of `privateKey`. */
|
|
72
|
+
keyAlgorithm: KeyAlgorithm;
|
|
73
|
+
/** The account that issued the certificate. */
|
|
74
|
+
accountUrl: string;
|
|
75
|
+
/** The CA the certificate was issued by (for revocation on delete). */
|
|
76
|
+
directoryUrl: string;
|
|
77
|
+
/** PEM root trusted for the CA's endpoint (private CAs only). */
|
|
78
|
+
trustedRoot: string | undefined;
|
|
79
|
+
}, never, Providers> {
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* A TLS certificate issued over ACME at deploy time, with renewal.
|
|
83
|
+
*
|
|
84
|
+
* Reconcile places an order, proves control of every name over DNS-01
|
|
85
|
+
* through the `solver`, finalizes with a fresh key's CSR and stores the
|
|
86
|
+
* chain and redacted private key in state. Protect the state store as
|
|
87
|
+
* secret material. `diff` reports an update when the
|
|
88
|
+
* names change or when `renewBefore` of validity remains, so a scheduled
|
|
89
|
+
* `alchemy deploy` keeps certificates fresh.
|
|
90
|
+
*
|
|
91
|
+
* ### Wildcard certificate
|
|
92
|
+
* **Example:** Let's Encrypt wildcard over Cloudflare DNS
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const account = yield* ACME.Account("Issuer", {
|
|
95
|
+
* ca: ACME.LetsEncrypt,
|
|
96
|
+
* termsOfServiceAgreed: true,
|
|
97
|
+
* });
|
|
98
|
+
* const zone = yield* Zone;
|
|
99
|
+
* const wildcard = yield* ACME.Certificate("Wildcard", {
|
|
100
|
+
* account,
|
|
101
|
+
* identifiers: ["*.example.com", "example.com"],
|
|
102
|
+
* solver: Cloudflare.ACME.ZoneSolver(zone),
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* ### Using the certificate
|
|
107
|
+
* The chain and key are Outputs — pass them to whatever terminates TLS.
|
|
108
|
+
*
|
|
109
|
+
* **Example:** Upload to a Fly App
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const www = yield* Fly.Certificate("Www", {
|
|
112
|
+
* app: Site,
|
|
113
|
+
* hostname: "www.example.com",
|
|
114
|
+
* kind: "custom",
|
|
115
|
+
* fullchain: wildcard.chain,
|
|
116
|
+
* privateKey: wildcard.privateKey,
|
|
117
|
+
* });
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* ### Renewal
|
|
121
|
+
* **Example:** Renew earlier and revoke on delete
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const api = yield* ACME.Certificate("Api", {
|
|
124
|
+
* account,
|
|
125
|
+
* identifiers: ["api.example.com"],
|
|
126
|
+
* solver: Cloudflare.ACME.ZoneSolver(zone),
|
|
127
|
+
* renewBefore: "45 days",
|
|
128
|
+
* revokeOnDelete: true,
|
|
129
|
+
* });
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @resource
|
|
133
|
+
* @product Certificate
|
|
134
|
+
* @category Certificates
|
|
135
|
+
*/
|
|
136
|
+
export declare const Certificate: import("alchemy/Resource").ResourceClass<Certificate>;
|
|
137
|
+
export declare const CertificateProvider: () => import("effect/Layer").Layer<Provider.Provider<Certificate>, never, never>;
|
|
138
|
+
//# sourceMappingURL=Certificate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Certificate.d.ts","sourceRoot":"","sources":["../src/Certificate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAO5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAoB,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,MAAM,EAAE,mBAAmB,CAAC;IAC5B;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC7B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,kBAAkB,EAClB,gBAAgB,EAChB;IACE,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,UAAU,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACtC,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gCAAgC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,YAAY,EAAE,YAAY,CAAC;IAC3B,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,EACD,KAAK,EACL,SAAS,CACV;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,eAAO,MAAM,WAAW,uDAA4C,CAAC;AA0BrE,eAAO,MAAM,mBAAmB,kFA6F5B,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { isResolved } from "alchemy/Diff";
|
|
2
|
+
import * as Provider from "alchemy/Provider";
|
|
3
|
+
import { Resource } from "alchemy/Resource";
|
|
4
|
+
import { arrayEqualsUnordered } from "alchemy/Util/equal";
|
|
5
|
+
import * as Duration from "effect/Duration";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
import { accountLayer, issueCertificate, revokeCertificate, } from "./Client.js";
|
|
8
|
+
import { resolveDnsSolver } from "./DnsSolver.js";
|
|
9
|
+
/**
|
|
10
|
+
* A TLS certificate issued over ACME at deploy time, with renewal.
|
|
11
|
+
*
|
|
12
|
+
* Reconcile places an order, proves control of every name over DNS-01
|
|
13
|
+
* through the `solver`, finalizes with a fresh key's CSR and stores the
|
|
14
|
+
* chain and redacted private key in state. Protect the state store as
|
|
15
|
+
* secret material. `diff` reports an update when the
|
|
16
|
+
* names change or when `renewBefore` of validity remains, so a scheduled
|
|
17
|
+
* `alchemy deploy` keeps certificates fresh.
|
|
18
|
+
*
|
|
19
|
+
* ### Wildcard certificate
|
|
20
|
+
* **Example:** Let's Encrypt wildcard over Cloudflare DNS
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const account = yield* ACME.Account("Issuer", {
|
|
23
|
+
* ca: ACME.LetsEncrypt,
|
|
24
|
+
* termsOfServiceAgreed: true,
|
|
25
|
+
* });
|
|
26
|
+
* const zone = yield* Zone;
|
|
27
|
+
* const wildcard = yield* ACME.Certificate("Wildcard", {
|
|
28
|
+
* account,
|
|
29
|
+
* identifiers: ["*.example.com", "example.com"],
|
|
30
|
+
* solver: Cloudflare.ACME.ZoneSolver(zone),
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* ### Using the certificate
|
|
35
|
+
* The chain and key are Outputs — pass them to whatever terminates TLS.
|
|
36
|
+
*
|
|
37
|
+
* **Example:** Upload to a Fly App
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const www = yield* Fly.Certificate("Www", {
|
|
40
|
+
* app: Site,
|
|
41
|
+
* hostname: "www.example.com",
|
|
42
|
+
* kind: "custom",
|
|
43
|
+
* fullchain: wildcard.chain,
|
|
44
|
+
* privateKey: wildcard.privateKey,
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* ### Renewal
|
|
49
|
+
* **Example:** Renew earlier and revoke on delete
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const api = yield* ACME.Certificate("Api", {
|
|
52
|
+
* account,
|
|
53
|
+
* identifiers: ["api.example.com"],
|
|
54
|
+
* solver: Cloudflare.ACME.ZoneSolver(zone),
|
|
55
|
+
* renewBefore: "45 days",
|
|
56
|
+
* revokeOnDelete: true,
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @resource
|
|
61
|
+
* @product Certificate
|
|
62
|
+
* @category Certificates
|
|
63
|
+
*/
|
|
64
|
+
export const Certificate = Resource("ACME.Certificate");
|
|
65
|
+
/** The resolved account attributes behind a resource-valued prop. */
|
|
66
|
+
const accountOf = (value) => value;
|
|
67
|
+
const credentialsOf = (account) => ({
|
|
68
|
+
ca: { directoryUrl: account.directoryUrl, trustedRoot: account.trustedRoot },
|
|
69
|
+
accountKey: account.privateKey,
|
|
70
|
+
accountUrl: account.accountUrl,
|
|
71
|
+
});
|
|
72
|
+
const DEFAULT_RENEW_BEFORE = "30 days";
|
|
73
|
+
const renewalDue = (notAfter, renewBefore, now) => Date.parse(notAfter) - now < Duration.toMillis(renewBefore ?? DEFAULT_RENEW_BEFORE);
|
|
74
|
+
export const CertificateProvider = () => Provider.succeed(Certificate, {
|
|
75
|
+
stables: ["directoryUrl"],
|
|
76
|
+
diff: Effect.fn(function* ({ news, olds, output }) {
|
|
77
|
+
if (news === undefined || !isResolved(news) || output === undefined) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
const account = accountOf(news.account);
|
|
81
|
+
if (account.accountUrl !== output.accountUrl) {
|
|
82
|
+
return { action: "replace" };
|
|
83
|
+
}
|
|
84
|
+
const now = yield* Effect.sync(() => Date.now());
|
|
85
|
+
const reissue = !arrayEqualsUnordered(news.identifiers, output.identifiers) ||
|
|
86
|
+
(news.keyAlgorithm ?? "ES256") !== output.keyAlgorithm ||
|
|
87
|
+
news.preferredChain !== olds?.preferredChain ||
|
|
88
|
+
renewalDue(output.notAfter, news.renewBefore, now);
|
|
89
|
+
return reissue ? { action: "update" } : undefined;
|
|
90
|
+
}),
|
|
91
|
+
read: Effect.fn(function* ({ output }) {
|
|
92
|
+
return output;
|
|
93
|
+
}),
|
|
94
|
+
reconcile: Effect.fn(function* ({ news, olds, output }) {
|
|
95
|
+
const account = accountOf(news.account);
|
|
96
|
+
const keyAlgorithm = news.keyAlgorithm ?? "ES256";
|
|
97
|
+
const now = yield* Effect.sync(() => Date.now());
|
|
98
|
+
// Observe: the stored certificate is authoritative — nothing to do
|
|
99
|
+
// while it covers the names and isn't due.
|
|
100
|
+
if (output !== undefined &&
|
|
101
|
+
output.accountUrl === account.accountUrl &&
|
|
102
|
+
arrayEqualsUnordered(news.identifiers, output.identifiers) &&
|
|
103
|
+
output.keyAlgorithm === keyAlgorithm &&
|
|
104
|
+
news.preferredChain === olds?.preferredChain &&
|
|
105
|
+
!renewalDue(output.notAfter, news.renewBefore, now)) {
|
|
106
|
+
return {
|
|
107
|
+
...output,
|
|
108
|
+
directoryUrl: account.directoryUrl,
|
|
109
|
+
trustedRoot: account.trustedRoot,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const solver = yield* resolveDnsSolver(news.solver);
|
|
113
|
+
const issued = yield* issueCertificate({
|
|
114
|
+
identifiers: news.identifiers,
|
|
115
|
+
solver,
|
|
116
|
+
keyAlgorithm,
|
|
117
|
+
preferredChain: news.preferredChain,
|
|
118
|
+
propagation: news.propagation,
|
|
119
|
+
}).pipe(Effect.provide(accountLayer(credentialsOf(account))));
|
|
120
|
+
return {
|
|
121
|
+
certificate: issued.certificate,
|
|
122
|
+
chain: issued.chain,
|
|
123
|
+
privateKey: issued.privateKey,
|
|
124
|
+
serial: issued.serial,
|
|
125
|
+
notBefore: issued.notBefore,
|
|
126
|
+
notAfter: issued.notAfter,
|
|
127
|
+
issuer: issued.issuer,
|
|
128
|
+
identifiers: [...news.identifiers],
|
|
129
|
+
certificateUrl: issued.certificateUrl,
|
|
130
|
+
orderUrl: issued.orderUrl,
|
|
131
|
+
keyAlgorithm,
|
|
132
|
+
accountUrl: account.accountUrl,
|
|
133
|
+
directoryUrl: account.directoryUrl,
|
|
134
|
+
trustedRoot: account.trustedRoot,
|
|
135
|
+
};
|
|
136
|
+
}),
|
|
137
|
+
delete: Effect.fn(function* ({ olds, output }) {
|
|
138
|
+
if (olds.revokeOnDelete !== true)
|
|
139
|
+
return;
|
|
140
|
+
const account = accountOf(olds.account);
|
|
141
|
+
// Signed with the certificate's own key, so revocation works even
|
|
142
|
+
// after the account was replaced or deactivated.
|
|
143
|
+
yield* revokeCertificate({
|
|
144
|
+
certificate: output.certificate,
|
|
145
|
+
privateKey: output.privateKey,
|
|
146
|
+
reason: "cessationOfOperation",
|
|
147
|
+
}).pipe(Effect.provide(accountLayer({
|
|
148
|
+
ca: {
|
|
149
|
+
directoryUrl: output.directoryUrl,
|
|
150
|
+
trustedRoot: output.trustedRoot,
|
|
151
|
+
},
|
|
152
|
+
accountKey: account.privateKey,
|
|
153
|
+
accountUrl: account.accountUrl,
|
|
154
|
+
})));
|
|
155
|
+
}),
|
|
156
|
+
});
|
|
157
|
+
//# sourceMappingURL=Certificate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Certificate.js","sourceRoot":"","sources":["../src/Certificate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,GAElB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,gBAAgB,EAA4B,MAAM,gBAAgB,CAAC;AAkF5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAc,kBAAkB,CAAC,CAAC;AASrE,qEAAqE;AACrE,MAAM,SAAS,GAAG,CAAC,KAAc,EAAc,EAAE,CAAC,KAAmB,CAAC;AAEtE,MAAM,aAAa,GAAG,CAAC,OAAmB,EAAsB,EAAE,CAAC,CAAC;IAClE,EAAE,EAAE,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE;IAC5E,UAAU,EAAE,OAAO,CAAC,UAAU;IAC9B,UAAU,EAAE,OAAO,CAAC,UAAU;CAC/B,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAmB,SAAS,CAAC;AAEvD,MAAM,UAAU,GAAG,CACjB,QAAgB,EAChB,WAAuC,EACvC,GAAW,EACF,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,WAAW,IAAI,oBAAoB,CAAC,CAAC;AAElG,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,EAAE,CACtC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE;IAC5B,OAAO,EAAE,CAAC,cAAc,CAAC;IAEzB,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE;QAC/C,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACpE,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,OAAO,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC;YAC7C,OAAO,EAAE,MAAM,EAAE,SAAkB,EAAE,CAAC;QACxC,CAAC;QACD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACjD,MAAM,OAAO,GACX,CAAC,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;YAC3D,CAAC,IAAI,CAAC,YAAY,IAAI,OAAO,CAAC,KAAK,MAAM,CAAC,YAAY;YACtD,IAAI,CAAC,cAAc,KAAK,IAAI,EAAE,cAAc;YAC5C,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QACrD,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAiB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7D,CAAC,CAAC;IAEF,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE;QACnC,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE;QACpD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,OAAO,CAAC;QAClD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACjD,mEAAmE;QACnE,2CAA2C;QAC3C,IACE,MAAM,KAAK,SAAS;YACpB,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC,UAAU;YACxC,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;YAC1D,MAAM,CAAC,YAAY,KAAK,YAAY;YACpC,IAAI,CAAC,cAAc,KAAK,IAAI,EAAE,cAAc;YAC5C,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,EACnD,CAAC;YACD,OAAO;gBACL,GAAG,MAAM;gBACT,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,WAAW,EAAE,OAAO,CAAC,WAAW;aACjC,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,gBAAgB,CAAC;YACrC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,MAAM;YACN,YAAY;YACZ,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,OAAO;YACL,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,WAAW,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC;YAClC,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,YAAY;YACZ,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QAC3C,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI;YAAE,OAAO;QACzC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxC,kEAAkE;QAClE,iDAAiD;QACjD,KAAK,CAAC,CAAC,iBAAiB,CAAC;YACvB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,MAAM,EAAE,sBAAsB;SAC/B,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,OAAO,CACZ,YAAY,CAAC;YACX,EAAE,EAAE;gBACF,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,WAAW,EAAE,MAAM,CAAC,WAAW;aAChC;YACD,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC,CACH,CACF,CAAC;IACJ,CAAC,CAAC;CACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An ACME certificate authority: its directory URL plus, for private CAs
|
|
3
|
+
* (Pebble, step-ca), the PEM root that signs the CA's own HTTPS endpoint.
|
|
4
|
+
*/
|
|
5
|
+
export interface CertificateAuthority {
|
|
6
|
+
/** The CA's ACME directory URL. */
|
|
7
|
+
readonly directoryUrl: string;
|
|
8
|
+
/**
|
|
9
|
+
* PEM root certificate to trust for the CA's HTTPS endpoint. Only for
|
|
10
|
+
* private CAs whose API certificate is not publicly trusted; public CAs
|
|
11
|
+
* leave it unset.
|
|
12
|
+
*/
|
|
13
|
+
readonly trustedRoot?: string | undefined;
|
|
14
|
+
}
|
|
15
|
+
/** Let's Encrypt production. No External Account Binding. */
|
|
16
|
+
export declare const LetsEncrypt: CertificateAuthority;
|
|
17
|
+
/** Let's Encrypt staging: generous limits, untrusted chain. */
|
|
18
|
+
export declare const LetsEncryptStaging: CertificateAuthority;
|
|
19
|
+
/** ZeroSSL. Requires an External Account Binding (`eab`). */
|
|
20
|
+
export declare const ZeroSSL: CertificateAuthority;
|
|
21
|
+
/** Google Trust Services. Requires an External Account Binding (`eab`). */
|
|
22
|
+
export declare const GoogleTrustServices: CertificateAuthority;
|
|
23
|
+
/** Google Trust Services staging. */
|
|
24
|
+
export declare const GoogleTrustServicesStaging: CertificateAuthority;
|
|
25
|
+
//# sourceMappingURL=CertificateAuthority.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CertificateAuthority.d.ts","sourceRoot":"","sources":["../src/CertificateAuthority.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,mCAAmC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,6DAA6D;AAC7D,eAAO,MAAM,WAAW,EAAE,oBAEzB,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,EAAE,oBAEhC,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,OAAO,EAAE,oBAErB,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,mBAAmB,EAAE,oBAEjC,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,0BAA0B,EAAE,oBAExC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Directories } from "@distilled.cloud/acme";
|
|
2
|
+
/** Let's Encrypt production. No External Account Binding. */
|
|
3
|
+
export const LetsEncrypt = {
|
|
4
|
+
directoryUrl: Directories.LetsEncrypt,
|
|
5
|
+
};
|
|
6
|
+
/** Let's Encrypt staging: generous limits, untrusted chain. */
|
|
7
|
+
export const LetsEncryptStaging = {
|
|
8
|
+
directoryUrl: Directories.LetsEncryptStaging,
|
|
9
|
+
};
|
|
10
|
+
/** ZeroSSL. Requires an External Account Binding (`eab`). */
|
|
11
|
+
export const ZeroSSL = {
|
|
12
|
+
directoryUrl: Directories.ZeroSSL,
|
|
13
|
+
};
|
|
14
|
+
/** Google Trust Services. Requires an External Account Binding (`eab`). */
|
|
15
|
+
export const GoogleTrustServices = {
|
|
16
|
+
directoryUrl: Directories.GoogleTrustServices,
|
|
17
|
+
};
|
|
18
|
+
/** Google Trust Services staging. */
|
|
19
|
+
export const GoogleTrustServicesStaging = {
|
|
20
|
+
directoryUrl: Directories.GoogleTrustServicesStaging,
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=CertificateAuthority.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CertificateAuthority.js","sourceRoot":"","sources":["../src/CertificateAuthority.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAiBpD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,WAAW,GAAyB;IAC/C,YAAY,EAAE,WAAW,CAAC,WAAW;CACtC,CAAC;AAEF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,kBAAkB,GAAyB;IACtD,YAAY,EAAE,WAAW,CAAC,kBAAkB;CAC7C,CAAC;AAEF,6DAA6D;AAC7D,MAAM,CAAC,MAAM,OAAO,GAAyB;IAC3C,YAAY,EAAE,WAAW,CAAC,OAAO;CAClC,CAAC;AAEF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,mBAAmB,GAAyB;IACvD,YAAY,EAAE,WAAW,CAAC,mBAAmB;CAC9C,CAAC;AAEF,qCAAqC;AACrC,MAAM,CAAC,MAAM,0BAA0B,GAAyB;IAC9D,YAAY,EAAE,WAAW,CAAC,0BAA0B;CACrD,CAAC"}
|
package/lib/Client.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ACME issuance flow shared by the `Certificate` resource (deploy time)
|
|
3
|
+
* and the `IssueCertificate` binding (runtime):
|
|
4
|
+
*
|
|
5
|
+
* order → DNS-01 per authorization (present → propagated → respond →
|
|
6
|
+
* poll) → finalize with a fresh key's CSR → download → parse.
|
|
7
|
+
*
|
|
8
|
+
* The wire is `@distilled.cloud/acme`; this file only sequences it.
|
|
9
|
+
*/
|
|
10
|
+
import * as Acme from "@distilled.cloud/acme";
|
|
11
|
+
import * as acme from "@distilled.cloud/acme/acme";
|
|
12
|
+
import * as Effect from "effect/Effect";
|
|
13
|
+
import * as HttpClient from "effect/http/HttpClient";
|
|
14
|
+
import * as Layer from "effect/Layer";
|
|
15
|
+
import * as Redacted from "effect/Redacted";
|
|
16
|
+
import type { CertificateAuthority } from "./CertificateAuthority.ts";
|
|
17
|
+
import { type PropagationOptions } from "./Dns.ts";
|
|
18
|
+
import type { DnsSolver } from "./DnsSolver.ts";
|
|
19
|
+
import { ChallengeFailed, ChallengeUnsupported, OrderInvalid, OrderTimeout, PkiError, type DnsPropagationTimeout, type DnsSolverError } from "./Errors.ts";
|
|
20
|
+
import { type KeyAlgorithm } from "./Pki.ts";
|
|
21
|
+
/** Everything the flow needs to sign requests as an account. */
|
|
22
|
+
export interface AccountCredentials {
|
|
23
|
+
readonly ca: CertificateAuthority;
|
|
24
|
+
/** The account's private JWK (JSON). */
|
|
25
|
+
readonly accountKey: Redacted.Redacted<string>;
|
|
26
|
+
/** The account URL (`kid`), once the account exists. */
|
|
27
|
+
readonly accountUrl?: string | undefined;
|
|
28
|
+
readonly externalAccountBinding?: {
|
|
29
|
+
readonly keyId: string;
|
|
30
|
+
readonly hmacKey: Redacted.Redacted<string>;
|
|
31
|
+
} | undefined;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The SDK's `Credentials` (+ a CA-trusting `HttpClient` for private CAs)
|
|
35
|
+
* for one account. Provide around any `@distilled.cloud/acme` call.
|
|
36
|
+
*/
|
|
37
|
+
export declare const accountLayer: (credentials: AccountCredentials) => Layer.Layer<Acme.Credentials | HttpClient.HttpClient>;
|
|
38
|
+
export interface IssueRequest<R = never> {
|
|
39
|
+
/** DNS names; the first is the subject CN. Wildcards allowed. */
|
|
40
|
+
readonly identifiers: ReadonlyArray<string>;
|
|
41
|
+
readonly solver: DnsSolver<R>;
|
|
42
|
+
/** @default "ES256" */
|
|
43
|
+
readonly keyAlgorithm?: KeyAlgorithm | undefined;
|
|
44
|
+
/** Issuer name (`CN=...` substring) to prefer when the CA offers alternate chains. */
|
|
45
|
+
readonly preferredChain?: string | undefined;
|
|
46
|
+
readonly propagation?: PropagationOptions | undefined;
|
|
47
|
+
}
|
|
48
|
+
export interface IssuedCertificate {
|
|
49
|
+
/** Leaf certificate PEM. */
|
|
50
|
+
readonly certificate: string;
|
|
51
|
+
/** Full chain PEM, leaf first. */
|
|
52
|
+
readonly chain: string;
|
|
53
|
+
/** PKCS#8 private key PEM. */
|
|
54
|
+
readonly privateKey: Redacted.Redacted<string>;
|
|
55
|
+
readonly identifiers: ReadonlyArray<string>;
|
|
56
|
+
readonly serial: string;
|
|
57
|
+
/** ISO 8601. */
|
|
58
|
+
readonly notBefore: string;
|
|
59
|
+
/** ISO 8601. */
|
|
60
|
+
readonly notAfter: string;
|
|
61
|
+
readonly issuer: string;
|
|
62
|
+
/** The CA's certificate URL (for re-download and revocation bookkeeping). */
|
|
63
|
+
readonly certificateUrl: string;
|
|
64
|
+
readonly orderUrl: string;
|
|
65
|
+
}
|
|
66
|
+
export type IssueError = OrderInvalid | ChallengeFailed | ChallengeUnsupported | OrderTimeout | DnsPropagationTimeout | DnsSolverError | PkiError | Acme.JoseError | acme.NewOrderError | acme.GetAuthorizationError | acme.RespondChallengeError | acme.FinalizeOrderError | acme.GetOrderError | acme.DownloadCertificateError;
|
|
67
|
+
/**
|
|
68
|
+
* Issue a certificate for `identifiers` as the current `Credentials`
|
|
69
|
+
* account. Requires the SDK's `Credentials` and an `HttpClient` (see
|
|
70
|
+
* {@link accountLayer}) plus whatever the solver needs.
|
|
71
|
+
*/
|
|
72
|
+
export declare const issueCertificate: <R = never>(request: IssueRequest<R>) => Effect.Effect<IssuedCertificate, IssueError, Acme.Credentials | HttpClient.HttpClient | R>;
|
|
73
|
+
/** RFC 5280 revocation reasons. */
|
|
74
|
+
export type RevocationReason = "unspecified" | "keyCompromise" | "affiliationChanged" | "superseded" | "cessationOfOperation";
|
|
75
|
+
export interface RevokeRequest {
|
|
76
|
+
/** Leaf certificate PEM. */
|
|
77
|
+
readonly certificate: string;
|
|
78
|
+
/**
|
|
79
|
+
* The certificate's private key. When given, the request is signed with
|
|
80
|
+
* it (RFC 8555 §7.6) so no account is needed; otherwise the ambient
|
|
81
|
+
* account credentials sign.
|
|
82
|
+
*/
|
|
83
|
+
readonly privateKey?: Redacted.Redacted<string> | string | undefined;
|
|
84
|
+
readonly reason?: RevocationReason | undefined;
|
|
85
|
+
}
|
|
86
|
+
export type RevokeError = PkiError | acme.RevokeCertificateError;
|
|
87
|
+
/** Revoke a certificate. `AcmeAlreadyRevoked` is folded into success. */
|
|
88
|
+
export declare const revokeCertificate: (request: RevokeRequest) => Effect.Effect<void, RevokeError, Acme.Credentials | HttpClient.HttpClient>;
|
|
89
|
+
//# sourceMappingURL=Client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../src/Client.ts"],"names":[],"mappings":"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"}
|