mirror of
https://github.com/internetarchive/heritrix3.git
synced 2026-08-24 23:46:42 +00:00
Add --web-auth basic command-line option
This option enables HTTP Basic authentication for the web interface instead of the default Digest authentication. This is useful when running Heritrix behind a reverse proxy that adds external authentication as typically they don't support Digest auth for the upstream server. #641
This commit is contained in:
@@ -4,6 +4,12 @@
|
||||
|
||||
[Full Changelog](https://github.com/internetarchive/heritrix3/compare/3.9.0...HEAD)
|
||||
|
||||
#### New features
|
||||
|
||||
- **Basic web auth:** You can now switch the web interface from Digest authentication to Basic authentication
|
||||
with the `--web-auth basic` command-line option. This is useful when running Heritrix behind a reverse proxy that
|
||||
adds external authentication.
|
||||
|
||||
#### Fixes
|
||||
|
||||
- **Code editor:** The configuration editor and script console were upgraded to CodeMirror 6. This resolves some browser
|
||||
|
||||
@@ -42,6 +42,8 @@ Command-line Options
|
||||
Specifies a keystore path, keystore password, and key password for HTTPS use. Separate the values with
|
||||
commas and do not include whitespace. By default Heritrix will generate a self-signed certificate the
|
||||
first time it is run.
|
||||
--web-auth digest|basic
|
||||
Authentication mode for the web interface. **Default:** ``digest``
|
||||
|
||||
Environment Variables
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -56,7 +56,9 @@ import org.archive.util.KeyTool;
|
||||
import org.restlet.Component;
|
||||
import org.restlet.Context;
|
||||
import org.restlet.Server;
|
||||
import org.restlet.data.ChallengeScheme;
|
||||
import org.restlet.data.Protocol;
|
||||
import org.restlet.security.ChallengeAuthenticator;
|
||||
import org.restlet.security.MapVerifier;
|
||||
|
||||
|
||||
@@ -111,6 +113,13 @@ public class Heritrix {
|
||||
*/
|
||||
private static final String STARTLOG = "heritrix_dmesg.log";
|
||||
|
||||
private enum AuthMode {
|
||||
DIGEST, BASIC;
|
||||
|
||||
public String toString() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
private static void usage(PrintStream out, String[] args) {
|
||||
HelpFormatter hf = new HelpFormatter();
|
||||
@@ -122,6 +131,8 @@ public class Heritrix {
|
||||
private static Options options() {
|
||||
Options options = new Options();
|
||||
options.addOption("h", "help", true, "Usage information." );
|
||||
options.addOption(null, "web-auth", true, "Authentication mode for the" +
|
||||
" web interface: " + Arrays.toString(AuthMode.values()));
|
||||
options.addOption("a", "web-admin", true, "REQUIRED. Specifies the " +
|
||||
"authorization username and password which must be supplied to " +
|
||||
"access the web interface. This may be of the form " +
|
||||
@@ -237,6 +248,7 @@ public class Heritrix {
|
||||
// DEFAULTS until changed by cmd-line options
|
||||
int port = 8443;
|
||||
Set<String> bindHosts = new HashSet<String>();
|
||||
AuthMode authMode = AuthMode.DIGEST;
|
||||
String authLogin = "admin";
|
||||
String authPassword = null;
|
||||
String keystorePath;
|
||||
@@ -330,6 +342,16 @@ public class Heritrix {
|
||||
System.setProperty("https.proxyPort", proxyPort);
|
||||
}
|
||||
|
||||
if (cl.hasOption("web-auth")) {
|
||||
try {
|
||||
authMode = AuthMode.valueOf(cl.getOptionValue("web-auth").toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.println("Unsupported --web-auth value '" + cl.getOptionValue("web-auth") +
|
||||
"' (must be one of " + Arrays.toString(AuthMode.values()) + ")");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Restlet will reconfigure logging according to the system property
|
||||
// so we must set it for -l to work properly
|
||||
System.setProperty("java.util.logging.config.file", properties.getPath());
|
||||
@@ -373,9 +395,13 @@ public class Heritrix {
|
||||
MapVerifier verifier = new MapVerifier();
|
||||
verifier.getLocalSecrets().put(authLogin, authPassword.toCharArray());
|
||||
|
||||
RateLimitGuard guard = new RateLimitGuard(component.getContext().createChildContext(),
|
||||
"Authentication Required", UUID.randomUUID().toString());
|
||||
guard.setWrappedVerifier(verifier);
|
||||
Context guardContext = component.getContext().createChildContext();
|
||||
ChallengeAuthenticator guard = switch (authMode) {
|
||||
case BASIC -> new ChallengeAuthenticator(guardContext, false,
|
||||
ChallengeScheme.HTTP_BASIC, "Authentication Required", verifier);
|
||||
case DIGEST -> new RateLimitGuard(guardContext, "Authentication Required",
|
||||
UUID.randomUUID().toString(), verifier);
|
||||
};
|
||||
guard.setNext(new EngineApplication(engine));
|
||||
|
||||
component.getDefaultHost().attach(guard);
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.restlet.Context;
|
||||
import org.restlet.Request;
|
||||
import org.restlet.Response;
|
||||
import org.restlet.ext.crypto.DigestAuthenticator;
|
||||
import org.restlet.security.LocalVerifier;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -38,8 +39,9 @@ public class RateLimitGuard extends DigestAuthenticator {
|
||||
|
||||
protected long lastFailureTime = 0;
|
||||
|
||||
public RateLimitGuard(Context context, String realm, String serverKey) throws IllegalArgumentException {
|
||||
public RateLimitGuard(Context context, String realm, String serverKey, LocalVerifier verifier) throws IllegalArgumentException {
|
||||
super(context, realm, serverKey);
|
||||
setWrappedVerifier(verifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user