mirror of https://github.com/shred/acme4j
Remove account recovery. Closes issue #1.
parent
19787f4c00
commit
92b3076031
|
@ -61,16 +61,6 @@ public interface AcmeClient {
|
|||
void changeRegistrationKey(Registration registration, KeyPair newKeyPair)
|
||||
throws AcmeException;
|
||||
|
||||
/**
|
||||
* Recovers an account by contact-based recovery. The server starts an out-of-band
|
||||
* recovery process by using one of the contact addresses given at account creation.
|
||||
*
|
||||
* @param registration
|
||||
* {@link Registration}, with the new key pair and the account location URI
|
||||
* set
|
||||
*/
|
||||
void recoverRegistration(Registration registration) throws AcmeException;
|
||||
|
||||
/**
|
||||
* Deletes an account. Related certificates may still be valid after account deletion,
|
||||
* and need to be revoked separately if neccessary.
|
||||
|
|
|
@ -23,8 +23,7 @@ public enum Resource {
|
|||
NEW_REG("new-reg"),
|
||||
NEW_AUTHZ("new-authz"),
|
||||
NEW_CERT("new-cert"),
|
||||
REVOKE_CERT("revoke-cert"),
|
||||
RECOVER_REG("recover-reg");
|
||||
REVOKE_CERT("revoke-cert");
|
||||
|
||||
/**
|
||||
* Parses the string and returns a matching {@link Resource} instance.
|
||||
|
|
|
@ -223,41 +223,6 @@ public abstract class AbstractAcmeClient implements AcmeClient {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recoverRegistration(Registration registration) throws AcmeException {
|
||||
if (registration == null) {
|
||||
throw new NullPointerException("registration must not be null");
|
||||
}
|
||||
if (registration.getLocation() == null) {
|
||||
throw new IllegalArgumentException("registration location must not be null");
|
||||
}
|
||||
|
||||
LOG.debug("recoverRegistration");
|
||||
try (Connection conn = createConnection()) {
|
||||
ClaimBuilder claims = new ClaimBuilder();
|
||||
claims.putResource(Resource.RECOVER_REG);
|
||||
claims.put("method", "contact");
|
||||
claims.put("base", registration.getLocation());
|
||||
if (!registration.getContacts().isEmpty()) {
|
||||
claims.put("contact", registration.getContacts());
|
||||
}
|
||||
|
||||
int rc = conn.sendSignedRequest(resourceUri(Resource.RECOVER_REG), claims, session, registration);
|
||||
if (rc != HttpURLConnection.HTTP_CREATED) {
|
||||
conn.throwAcmeException();
|
||||
}
|
||||
|
||||
registration.setLocation(conn.getLocation());
|
||||
|
||||
URI tos = conn.getLink("terms-of-service");
|
||||
if (tos != null) {
|
||||
registration.setAgreement(tos);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new AcmeNetworkException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRegistration(Registration registration) throws AcmeException {
|
||||
if (registration == null) {
|
||||
|
|
|
@ -34,10 +34,9 @@ public class ResourceTest {
|
|||
assertThat(Resource.NEW_CERT.path(), is("new-cert"));
|
||||
assertThat(Resource.NEW_REG.path(), is("new-reg"));
|
||||
assertThat(Resource.REVOKE_CERT.path(), is("revoke-cert"));
|
||||
assertThat(Resource.RECOVER_REG.path(), is("recover-reg"));
|
||||
|
||||
// fails if there are untested future Resource values
|
||||
assertThat(Resource.values().length, is(5));
|
||||
assertThat(Resource.values().length, is(4));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -56,7 +56,6 @@ public class AbstractAcmeClientTest {
|
|||
|
||||
private URI resourceUri;
|
||||
private URI locationUri;
|
||||
private URI anotherLocationUri;
|
||||
private URI agreementUri;
|
||||
private KeyPair accountKeyPair;
|
||||
private Registration testRegistration;
|
||||
|
@ -65,7 +64,6 @@ public class AbstractAcmeClientTest {
|
|||
public void setup() throws IOException, URISyntaxException {
|
||||
resourceUri = new URI("https://example.com/acme/some-resource");
|
||||
locationUri = new URI("https://example.com/acme/some-location");
|
||||
anotherLocationUri = new URI("https://example.com/acme/another-location");
|
||||
agreementUri = new URI("http://example.com/agreement.pdf");
|
||||
accountKeyPair = TestUtils.createKeyPair();
|
||||
testRegistration = new Registration(accountKeyPair);
|
||||
|
@ -220,46 +218,6 @@ public class AbstractAcmeClientTest {
|
|||
client.changeRegistrationKey(registration, registration.getKeyPair());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a {@link Registration} can be recovered by contact-based recovery.
|
||||
*/
|
||||
@Test
|
||||
public void testRecoverRegistration() throws AcmeException {
|
||||
Registration registration = new Registration(accountKeyPair);
|
||||
registration.addContact("mailto:foo@example.com");
|
||||
registration.setLocation(locationUri);
|
||||
|
||||
Connection connection = new DummyConnection() {
|
||||
@Override
|
||||
public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session, Registration registration) {
|
||||
assertThat(session, is(notNullValue()));
|
||||
assertThat(registration.getKeyPair(), is(sameInstance(accountKeyPair)));
|
||||
return HttpURLConnection.HTTP_CREATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getLocation() {
|
||||
return anotherLocationUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getLink(String relation) {
|
||||
switch(relation) {
|
||||
case "terms-of-service": return agreementUri;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TestableAbstractAcmeClient client = new TestableAbstractAcmeClient(connection);
|
||||
client.putTestResource(Resource.RECOVER_REG, resourceUri);
|
||||
|
||||
client.recoverRegistration(registration);
|
||||
|
||||
assertThat(registration.getLocation(), is(anotherLocationUri));
|
||||
assertThat(registration.getAgreement(), is(agreementUri));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a {@link Registration} can be deleted.
|
||||
*/
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
# Account Recovery
|
||||
|
||||
The ACME server identifies your account by the public key that you provided on registration. If you lose your key pair, you will be unable to access your account.
|
||||
|
||||
ACME offers a contact-based way of recovering access to your authorizations and certificates in case you have lost your key pair. However, it involves creating a new account, and transfering your data to it. You will not be able to regain access to your old account.
|
||||
|
||||
Individual CAs may offer further ways of recovery, which are not part of this documentation.
|
||||
|
||||
## Contact-Based Recovery
|
||||
|
||||
> **CAUTION**: Contact-Based Recovery is [currently not supported by _Let's Encrypt_](https://github.com/letsencrypt/boulder/issues/432). If you should lose your key pair, you are stuck.
|
||||
|
||||
On this recovery method, the CA contacts the account owner via one of the contact addresses given on account creation. The owner is asked to take some action (e.g. clicking on a link in an email). If it was successful, the account data is transferred to the new account.
|
||||
|
||||
To initiate contact-based recovery, you first need to create a new account key pair. Then create a `Registration` object by passing the _new_ key pair and location URI of your _old_ account to the constructor. Finally, start the recovery process by invoking `recoverRegistration()`:
|
||||
|
||||
```java
|
||||
KeyPair newKeyPair = ... // your new account KeyPair
|
||||
URI oldAccountUri = ... // location of your old account
|
||||
|
||||
Registration reg = new Registration(newKeyPair, oldAccountUri);
|
||||
client.recoverRegistration(reg);
|
||||
|
||||
URI newAccountUri = reg.getLocation();
|
||||
```
|
||||
|
||||
`newAccountUri` is the location URI of your _new_ account. Store it and use it in connection with your new key pair.
|
||||
|
||||
The old location URI is now invalid and can be deleted.
|
|
@ -34,7 +34,6 @@
|
|||
<item name="Registration" href="usage/register.html"/>
|
||||
<item name="Authorization" href="usage/authorization.html"/>
|
||||
<item name="Certificate" href="usage/certificate.html"/>
|
||||
<item name="Recovery" href="usage/recovery.html"/>
|
||||
</item>
|
||||
<item name="Challenges" href="challenge/index.html">
|
||||
<item name="http-01" href="challenge/http-01.html"/>
|
||||
|
|
Loading…
Reference in New Issue