Skip to content

Commit 5170c8f

Browse files
committed
chore(acme): minor refactors
1 parent 32281e0 commit 5170c8f

File tree

3 files changed

+36
-29
lines changed

3 files changed

+36
-29
lines changed

libp2p/autotls/acme/api.nim

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import chronos/apps/http/httpclient, jwt, results, bearssl/pem
55
import ./utils
66
import ../../crypto/crypto
77
import ../../crypto/rsa
8-
import ../../transports/tls/certificate_ffi
9-
import ../../transports/tls/certificate
108

119
const
1210
LetsEncryptURL* = "https://acme-v02.api.letsencrypt.org"
@@ -30,7 +28,7 @@ type ACMEDirectory = object
3028

3129
type ACMEApi* = object
3230
directory: ACMEDirectory
33-
session*: HttpSessionRef
31+
session: HttpSessionRef
3432
acmeServerURL: string
3533

3634
type JWK = object
@@ -113,6 +111,8 @@ template handleError(msg: string, body: untyped): untyped =
113111
raise newException(ACMEError, msg & ": Failed to decode JSON", exc)
114112
except HttpError as exc:
115113
raise newException(ACMEError, msg & ": Failed to connect to ACME server", exc)
114+
except CancelledError as exc:
115+
raise newException(CancelledError, msg & ": Future cancelled", exc)
116116
except CatchableError as exc:
117117
raise newException(ACMEError, msg & ": Unexpected error", exc)
118118

@@ -121,13 +121,12 @@ proc new*(
121121
): Future[ACMEApi] {.async: (raises: [ACMEError, CancelledError]).} =
122122
let session = HttpSessionRef.new()
123123
let directory = handleError("new API"):
124-
(
125-
await (
126-
await HttpClientRequestRef.get(session, acmeServerURL & "/directory").get().send()
127-
).getResponseBody()
128-
).to(ACMEDirectory)
124+
let rawResponse =
125+
await HttpClientRequestRef.get(session, acmeServerURL & "/directory").get().send()
126+
let body = await rawResponse.getResponseBody()
127+
body.to(ACMEDirectory)
129128

130-
return ACMEApi(session: session, directory: directory, acmeServerURL: acmeServerURL)
129+
ACMEApi(session: session, directory: directory, acmeServerURL: acmeServerURL)
131130

132131
proc newNonce(
133132
self: ACMEApi
@@ -245,14 +244,14 @@ proc requestChallenge*(
245244
finalizeURL: challengeResponse.finalize, orderURL: orderURL, dns01: dns01
246245
)
247246

248-
proc notifyChallengeCompleted*(
247+
proc challengeCompleted*(
249248
self: ACMEApi,
250249
chalURL: string,
251250
key: KeyPair,
252251
kid: Kid,
253252
retries: int = DefaultChalCompletedRetries,
254253
): Future[void] {.async: (raises: [ACMEError, CancelledError]).} =
255-
let completedResponse = handleError("notifyChallengeCompleted (send notify)"):
254+
let completedResponse = handleError("challengeCompleted (send notify)"):
256255
let payload =
257256
await self.createSignedAcmeRequest(chalURL, %*{}, key, kid = Opt.some(kid))
258257
let rawResponse = await HttpClientRequestRef
@@ -265,7 +264,7 @@ proc notifyChallengeCompleted*(
265264
# check until acme server is done (poll validation)
266265
for i in 0 .. retries:
267266
let (retryAfterHeader, checkResponse) = handleError(
268-
"notifyChallengeCompleted (check " & $i & ")"
267+
"challengeCompleted (check " & $i & ")"
269268
):
270269
let rawResponse = await HttpClientRequestRef
271270
.get(self.session, completedResponse.checkURL)
@@ -300,21 +299,7 @@ proc finalizeCertificate*(
300299
kid: Kid,
301300
retries: int = DefaultFinalizeRetries,
302301
): Future[bool] {.async: (raises: [ACMEError, CancelledError]).} =
303-
var certKey: cert_key_t
304-
var certCtx: cert_context_t
305-
var derCSR: ptr cert_buffer = nil
306-
307-
let personalizationStr = "libp2p_autotls"
308-
if cert_init_drbg(
309-
personalizationStr.cstring, personalizationStr.len.csize_t, certCtx.addr
310-
) != CERT_SUCCESS:
311-
raise newException(ACMEError, "Failed to initialize certCtx")
312-
if cert_generate_key(certCtx, certKey.addr) != CERT_SUCCESS:
313-
raise newException(ACMEError, "Failed to generate cert key")
314-
315-
if cert_signing_req(domain.cstring, certKey, derCSR.addr) != CERT_SUCCESS:
316-
raise newException(ACMEError, "Failed to create CSR")
317-
302+
let derCSR = createCSR(domain)
318303
let b64CSR = base64.encode(derCSR.toSeq, safe = true)
319304

320305
# call finalize and keep checking order until cert is valid (done)
@@ -373,3 +358,6 @@ proc downloadCertificate*(
373358
ACMECertificateResponse(
374359
rawCertificate: bytesToString(rawBody), certificateExpiry: certificateExpiry
375360
)
361+
362+
proc close*(self: ACMEApi): Future[void] {.async: (raises: [CancelledError]).} =
363+
await self.session.closeWait()

libp2p/autotls/acme/utils.nim

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import base64, strutils, chronos/apps/http/httpclient, json
22
import ../../errors
3+
import ../../transports/tls/certificate_ffi
34

45
type ACMEError* = object of LPError
56

@@ -12,13 +13,31 @@ proc base64UrlEncode*(data: seq[byte]): string =
1213

1314
proc getResponseBody*(
1415
response: HttpClientResponseRef
15-
): Future[JsonNode] {.async: (raises: [ACMEError]).} =
16+
): Future[JsonNode] {.async: (raises: [ACMEError, CancelledError]).} =
1617
try:
1718
let responseBody = bytesToString(await response.getBodyBytes()).parseJson()
1819
return responseBody
20+
except CancelledError as exc:
21+
raise newException(CancelledError, "Future cancelled", exc)
1922
except CatchableError as exc:
2023
raise
2124
newException(ACMEError, "Unexpected error occurred while getting body bytes", exc)
2225
except Exception as exc: # this is required for nim 1.6
2326
raise
2427
newException(ACMEError, "Unexpected error occurred while getting body bytes", exc)
28+
29+
proc createCSR*(domain: string): string {.raises: [ACMEError].} =
30+
var certKey: cert_key_t
31+
var certCtx: cert_context_t
32+
var derCSR: ptr cert_buffer = nil
33+
34+
let personalizationStr = "libp2p_autotls"
35+
if cert_init_drbg(
36+
personalizationStr.cstring, personalizationStr.len.csize_t, certCtx.addr
37+
) != CERT_SUCCESS:
38+
raise newException(ACMEError, "Failed to initialize certCtx")
39+
if cert_generate_key(certCtx, certKey.addr) != CERT_SUCCESS:
40+
raise newException(ACMEError, "Failed to generate cert key")
41+
42+
if cert_signing_req(domain.cstring, certKey, derCSR.addr) != CERT_SUCCESS:
43+
raise newException(ACMEError, "Failed to create CSR")

tests/testautotls.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ suite "AutoTLS":
2525
asyncTest "test ACME":
2626
let api = await ACMEApi.new(acmeServerURL = LetsEncryptURLStaging)
2727
defer:
28-
await api.session.closeWait()
28+
await api.close()
2929
let key = KeyPair.random(PKScheme.RSA, newRng()[]).get()
3030
let registerResponse = await api.acmeRegister(key)
3131
# account was registered (kid set)

0 commit comments

Comments
 (0)