.addEmail(contact) .create(session); log.info("Registered a new user, URL: {}", account.getLocation()); Order order = account.newOrder().domain(domain).create();
private EditableAccount() { editContacts.addAll(Account.this.getContacts()); }
/** * Commits the changes and updates the account. */ public void commit() throws AcmeException { LOG.debug("modify/commit"); try (Connection conn = getSession().connect()) { JSONBuilder claims = new JSONBuilder(); if (!editContacts.isEmpty()) { claims.put(KEY_CONTACT, editContacts); } conn.sendSignedRequest(getLocation(), claims, getLogin()); JSON json = conn.readJsonResponse(); if (json != null) { setJSON(json); } } } }
@Override public Tuple2<Order, Dns01Challenge> challengeInit(String domainName) { AssertTools.assertNotNull(account, "You need to log in first"); Order order; try { order = account.newOrder() // .domains(domainName) // .create(); } catch (AcmeException e) { LOGGER.error("Could not ask for domain {}", domainName, e); throw new LetsencryptException("Could not ask for domain " + domainName, e); } // Get the DNS challenge Dns01Challenge challenge = null; List<String> availableChallenges = new ArrayList<>(); for (Authorization auth : order.getAuthorizations()) { auth.getChallenges().stream().map(it -> it.getType()).forEach(it -> availableChallenges.add(it)); challenge = auth.findChallenge(Dns01Challenge.TYPE); } if (challenge == null) { throw new LetsencryptException("DNS Challenge not found for " + domainName + " ; Available challenges are: [" + Joiner.on(", ").join(availableChallenges) + "]"); } return new Tuple2<>(order, challenge); }
if (Arrays.equals(getLogin().getKeyPair().getPrivate().getEncoded(), newKeyPair.getPrivate().getEncoded())) { throw new IllegalArgumentException("newKeyPair must actually be a new key pair"); try (Connection conn = getSession().connect()) { URL keyChangeUrl = getSession().resourceUrl(Resource.KEY_CHANGE); PublicJsonWebKey newKeyJwk = PublicJsonWebKey.Factory.newPublicJwk(newKeyPair.getPublic()); payloadClaim.put("account", getLocation()); payloadClaim.putKey("oldKey", getLogin().getKeyPair().getPublic()); outerClaim.put("payload", innerJws.getEncodedPayload()); conn.sendSignedRequest(keyChangeUrl, outerClaim, getLogin()); getLogin().setKeyPair(newKeyPair); } catch (JoseException ex) { throw new AcmeProtocolException("Cannot sign key-change", ex);
public CompletableFuture<URL> openAccount(String email, KeyPair accountKeyPair) { try { log.info("open account"); Session session = new Session("acme://letsencrypt.org/staging"); Account account = new AccountBuilder() .addContact("mailto:"+email) .agreeToTermsOfService() .useKeyPair(accountKeyPair) .create(session); URL location = account.getLocation(); log.info("account location="+location); return CompletableFuture.completedFuture(location); } catch (AcmeException e) { throw new RuntimeException(e); } } //TODO: Put the remote request INTO a different pool to not hold up the webserver main
/** * Returns an {@link Iterator} of all {@link Order} belonging to this {@link Account}. * <p> * Using the iterator will initiate one or more requests to the ACME server. * * @return {@link Iterator} instance that returns {@link Order} objects in no specific * order. {@link Iterator#hasNext()} and {@link Iterator#next()} may throw * {@link AcmeProtocolException} if a batch of authorization URIs could not be * fetched from the server. Each {@link Iterator} instance may provide the * {@link Order} objects in a different order. */ public Iterator<Order> getOrders() { URL ordersUrl = getJSON().get(KEY_ORDERS).asURL(); return new ResourceIterator<>(getLogin(), KEY_ORDERS, ordersUrl, Login::bindOrder); }
Objects.requireNonNull(identifier, "identifier"); URL newAuthzUrl = getSession().resourceUrl(Resource.NEW_AUTHZ); try (Connection conn = getSession().connect()) { JSONBuilder claims = new JSONBuilder(); claims.put("identifier", identifier.toMap()); conn.sendSignedRequest(newAuthzUrl, claims, getLogin()); Authorization auth = getLogin().bindAuthorization(authLocation); JSON json = conn.readJsonResponse(); if (json != null) {
/** * Returns if the user agreed to the terms of service. * * @return {@code true} if the user agreed to the terms of service. May be * {@code null} if the server did not provide such an information. */ @CheckForNull public Boolean getTermsOfServiceAgreed() { return getJSON().get(KEY_TOS_AGREED).map(Value::asBoolean).orElse(null); }
/** * Creates a builder for a new {@link Order}. * * @return {@link OrderBuilder} object */ public OrderBuilder newOrder() { return new OrderBuilder(getLogin()); }
/** * Creates a new {@link Login}. * * @param accountLocation * Account location {@link URL} * @param keyPair * {@link KeyPair} of the account * @param session * {@link Session} to be used */ public Login(URL accountLocation, KeyPair keyPair, Session session) { this.accountLocation = Objects.requireNonNull(accountLocation, "accountLocation"); this.keyPair = Objects.requireNonNull(keyPair, "keyPair"); this.session = Objects.requireNonNull(session, "session"); this.account = new Account(this); }
/** * Permanently deactivates an account. Related certificates may still be valid after * account deactivation, and need to be revoked separately if neccessary. * <p> * A deactivated account cannot be reactivated! */ public void deactivate() throws AcmeException { LOG.debug("deactivate"); try (Connection conn = getSession().connect()) { JSONBuilder claims = new JSONBuilder(); claims.put(KEY_STATUS, "deactivated"); conn.sendSignedRequest(getLocation(), claims, getLogin()); JSON json = conn.readJsonResponse(); if (json != null) { setJSON(json); } } }
/** * @return The list of challenges with tokens to create webpages for that remote end will call to verify we own the domain */ public CompletableFuture<ProxyOrder> placeOrder(URL accountUrl, KeyPair accountKeyPair) { try { log.info("reestablish account from location="+accountUrl+" and keypair"); Session session = new Session("acme://letsencrypt.org/staging"); Login login = session.login(accountUrl, accountKeyPair); Account account = login.getAccount(); log.info("create an order"); String domainTemp = "something.com"; Order order = account.newOrder() .domain(domainTemp) .create(); checkAuthStatii(order); List<ProxyAuthorization> auths = new ArrayList<>(); for(Authorization auth : order.getAuthorizations()) auths.add(new ProxyAuthorization(auth)); return CompletableFuture.completedFuture(new ProxyOrder(order, auths)); } catch (AcmeException e) { throw new RuntimeException(e); } }
if (Arrays.equals(getLogin().getKeyPair().getPrivate().getEncoded(), newKeyPair.getPrivate().getEncoded())) { throw new IllegalArgumentException("newKeyPair must actually be a new key pair"); try (Connection conn = getSession().connect()) { URL keyChangeUrl = getSession().resourceUrl(Resource.KEY_CHANGE); PublicJsonWebKey newKeyJwk = PublicJsonWebKey.Factory.newPublicJwk(newKeyPair.getPublic()); payloadClaim.put("account", getLocation()); payloadClaim.putKey("oldKey", getLogin().getKeyPair().getPublic()); outerClaim.put("payload", innerJws.getEncodedPayload()); conn.sendSignedRequest(keyChangeUrl, outerClaim, getLogin()); getLogin().setKeyPair(newKeyPair); } catch (JoseException ex) { throw new AcmeProtocolException("Cannot sign key-change", ex);
private void login() { KeyPair accountKeyPair = RSATools.createKeyPair(RSACrypt.RSA_CRYPT.loadKeysPemFromString(config.getAccountKeypairPem())); LOGGER.info("Registering account"); try { account = new AccountBuilder() // .addContact("mailto:" + config.getContactEmail()) // .agreeToTermsOfService() // .useKeyPair(accountKeyPair) // .create(session); } catch (AcmeException e) { LOGGER.error("Problem logging in", e); throw new LetsencryptException("Problem logging in", e); } URL accountLocationUrl = account.getLocation(); session.login(accountLocationUrl, accountKeyPair); // Get the location LOGGER.info("AcmeClient location: {}", accountLocationUrl); }
/** * Returns an {@link Iterator} of all {@link Order} belonging to this {@link Account}. * <p> * Using the iterator will initiate one or more requests to the ACME server. * * @return {@link Iterator} instance that returns {@link Order} objects in no specific * order. {@link Iterator#hasNext()} and {@link Iterator#next()} may throw * {@link AcmeProtocolException} if a batch of authorization URIs could not be * fetched from the server. Each {@link Iterator} instance may provide the * {@link Order} objects in a different order. */ public Iterator<Order> getOrders() { URL ordersUrl = getJSON().get(KEY_ORDERS).asURL(); return new ResourceIterator<>(getLogin(), KEY_ORDERS, ordersUrl, Login::bindOrder); }
Objects.requireNonNull(identifier, "identifier"); URL newAuthzUrl = getSession().resourceUrl(Resource.NEW_AUTHZ); try (Connection conn = getSession().connect()) { JSONBuilder claims = new JSONBuilder(); claims.put("identifier", identifier.toMap()); conn.sendSignedRequest(newAuthzUrl, claims, getLogin()); Authorization auth = getLogin().bindAuthorization(authLocation); JSON json = conn.readJsonResponse(); if (json != null) {
/** * Returns if the user agreed to the terms of service. * * @return {@code true} if the user agreed to the terms of service. May be * {@code null} if the server did not provide such an information. */ @CheckForNull public Boolean getTermsOfServiceAgreed() { return getJSON().get(KEY_TOS_AGREED).map(Value::asBoolean).orElse(null); }
/** * Creates a builder for a new {@link Order}. * * @return {@link OrderBuilder} object */ public OrderBuilder newOrder() { return new OrderBuilder(getLogin()); }
/** * Creates a new {@link Login}. * * @param accountLocation * Account location {@link URL} * @param keyPair * {@link KeyPair} of the account * @param session * {@link Session} to be used */ public Login(URL accountLocation, KeyPair keyPair, Session session) { this.accountLocation = Objects.requireNonNull(accountLocation, "accountLocation"); this.keyPair = Objects.requireNonNull(keyPair, "keyPair"); this.session = Objects.requireNonNull(session, "session"); this.account = new Account(this); }