Class AcmeClientSpi
- java.lang.Object
-
- org.wildfly.security.x500.cert.acme.AcmeClientSpi
-
public abstract class AcmeClientSpi extends Object
SPI for an Automatic Certificate Management Environment (ACME) client provider to implement.- Since:
- 1.5.0
- Author:
- Farah Juma
-
-
Field Summary
Fields Modifier and Type Field Description private static String
CHARSET
private static int[]
CONTENT_TYPE_DELIMS
static int
DEFAULT_EC_KEY_SIZE
The default key size that will be used if the key algorithm name is EC.static String
DEFAULT_KEY_ALGORITHM_NAME
The default key algorithm name.static int
DEFAULT_KEY_SIZE
The default key size that will be used if the key algorithm name is not EC.private static long
DEFAULT_RETRY_AFTER_MILLI
private static jakarta.json.JsonObject
EMPTY_PAYLOAD
private static String
EMPTY_STRING
private static int
MAX_RETRIES
private static String
USER_AGENT_STRING
private static String
UTF_8
-
Constructor Summary
Constructors Constructor Description AcmeClientSpi()
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description void
changeAccountKey(AcmeAccount account, boolean staging)
Change the key that is associated with the given ACME account.void
changeAccountKey(AcmeAccount account, boolean staging, X509Certificate certificate, PrivateKey privateKey)
Change the key that is associated with the given ACME account.private static boolean
checkContentType(HttpURLConnection connection, String expectedMediaType)
abstract void
cleanupAfterChallenge(AcmeAccount account, AcmeChallenge challenge)
Undo the actions that were taken to prove control of the identifier associated with the given challenge.boolean
createAccount(AcmeAccount account, boolean staging)
Create an account with an ACME server using the given account information.boolean
createAccount(AcmeAccount account, boolean staging, boolean onlyReturnExisting)
Create an account with an ACME server using the given account information.String
createAuthorization(AcmeAccount account, boolean staging, String domainName)
Create an authorization for the given identifier.void
deactivateAccount(AcmeAccount account, boolean staging)
Deactivate the given ACME account.void
deactivateAuthorization(AcmeAccount account, boolean staging, String authorizationUrl)
Deactivate an authorization.private String
getAccountUrl(AcmeAccount account, boolean staging)
private static InputStream
getConvertedInputStream(InputStream inputStream)
private static LinkedHashSet<String>
getDomainNames(String[] domainNames)
private static int
getECSignatureByteLength(String signatureAlgorithm)
private static String
getEncodedJson(jakarta.json.JsonObject jsonObject)
private String
getEncodedProtectedHeader(boolean useJwk, String resourceUrl, AcmeAccount account, boolean staging)
private static String
getEncodedProtectedHeader(String algHeader, PublicKey publicKey, String resourceUrl)
private static String
getEncodedSignature(PrivateKey privateKey, String signatureAlgorithm, String encodedProtectedHeader, String encodedPayload)
private static String
getEncodedSignature(PrivateKey privateKey, Signature signature, String encodedProtectedHeader, String encodedPayload)
private static jakarta.json.JsonObject
getJsonResponse(HttpURLConnection connection)
private static jakarta.json.JsonObject
getJws(String encodedProtectedHeader, String encodedPayload, String encodedSignature)
private static String
getLocation(HttpURLConnection connection, String urlType)
AcmeMetadata
getMetadata(AcmeAccount account, boolean staging)
Get the metadata associated with the ACME server.byte[]
getNewNonce(AcmeAccount account, boolean staging)
Get a new nonce for the given account from the ACME server.private byte[]
getNonce(AcmeAccount account, boolean staging)
private static String
getOptionalJsonString(jakarta.json.JsonObject jsonObject, String name)
private static X509Certificate[]
getPemCertificateChain(HttpURLConnection connection)
private static String
getProblemMessage(jakarta.json.JsonObject jsonResponse)
private static String
getProblemMessages(jakarta.json.JsonObject errorResponse)
private static byte[]
getReplayNonce(HttpURLConnection connection)
private URL
getResourceUrl(AcmeAccount account, AcmeResource resource, boolean staging)
Map<AcmeResource,URL>
getResourceUrls(AcmeAccount account, boolean staging)
Get the resource URLs needed to perform operations from the ACME server.private static long
getRetryAfter(HttpURLConnection connection, boolean useDefaultIfHeaderNotPresent)
private static String
getSanitizedDomainName(String domainName)
private static void
handleAcmeErrorResponse(HttpURLConnection connection, int responseCode)
private static boolean
isDelim(int c, int... delims)
X509CertificateChainAndSigningKey
obtainCertificateChain(AcmeAccount account, boolean staging, String... domainNames)
Obtain a certificate chain using the given ACME account.X509CertificateChainAndSigningKey
obtainCertificateChain(AcmeAccount account, boolean staging, String keyAlgorithmName, int keySize, String... domainNames)
Obtain a certificate chain using the given ACME account.private jakarta.json.JsonObject
pollResourceUntilFinalized(AcmeAccount account, boolean staging, String resourceUrl)
abstract AcmeChallenge
proveIdentifierControl(AcmeAccount account, List<AcmeChallenge> challenges)
Prove control of the identifier associated with the given list of challenges.(package private) String[]
queryAccountContactUrls(AcmeAccount account, boolean staging)
(package private) String
queryAccountStatus(AcmeAccount account, boolean staging)
private AcmeChallenge
respondToChallenges(AcmeAccount account, boolean staging, jakarta.json.JsonObject authorization)
void
revokeCertificate(AcmeAccount account, boolean staging, X509Certificate certificate)
Revoke the given certificate.void
revokeCertificate(AcmeAccount account, boolean staging, X509Certificate certificate, CRLReason reason)
Revoke the given certificate.private HttpURLConnection
sendGetRequest(String resourceUrl, int expectedResponseCode, String expectedContentType)
private HttpURLConnection
sendPostAsGetRequest(AcmeAccount account, boolean staging, String resourceUrl, String expectedContentType, int... expectedResponseCodes)
private HttpURLConnection
sendPostRequestWithRetries(AcmeAccount account, boolean staging, String resourceUrl, boolean useJwk, String encodedPayload, int... expectedResponseCodes)
private HttpURLConnection
sendPostRequestWithRetries(AcmeAccount account, boolean staging, String resourceUrl, boolean useJwk, String encodedPayload, String expectedContentType, int... expectedResponseCodes)
private static void
skipDelims(org.wildfly.common.iteration.CodePointIterator di, org.wildfly.common.iteration.CodePointIterator cpi, int... delims)
void
updateAccount(AcmeAccount account, boolean staging, boolean termsOfServiceAgreed)
Update whether or not the terms of service have been agreed to for an account with an ACME server.void
updateAccount(AcmeAccount account, boolean staging, boolean termsOfServiceAgreed, String[] contactUrls)
Update an account with an ACME server using the given account information.void
updateAccount(AcmeAccount account, boolean staging, String[] contactUrls)
Update the contact URLs for an account with an ACME server.
-
-
-
Field Detail
-
DEFAULT_EC_KEY_SIZE
public static final int DEFAULT_EC_KEY_SIZE
The default key size that will be used if the key algorithm name is EC.- See Also:
- Constant Field Values
-
DEFAULT_KEY_SIZE
public static final int DEFAULT_KEY_SIZE
The default key size that will be used if the key algorithm name is not EC.- See Also:
- Constant Field Values
-
DEFAULT_KEY_ALGORITHM_NAME
public static final String DEFAULT_KEY_ALGORITHM_NAME
The default key algorithm name.- See Also:
- Constant Field Values
-
MAX_RETRIES
private static final int MAX_RETRIES
- See Also:
- Constant Field Values
-
DEFAULT_RETRY_AFTER_MILLI
private static final long DEFAULT_RETRY_AFTER_MILLI
- See Also:
- Constant Field Values
-
CONTENT_TYPE_DELIMS
private static final int[] CONTENT_TYPE_DELIMS
-
CHARSET
private static final String CHARSET
- See Also:
- Constant Field Values
-
UTF_8
private static final String UTF_8
- See Also:
- Constant Field Values
-
USER_AGENT_STRING
private static final String USER_AGENT_STRING
-
EMPTY_PAYLOAD
private static final jakarta.json.JsonObject EMPTY_PAYLOAD
-
EMPTY_STRING
private static final String EMPTY_STRING
- See Also:
- Constant Field Values
-
-
Method Detail
-
getResourceUrls
public Map<AcmeResource,URL> getResourceUrls(AcmeAccount account, boolean staging) throws AcmeException
Get the resource URLs needed to perform operations from the ACME server.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be used- Returns:
- a map of ACME resources to URLs
- Throws:
AcmeException
- if an error occurs while attempting to get the resource URLs from the ACME server
-
getMetadata
public AcmeMetadata getMetadata(AcmeAccount account, boolean staging) throws AcmeException
Get the metadata associated with the ACME server.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be used- Returns:
- the metadata associated with the ACME server (may be
null
) - Throws:
AcmeException
- if an error occurs while attempting to get the metadata associated with the ACME server
-
createAccount
public boolean createAccount(AcmeAccount account, boolean staging) throws AcmeException
Create an account with an ACME server using the given account information.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be used- Returns:
true
if the account was created,false
if the account already existed- Throws:
AcmeException
- if an error occurs while attempting to create or lookup an account with the ACME server
-
createAccount
public boolean createAccount(AcmeAccount account, boolean staging, boolean onlyReturnExisting) throws AcmeException
Create an account with an ACME server using the given account information.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be usedonlyReturnExisting
-true
if the ACME server should not create a new account if one does not already exist (this allows an existing account's URL to be looked up and populated using the account key)- Returns:
true
if the account was created,false
if the account already existed- Throws:
AcmeException
- if an error occurs while attempting to create or lookup an account with the ACME server or ifonlyReturnExisting
is set totrue
and the account does not exist
-
updateAccount
public void updateAccount(AcmeAccount account, boolean staging, boolean termsOfServiceAgreed) throws AcmeException
Update whether or not the terms of service have been agreed to for an account with an ACME server.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be usedtermsOfServiceAgreed
- the new value for whether or not the terms of service have been agreed to- Throws:
AcmeException
- if an error occurs while attempting to update the account
-
updateAccount
public void updateAccount(AcmeAccount account, boolean staging, String[] contactUrls) throws AcmeException
Update the contact URLs for an account with an ACME server.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be usedcontactUrls
- the new account contact URLs- Throws:
AcmeException
- if an error occurs while attempting to update the account
-
updateAccount
public void updateAccount(AcmeAccount account, boolean staging, boolean termsOfServiceAgreed, String[] contactUrls) throws AcmeException
Update an account with an ACME server using the given account information.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be usedtermsOfServiceAgreed
- the new value for whether or not the terms of service have been agreed tocontactUrls
- the new account contact URLs- Throws:
AcmeException
- if an error occurs while attempting to update the account
-
changeAccountKey
public void changeAccountKey(AcmeAccount account, boolean staging) throws AcmeException
Change the key that is associated with the given ACME account.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be used- Throws:
AcmeException
- if an error occurs while attempting to change the key that is associated with the given ACME account
-
changeAccountKey
public void changeAccountKey(AcmeAccount account, boolean staging, X509Certificate certificate, PrivateKey privateKey) throws AcmeException
Change the key that is associated with the given ACME account.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be usedcertificate
- the new certificate to associate with the given ACME account (must not benull
)privateKey
- the new private key to associate with the given ACME account (must not benull
)- Throws:
AcmeException
- if an error occurs while attempting to change the key that is associated with the given ACME account
-
deactivateAccount
public void deactivateAccount(AcmeAccount account, boolean staging) throws AcmeException
Deactivate the given ACME account. It is not possible to reactivate an ACME account after it has been deactivated.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be used- Throws:
AcmeException
- if an error occurs while attempting to deactivate the given ACME account
-
obtainCertificateChain
public X509CertificateChainAndSigningKey obtainCertificateChain(AcmeAccount account, boolean staging, String... domainNames) throws AcmeException
Obtain a certificate chain using the given ACME account.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be useddomainNames
- the domain names to request the certificate for (must not benull
)- Returns:
- the X509 certificate chain and private key
- Throws:
AcmeException
- if an occur occurs while attempting to obtain the certificate
-
obtainCertificateChain
public X509CertificateChainAndSigningKey obtainCertificateChain(AcmeAccount account, boolean staging, String keyAlgorithmName, int keySize, String... domainNames) throws AcmeException
Obtain a certificate chain using the given ACME account.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be usedkeyAlgorithmName
- the optional key algorithm name to use when generating the key pair (may benull
)keySize
- the optional key size to use when generating the key pair (-1 to indicate that the default key size should be used)domainNames
- the domain names to request the certificate for (must not benull
)- Returns:
- the X509 certificate chain and private key
- Throws:
AcmeException
- if an occur occurs while attempting to obtain the certificate
-
createAuthorization
public String createAuthorization(AcmeAccount account, boolean staging, String domainName) throws AcmeException
Create an authorization for the given identifier.This method allows an ACME client to obtain authorization for an identifier proactively before attempting to obtain a certificate.
- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be useddomainName
- the domain name to create an authorization for (must not benull
)- Returns:
- the authorization URL corresponding to the given identifier
- Throws:
AcmeException
- if an error occurs while attempting to create an authorization for the given identifier
-
deactivateAuthorization
public void deactivateAuthorization(AcmeAccount account, boolean staging, String authorizationUrl) throws AcmeException
Deactivate an authorization.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be usedauthorizationUrl
- the authorization url (must not benull
)- Throws:
AcmeException
- if an error occurs while attempting to deactivate an authorization for the given identifier
-
proveIdentifierControl
public abstract AcmeChallenge proveIdentifierControl(AcmeAccount account, List<AcmeChallenge> challenges) throws AcmeException
Prove control of the identifier associated with the given list of challenges.This method should select one challenge from the given list of challenges from the ACME server to prove control of the identifier associated with the challenges as specified by the ACME v2 protocol.
- Parameters:
account
- the ACME account information to use (must not benull
)challenges
- the list of challenges from the ACME server (must not benull
)- Returns:
- the challenge that was selected and used to prove control of the identifier
- Throws:
AcmeException
- if an error occurs while attempting to provide control of the identifier associated with the challenges or if none of the challenge types are supported by this client
-
cleanupAfterChallenge
public abstract void cleanupAfterChallenge(AcmeAccount account, AcmeChallenge challenge) throws AcmeException
Undo the actions that were taken to prove control of the identifier associated with the given challenge.- Parameters:
account
- the ACME account information to use (must not benull
)challenge
- the challenge (must not benull
)- Throws:
AcmeException
- if an error occurs while attempting to undo the actions that were taken to prove control of the identifier associated with the given challenge
-
revokeCertificate
public void revokeCertificate(AcmeAccount account, boolean staging, X509Certificate certificate) throws AcmeException
Revoke the given certificate.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be usedcertificate
- the certificate to be revoked (must not benull
)- Throws:
AcmeException
- if an error occurs while attempting to revoke the given certificate
-
revokeCertificate
public void revokeCertificate(AcmeAccount account, boolean staging, X509Certificate certificate, CRLReason reason) throws AcmeException
Revoke the given certificate.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be usedcertificate
- the certificate to be revoked (must not benull
)reason
- the optional reason why the certificate is being revoked (may benull
)- Throws:
AcmeException
- if an error occurs while attempting to revoke the given certificate
-
getNewNonce
public byte[] getNewNonce(AcmeAccount account, boolean staging) throws AcmeException
Get a new nonce for the given account from the ACME server.- Parameters:
account
- the ACME account information to use (must not benull
)staging
- whether or not the staging server URL should be used- Returns:
- nonce the new nonce for the given account
- Throws:
AcmeException
- if an error occurs while attempting to get the new nonce from the ACME server
-
queryAccountContactUrls
String[] queryAccountContactUrls(AcmeAccount account, boolean staging) throws AcmeException
- Throws:
AcmeException
-
queryAccountStatus
String queryAccountStatus(AcmeAccount account, boolean staging) throws AcmeException
- Throws:
AcmeException
-
getResourceUrl
private URL getResourceUrl(AcmeAccount account, AcmeResource resource, boolean staging) throws AcmeException
- Throws:
AcmeException
-
sendGetRequest
private HttpURLConnection sendGetRequest(String resourceUrl, int expectedResponseCode, String expectedContentType) throws AcmeException
- Throws:
AcmeException
-
sendPostAsGetRequest
private HttpURLConnection sendPostAsGetRequest(AcmeAccount account, boolean staging, String resourceUrl, String expectedContentType, int... expectedResponseCodes) throws AcmeException
- Throws:
AcmeException
-
sendPostRequestWithRetries
private HttpURLConnection sendPostRequestWithRetries(AcmeAccount account, boolean staging, String resourceUrl, boolean useJwk, String encodedPayload, int... expectedResponseCodes) throws AcmeException
- Throws:
AcmeException
-
sendPostRequestWithRetries
private HttpURLConnection sendPostRequestWithRetries(AcmeAccount account, boolean staging, String resourceUrl, boolean useJwk, String encodedPayload, String expectedContentType, int... expectedResponseCodes) throws AcmeException
- Throws:
AcmeException
-
pollResourceUntilFinalized
private jakarta.json.JsonObject pollResourceUntilFinalized(AcmeAccount account, boolean staging, String resourceUrl) throws AcmeException
- Throws:
AcmeException
-
respondToChallenges
private AcmeChallenge respondToChallenges(AcmeAccount account, boolean staging, jakarta.json.JsonObject authorization) throws AcmeException
- Throws:
AcmeException
-
getDomainNames
private static LinkedHashSet<String> getDomainNames(String[] domainNames) throws AcmeException
- Throws:
AcmeException
-
getSanitizedDomainName
private static String getSanitizedDomainName(String domainName) throws AcmeException
- Throws:
AcmeException
-
getJsonResponse
private static jakarta.json.JsonObject getJsonResponse(HttpURLConnection connection) throws AcmeException
- Throws:
AcmeException
-
getReplayNonce
private static byte[] getReplayNonce(HttpURLConnection connection) throws AcmeException
- Throws:
AcmeException
-
getLocation
private static String getLocation(HttpURLConnection connection, String urlType) throws AcmeException
- Throws:
AcmeException
-
getRetryAfter
private static long getRetryAfter(HttpURLConnection connection, boolean useDefaultIfHeaderNotPresent) throws AcmeException
- Throws:
AcmeException
-
handleAcmeErrorResponse
private static void handleAcmeErrorResponse(HttpURLConnection connection, int responseCode) throws AcmeException
- Throws:
AcmeException
-
getProblemMessages
private static String getProblemMessages(jakarta.json.JsonObject errorResponse)
-
getProblemMessage
private static String getProblemMessage(jakarta.json.JsonObject jsonResponse)
-
getOptionalJsonString
private static String getOptionalJsonString(jakarta.json.JsonObject jsonObject, String name)
-
getPemCertificateChain
private static X509Certificate[] getPemCertificateChain(HttpURLConnection connection) throws AcmeException
- Throws:
AcmeException
-
getEncodedJson
private static String getEncodedJson(jakarta.json.JsonObject jsonObject)
-
getJws
private static jakarta.json.JsonObject getJws(String encodedProtectedHeader, String encodedPayload, String encodedSignature)
-
getEncodedProtectedHeader
private static String getEncodedProtectedHeader(String algHeader, PublicKey publicKey, String resourceUrl)
-
getEncodedProtectedHeader
private String getEncodedProtectedHeader(boolean useJwk, String resourceUrl, AcmeAccount account, boolean staging) throws AcmeException
- Throws:
AcmeException
-
getEncodedSignature
private static String getEncodedSignature(PrivateKey privateKey, Signature signature, String encodedProtectedHeader, String encodedPayload) throws AcmeException
- Throws:
AcmeException
-
getEncodedSignature
private static String getEncodedSignature(PrivateKey privateKey, String signatureAlgorithm, String encodedProtectedHeader, String encodedPayload) throws AcmeException
- Throws:
AcmeException
-
getECSignatureByteLength
private static int getECSignatureByteLength(String signatureAlgorithm) throws AcmeException
- Throws:
AcmeException
-
getNonce
private byte[] getNonce(AcmeAccount account, boolean staging) throws AcmeException
- Throws:
AcmeException
-
getAccountUrl
private String getAccountUrl(AcmeAccount account, boolean staging) throws AcmeException
- Throws:
AcmeException
-
checkContentType
private static boolean checkContentType(HttpURLConnection connection, String expectedMediaType) throws AcmeException
- Throws:
AcmeException
-
skipDelims
private static void skipDelims(org.wildfly.common.iteration.CodePointIterator di, org.wildfly.common.iteration.CodePointIterator cpi, int... delims) throws AcmeException
- Throws:
AcmeException
-
isDelim
private static boolean isDelim(int c, int... delims)
-
getConvertedInputStream
private static InputStream getConvertedInputStream(InputStream inputStream) throws IOException
- Throws:
IOException
-
-