Probably done with ACME support
Let's Encrypt
This commit is contained in:
parent
e05c7230a6
commit
9ed0a5580b
4 changed files with 60 additions and 47 deletions
24
pom.xml
24
pom.xml
|
@ -42,16 +42,24 @@
|
||||||
<goal>shade</goal>
|
<goal>shade</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<artifactSet>
|
<!-- <artifactSet> <includes> <include>org.shredzone.acme4j:acme4j-client</include>
|
||||||
<includes>
|
<include>org.shredzone.acme4j:acme4j-utils</include> <include>org.bouncycastle:bcprov-jdk15on</include>
|
||||||
<include>org.shredzone.acme4j:acme4j-client</include>
|
</includes> </artifactSet> -->
|
||||||
</includes>
|
|
||||||
</artifactSet>
|
|
||||||
<pluginExecution>
|
<pluginExecution>
|
||||||
<action>
|
<action>
|
||||||
<execute />
|
<execute />
|
||||||
</action>
|
</action>
|
||||||
</pluginExecution>
|
</pluginExecution>
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>*:*</artifact>
|
||||||
|
<excludes>
|
||||||
|
<exclude>META-INF/*.SF</exclude>
|
||||||
|
<exclude>META-INF/*.DSA</exclude>
|
||||||
|
<exclude>META-INF/*.RSA</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
@ -82,35 +90,41 @@
|
||||||
<groupId>org.spigotmc</groupId>
|
<groupId>org.spigotmc</groupId>
|
||||||
<artifactId>spigot-api</artifactId>
|
<artifactId>spigot-api</artifactId>
|
||||||
<version>1.9.2-R0.1-SNAPSHOT</version>
|
<version>1.9.2-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
|
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>3.4</version>
|
<version>3.4</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
|
<!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.reflections</groupId>
|
<groupId>org.reflections</groupId>
|
||||||
<artifactId>reflections</artifactId>
|
<artifactId>reflections</artifactId>
|
||||||
<version>0.9.10</version>
|
<version>0.9.10</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
|
<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.javassist</groupId>
|
<groupId>org.javassist</groupId>
|
||||||
<artifactId>javassist</artifactId>
|
<artifactId>javassist</artifactId>
|
||||||
<version>3.20.0-GA</version>
|
<version>3.20.0-GA</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io -->
|
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
<version>1.3.2</version>
|
<version>1.3.2</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
|
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
|
||||||
<artifactId>ButtonCore</artifactId>
|
<artifactId>ButtonCore</artifactId>
|
||||||
<version>master-SNAPSHOT</version>
|
<version>master-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.shredzone.acme4j</groupId>
|
<groupId>org.shredzone.acme4j</groupId>
|
||||||
|
|
|
@ -13,10 +13,12 @@
|
||||||
*/ //Modified
|
*/ //Modified
|
||||||
package buttondevteam.website;
|
package buttondevteam.website;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
@ -25,8 +27,6 @@ import java.security.cert.X509Certificate;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import javax.swing.JOptionPane;
|
|
||||||
|
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.shredzone.acme4j.*;
|
import org.shredzone.acme4j.*;
|
||||||
import org.shredzone.acme4j.challenge.Challenge;
|
import org.shredzone.acme4j.challenge.Challenge;
|
||||||
|
@ -40,6 +40,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.website.page.AcmeChallengePage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple client test tool.
|
* A simple client test tool.
|
||||||
|
@ -151,7 +152,7 @@ public class AcmeClient {
|
||||||
* {@link Session} to bind with
|
* {@link Session} to bind with
|
||||||
* @return {@link Registration} connected to your account
|
* @return {@link Registration} connected to your account
|
||||||
*/
|
*/
|
||||||
private Registration findOrRegisterAccount(Session session) throws AcmeException {
|
private Registration findOrRegisterAccount(Session session) throws AcmeException, IOException {
|
||||||
Registration reg;
|
Registration reg;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -245,45 +246,31 @@ public class AcmeClient {
|
||||||
* Domain name to be authorized
|
* Domain name to be authorized
|
||||||
* @return {@link Challenge} to verify
|
* @return {@link Challenge} to verify
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public Challenge httpChallenge(Authorization auth, String domain) throws AcmeException {
|
public Challenge httpChallenge(Authorization auth, String domain) throws AcmeException {
|
||||||
// Find a single http-01 challenge
|
// Find a single http-01 challenge
|
||||||
Http01Challenge challenge = auth.findChallenge(Http01Challenge.TYPE);
|
Http01Challenge challenge = auth.findChallenge(Http01Challenge.TYPE);
|
||||||
if (challenge == null) {
|
if (challenge == null) {
|
||||||
throw new AcmeException("Found no " + Http01Challenge.TYPE + " challenge, don't know what to do...");
|
throw new AcmeException("Found no " + Http01Challenge.TYPE + " challenge, don't know what to do...");
|
||||||
}
|
}
|
||||||
|
if (ButtonWebsiteModule.PORT == 80)
|
||||||
// Output the challenge, wait for acknowledge...
|
LOG.info("Storing the challenge data.");
|
||||||
LOG.info("Please create a file in your web server's base directory.");
|
else
|
||||||
LOG.info("It must be reachable at: http://" + domain + "/.well-known/acme-challenge/" + challenge.getToken());
|
LOG.info("Store the challenge data! Can't do automatically.");
|
||||||
|
LOG.info("It should be reachable at: http://" + domain + "/.well-known/acme-challenge/" + challenge.getToken());
|
||||||
LOG.info("File name: " + challenge.getToken());
|
LOG.info("File name: " + challenge.getToken());
|
||||||
LOG.info("Content: " + challenge.getAuthorization());
|
LOG.info("Content: " + challenge.getAuthorization());
|
||||||
LOG.info("The file must not contain any leading or trailing whitespaces or line breaks!");
|
LOG.info("Press any key to continue...");
|
||||||
LOG.info("If you're ready, dismiss the dialog...");
|
if (ButtonWebsiteModule.PORT != 80)
|
||||||
|
try {
|
||||||
StringBuilder message = new StringBuilder();
|
System.in.read();
|
||||||
message.append("Please create a file in your web server's base directory.\n\n");
|
} catch (IOException e) {
|
||||||
message.append("http://").append(domain).append("/.well-known/acme-challenge/").append(challenge.getToken())
|
e.printStackTrace();
|
||||||
.append("\n\n");
|
}
|
||||||
message.append("Content:\n\n");
|
ButtonWebsiteModule.addPage(new AcmeChallengePage(challenge.getToken(), challenge.getAuthorization()));
|
||||||
message.append(challenge.getAuthorization());
|
|
||||||
acceptChallenge(message.toString());
|
|
||||||
|
|
||||||
return challenge;
|
return challenge;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Presents the instructions for preparing the challenge validation, and waits for dismissal. If the user cancelled the dialog, an exception is thrown.
|
|
||||||
*
|
|
||||||
* @param message
|
|
||||||
* Instructions to be shown in the dialog
|
|
||||||
*/
|
|
||||||
public void acceptChallenge(String message) throws AcmeException {
|
|
||||||
int option = JOptionPane.showConfirmDialog(null, message, "Prepare Challenge", JOptionPane.OK_CANCEL_OPTION);
|
|
||||||
if (option == JOptionPane.CANCEL_OPTION) {
|
|
||||||
throw new AcmeException("User cancelled the challenge");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Presents the user a link to the Terms of Service, and asks for confirmation. If the user denies confirmation, an exception is thrown.
|
* Presents the user a link to the Terms of Service, and asks for confirmation. If the user denies confirmation, an exception is thrown.
|
||||||
*
|
*
|
||||||
|
@ -292,10 +279,10 @@ public class AcmeClient {
|
||||||
* @param agreement
|
* @param agreement
|
||||||
* {@link URI} of the Terms of Service
|
* {@link URI} of the Terms of Service
|
||||||
*/
|
*/
|
||||||
public void acceptAgreement(Registration reg, URI agreement) throws AcmeException {
|
public void acceptAgreement(Registration reg, URI agreement) throws AcmeException, IOException {
|
||||||
int option = JOptionPane.showConfirmDialog(null, "Do you accept the Terms of Service?\n\n" + agreement,
|
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
|
||||||
"Accept ToS", JOptionPane.YES_NO_OPTION);
|
System.out.println("Do you accept the terms? (y/n)");
|
||||||
if (option == JOptionPane.NO_OPTION) {
|
if (br.readLine().equalsIgnoreCase("y\n")) {
|
||||||
throw new AcmeException("User did not accept Terms of Service");
|
throw new AcmeException("User did not accept Terms of Service");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,8 +299,8 @@ public class AcmeClient {
|
||||||
*/
|
*/
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
System.err.println("Usage: ClientTest <domain>...");
|
TBMCCoreAPI.SendException("Error while doing ACME!", new Exception("No domains given"));
|
||||||
System.exit(1);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.info("Starting up...");
|
LOG.info("Starting up...");
|
||||||
|
|
|
@ -11,11 +11,12 @@ import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.website.page.*;
|
import buttondevteam.website.page.*;
|
||||||
|
|
||||||
public class ButtonWebsiteModule extends JavaPlugin {
|
public class ButtonWebsiteModule extends JavaPlugin {
|
||||||
|
public static final int PORT = 8080;
|
||||||
private static HttpServer server;
|
private static HttpServer server;
|
||||||
|
|
||||||
public ButtonWebsiteModule() {
|
public ButtonWebsiteModule() {
|
||||||
try {
|
try {
|
||||||
server = HttpServer.create(new InetSocketAddress((InetAddress) null, 8080), 10);
|
server = HttpServer.create(new InetSocketAddress((InetAddress) null, PORT), 10);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("An error occured while starting the webserver!", e);
|
TBMCCoreAPI.SendException("An error occured while starting the webserver!", e);
|
||||||
}
|
}
|
||||||
|
@ -25,10 +26,12 @@ public class ButtonWebsiteModule extends JavaPlugin {
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
addPage(new IndexPage());
|
addPage(new IndexPage());
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
|
||||||
|
|
||||||
this.getLogger().info("Starting webserver...");
|
this.getLogger().info("Starting webserver...");
|
||||||
((Runnable) server::start).run(); // Totally normal way of calling a method
|
((Runnable) server::start).run(); // Totally normal way of calling a method
|
||||||
this.getLogger().info("Webserver started");
|
this.getLogger().info("Webserver started");
|
||||||
|
Thread t = new Thread(() -> AcmeClient.main("server.figytuna.com"));
|
||||||
|
t.setContextClassLoader(getClass().getClassLoader());
|
||||||
|
t.start();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,15 +6,24 @@ import buttondevteam.website.io.Response;
|
||||||
|
|
||||||
public class AcmeChallengePage extends Page {
|
public class AcmeChallengePage extends Page {
|
||||||
|
|
||||||
|
public AcmeChallengePage(String token, String content) {
|
||||||
|
this.token = token;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String GetName() {
|
public String GetName() {
|
||||||
return ".well-known/acme-challenge";
|
return ".well-known/acme-challenge/" + token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response handlePage(HttpExchange exchange) {
|
public Response handlePage(HttpExchange exchange) {
|
||||||
// TODO Auto-generated method stub
|
if (content == null)
|
||||||
return null;
|
return new Response(500, "500 No content", exchange);
|
||||||
|
return new Response(200, content, exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String token;
|
||||||
|
private String content;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue