Support the acme-ip draft

pull/81/head
Richard Körber 2018-08-20 23:36:38 +02:00
parent fdab98ad41
commit 1cffd3428d
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
4 changed files with 64 additions and 2 deletions

View File

@ -12,6 +12,7 @@ It is an independent open source implementation that is not affiliated with or e
* Fully supports the ACME v2 protocol up to [draft 13](https://tools.ietf.org/html/draft-ietf-acme-acme-13) * Fully supports the ACME v2 protocol up to [draft 13](https://tools.ietf.org/html/draft-ietf-acme-acme-13)
* Supports all ACME challenges and the `tls-alpn-01` challenge * Supports all ACME challenges and the `tls-alpn-01` challenge
* Supports the [acme-ip draft](https://tools.ietf.org/html/draft-ietf-acme-ip)
* Easy to use Java API * Easy to use Java API
* Requires JRE 8 (update 101) or higher * Requires JRE 8 (update 101) or higher
* Built with maven, packages available at [Maven Central](http://search.maven.org/#search|ga|1|g%3A%22org.shredzone.acme4j%22) * Built with maven, packages available at [Maven Central](http://search.maven.org/#search|ga|1|g%3A%22org.shredzone.acme4j%22)

View File

@ -17,6 +17,8 @@ import static java.util.Objects.requireNonNull;
import static org.shredzone.acme4j.toolbox.AcmeUtils.toAce; import static org.shredzone.acme4j.toolbox.AcmeUtils.toAce;
import java.io.Serializable; import java.io.Serializable;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map; import java.util.Map;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
@ -30,6 +32,7 @@ import org.shredzone.acme4j.toolbox.JSONBuilder;
* Represents an identifier. * Represents an identifier.
* <p> * <p>
* The ACME protocol only defines the DNS identifier, which identifies a domain name. * The ACME protocol only defines the DNS identifier, which identifies a domain name.
* acme4j also supports IP identifiers.
* <p> * <p>
* CAs may define further, proprietary identifier types. * CAs may define further, proprietary identifier types.
* *
@ -45,6 +48,13 @@ public class Identifier implements Serializable {
*/ */
public static final String DNS = "dns"; public static final String DNS = "dns";
/**
* Type constant for IP identifiers.
*
* @see <a href="https://tools.ietf.org/html/draft-ietf-acme-ip">draft-ietf-acme-ip</a>
*/
public static final String IP = "ip";
private static final String KEY_TYPE = "type"; private static final String KEY_TYPE = "type";
private static final String KEY_VALUE = "value"; private static final String KEY_VALUE = "value";
@ -62,6 +72,17 @@ public class Identifier implements Serializable {
return new Identifier(DNS, toAce(domain)); return new Identifier(DNS, toAce(domain));
} }
/**
* Creates a new IP identifier for the given {@link InetAddress}.
*
* @param ip
* {@link InetAddress}
* @return New {@link Identifier}
*/
public static Identifier ip(InetAddress ip) {
return new Identifier(IP, ip.getHostAddress());
}
/** /**
* Creates a new {@link Identifier}. * Creates a new {@link Identifier}.
* <p> * <p>
@ -119,6 +140,24 @@ public class Identifier implements Serializable {
return value; return value;
} }
/**
* Returns the IP address if this is an IP identifier.
*
* @return {@link InetAddress}
* @throws AcmeProtocolException
* if this is not a DNS identifier.
*/
public InetAddress getIP() {
if (!IP.equals(type)) {
throw new AcmeProtocolException("expected 'ip' identifier, but found '" + type + "'");
}
try {
return InetAddress.getByName(value);
} catch (UnknownHostException ex) {
throw new AcmeProtocolException("bad ip identifier value", ex);
}
}
/** /**
* Returns the identifier as JSON map. * Returns the identifier as JSON map.
*/ */

View File

@ -16,6 +16,8 @@ package org.shredzone.acme4j;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map; import java.util.Map;
import org.junit.Test; import org.junit.Test;
@ -30,6 +32,7 @@ public class IdentifierTest {
@Test @Test
public void testConstants() { public void testConstants() {
assertThat(Identifier.DNS, is("dns")); assertThat(Identifier.DNS, is("dns"));
assertThat(Identifier.IP, is("ip"));
} }
@Test @Test
@ -74,6 +77,24 @@ public class IdentifierTest {
new Identifier("foo", "example.com").getDomain(); new Identifier("foo", "example.com").getDomain();
} }
@Test
public void testIp() throws UnknownHostException {
Identifier id1 = Identifier.ip(InetAddress.getByName("192.168.1.2"));
assertThat(id1.getType(), is(Identifier.IP));
assertThat(id1.getValue(), is("192.168.1.2"));
assertThat(id1.getIP().getHostAddress(), is("192.168.1.2"));
Identifier id2 = Identifier.ip(InetAddress.getByName("2001:db8:85a3::8a2e:370:7334"));
assertThat(id2.getType(), is(Identifier.IP));
assertThat(id2.getValue(), is("2001:db8:85a3:0:0:8a2e:370:7334"));
assertThat(id2.getIP().getHostAddress(), is("2001:db8:85a3:0:0:8a2e:370:7334"));
}
@Test(expected = AcmeProtocolException.class)
public void testNoIp() {
new Identifier("foo", "example.com").getIP();
}
@Test @Test
public void testEquals() { public void testEquals() {
Identifier idRef = new Identifier("foo", "123.456"); Identifier idRef = new Identifier("foo", "123.456");

View File

@ -20,6 +20,7 @@ import static org.shredzone.acme4j.toolbox.TestUtils.*;
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL; import java.net.URL;
import java.time.Instant; import java.time.Instant;
import java.util.Arrays; import java.util.Arrays;
@ -80,7 +81,7 @@ public class OrderBuilderTest {
.identifier(Identifier.dns("d.example.com")) .identifier(Identifier.dns("d.example.com"))
.identifiers(Arrays.asList( .identifiers(Arrays.asList(
Identifier.dns("d2.example.com"), Identifier.dns("d2.example.com"),
new Identifier("ip", "192.168.1.2"))) Identifier.ip(InetAddress.getByName("192.168.1.2"))))
.notBefore(notBefore) .notBefore(notBefore)
.notAfter(notAfter) .notAfter(notAfter)
.create(); .create();
@ -99,7 +100,7 @@ public class OrderBuilderTest {
Identifier.dns("m.example.org"), Identifier.dns("m.example.org"),
Identifier.dns("d.example.com"), Identifier.dns("d.example.com"),
Identifier.dns("d2.example.com"), Identifier.dns("d2.example.com"),
new Identifier("ip", "192.168.1.2"))); Identifier.ip(InetAddress.getByName("192.168.1.2"))));
assertThat(order.getNotBefore(), is(parseTimestamp("2016-01-01T00:10:00Z"))); assertThat(order.getNotBefore(), is(parseTimestamp("2016-01-01T00:10:00Z")));
assertThat(order.getNotAfter(), is(parseTimestamp("2016-01-08T00:10:00Z"))); assertThat(order.getNotAfter(), is(parseTimestamp("2016-01-08T00:10:00Z")));
assertThat(order.getExpires(), is(parseTimestamp("2016-01-10T00:00:00Z"))); assertThat(order.getExpires(), is(parseTimestamp("2016-01-10T00:00:00Z")));