Current section
Files
Jump to
Current section
Files
src/acumen@revoke_certificate.erl
-module(acumen@revoke_certificate).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/acumen/revoke_certificate.gleam").
-export([build/3, build_with_certificate_key/3, reason/2, request/1, response/1]).
-export_type([request_builder/0, revocation_reason/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Revoke certificates issued through ACME.\n"
"\n"
" Once revoked, a certificate appears on Certificate Revocation Lists (CRLs).\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import acumen\n"
" import acumen/revoke_certificate\n"
"\n"
" // Build the revocation request with the DER-encoded certificate\n"
" let rev = revoke_certificate.request(cert_der_bytes)\n"
" |> revoke_certificate.reason(revoke_certificate.KeyCompromise)\n"
"\n"
" // Execute the request\n"
" let assert Ok(#(resp, ctx)) = acumen.execute(\n"
" ctx,\n"
" build: revoke_certificate.build(rev, _, registered_key),\n"
" send: httpc.send,\n"
" )\n"
"\n"
" // Parse the response\n"
" let assert Ok(Nil) = revoke_certificate.response(resp)\n"
" ```\n"
).
-opaque request_builder() :: {request_builder,
bitstring(),
gleam@option:option(revocation_reason())}.
-type revocation_reason() :: unspecified |
key_compromise |
ca_compromise |
affiliation_changed |
superseded |
cessation_of_operation |
certificate_hold |
remove_from_crl |
privilege_withdrawn |
aa_compromise.
-file("src/acumen/revoke_certificate.gleam", 109).
-spec reason_to_code(revocation_reason()) -> integer().
reason_to_code(Revocation_reason) ->
case Revocation_reason of
unspecified ->
0;
key_compromise ->
1;
ca_compromise ->
2;
affiliation_changed ->
3;
superseded ->
4;
cessation_of_operation ->
5;
certificate_hold ->
6;
remove_from_crl ->
8;
privilege_withdrawn ->
9;
aa_compromise ->
10
end.
-file("src/acumen/revoke_certificate.gleam", 94).
-spec build_payload(request_builder()) -> gleam@json:json().
build_payload(Builder) ->
Encoded = gleam@bit_array:base64_url_encode(
erlang:element(2, Builder),
false
),
Fields = [{<<"certificate"/utf8>>, gleam@json:string(Encoded)}],
Fields@1 = case erlang:element(3, Builder) of
{some, Revocation_reason} ->
[{<<"reason"/utf8>>,
gleam@json:int(reason_to_code(Revocation_reason))} |
Fields];
none ->
Fields
end,
gleam@json:object(Fields@1).
-file("src/acumen/revoke_certificate.gleam", 76).
?DOC(" Builds a signed revocation request to the `revokeCert` endpoint.\n").
-spec build(request_builder(), acumen:context(), acumen:registered_key()) -> {ok,
gleam@http@request:request(binary())} |
{error, acumen:acme_error()}.
build(Builder, Context, Key) ->
_pipe = build_payload(Builder),
_pipe@1 = gleam@json:to_string(_pipe),
_pipe@2 = acumen@internal@jws:sign_with_kid(
erlang:element(2, Key),
erlang:element(3, Key),
_pipe@1,
erlang:element(3, Context),
erlang:element(5, erlang:element(2, Context))
),
_pipe@3 = gleam@result:map_error(
_pipe@2,
fun(Field@0) -> {jws_error, Field@0} end
),
gleam@result:'try'(
_pipe@3,
fun(_capture) ->
acumen:build_post_request(
erlang:element(5, erlang:element(2, Context)),
_capture
)
end
).
-file("src/acumen/revoke_certificate.gleam", 152).
?DOC(
" Signs the revocation request with the certificate's private key instead\n"
" of the account key. Useful when account access is unavailable, such as\n"
" during incident response.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import acumen\n"
" import acumen/revoke_certificate\n"
" import gose/key\n"
"\n"
" let assert Ok(cert_private_key) = key.from_pem(cert_key_pem)\n"
"\n"
" let req = revoke_certificate.request(cert_der_bytes)\n"
" |> revoke_certificate.reason(revoke_certificate.KeyCompromise)\n"
"\n"
" let assert Ok(#(resp, ctx)) = acumen.execute(\n"
" ctx,\n"
" build: revoke_certificate.build_with_certificate_key(\n"
" req,\n"
" _,\n"
" key: cert_private_key,\n"
" ),\n"
" send: httpc.send,\n"
" )\n"
"\n"
" let assert Ok(Nil) = revoke_certificate.response(resp)\n"
" ```\n"
).
-spec build_with_certificate_key(
request_builder(),
acumen:context(),
gose:key(binary())
) -> {ok, gleam@http@request:request(binary())} | {error, acumen:acme_error()}.
build_with_certificate_key(Builder, Context, Key) ->
_pipe = build_payload(Builder),
_pipe@1 = gleam@json:to_string(_pipe),
_pipe@2 = acumen@internal@jws:sign_with_jwk(
Key,
_pipe@1,
erlang:element(3, Context),
erlang:element(5, erlang:element(2, Context))
),
_pipe@3 = gleam@result:map_error(
_pipe@2,
fun(Field@0) -> {jws_error, Field@0} end
),
gleam@result:'try'(
_pipe@3,
fun(_capture) ->
acumen:build_post_request(
erlang:element(5, erlang:element(2, Context)),
_capture
)
end
).
-file("src/acumen/revoke_certificate.gleam", 170).
?DOC(" Sets the revocation reason. Optional but recommended.\n").
-spec reason(request_builder(), revocation_reason()) -> request_builder().
reason(Builder, Revocation_reason) ->
{request_builder, erlang:element(2, Builder), {some, Revocation_reason}}.
-file("src/acumen/revoke_certificate.gleam", 178).
?DOC(" Creates a new revocation request builder with the given DER-encoded certificate.\n").
-spec request(bitstring()) -> request_builder().
request(Certificate_der) ->
{request_builder, Certificate_der, none}.
-file("src/acumen/revoke_certificate.gleam", 183).
?DOC(" Parses the revocation response. Empty body on success.\n").
-spec response(gleam@http@response:response(binary())) -> {ok, nil} |
{error, acumen:acme_error()}.
response(Resp) ->
case erlang:element(2, Resp) of
200 ->
{ok, nil};
_ ->
{error,
{invalid_response,
acumen@internal@utils:unexpected_status_message(
erlang:element(2, Resp)
)}}
end.