summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2014-11-18 18:40:49 +0100
committerSimon Rettberg2014-11-18 18:40:49 +0100
commitecb072b02e1a70555db0fdf4ed47375d3080a074 (patch)
tree75db05621458eee14a96ff2d825a30072eb06e40
parentAdded class ProxyHandler for for configuring proxy settings system wide once ... (diff)
downloadtmlite-bwlp-ecb072b02e1a70555db0fdf4ed47375d3080a074.tar.gz
tmlite-bwlp-ecb072b02e1a70555db0fdf4ed47375d3080a074.tar.xz
tmlite-bwlp-ecb072b02e1a70555db0fdf4ed47375d3080a074.zip
Many improvements and additions:
- Added task+script for lighttpd https config - Added task for reloading proxy config - ldapsearch now supports searching for specific user - DownloadFile now supports checking file integrity through optional gpg signature
-rwxr-xr-xscripts/install-https68
-rwxr-xr-xscripts/system-backup5
-rwxr-xr-xscripts/system-restore62
-rw-r--r--src/main/java/org/openslx/satserver/util/Exec.java20
-rw-r--r--src/main/java/org/openslx/satserver/util/ProxyHandler.java35
-rw-r--r--src/main/java/org/openslx/satserver/util/Util.java19
-rw-r--r--src/main/java/org/openslx/taskmanager/tasks/DownloadFile.java47
-rw-r--r--src/main/java/org/openslx/taskmanager/tasks/LdapSearch.java8
-rw-r--r--src/main/java/org/openslx/taskmanager/tasks/LighttpdHttps.java105
-rw-r--r--src/main/java/org/openslx/taskmanager/tasks/ReloadProxy.java26
10 files changed, 359 insertions, 36 deletions
diff --git a/scripts/install-https b/scripts/install-https
new file mode 100755
index 0000000..84a6184
--- /dev/null
+++ b/scripts/install-https
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+CERT="/etc/lighttpd/server.pem"
+
+op_disable ()
+{
+ [ -e "$CERT" ] || exit 0
+ rm -f -- "$CERT" || exit 1
+}
+
+op_test ()
+{
+ [ $# -eq 2 ] || exit 1
+ local K=$1
+ local C=$2
+ [ -r "$K" ] || exit 2
+ [ -r "$C" ] || exit 3
+ # Encrypt something, then decrypt again and compare
+ local TEST_IN=$(mktemp --tmpdir bwlp-XXXXXXXX)
+ local TEST_OUT=$(mktemp --tmpdir bwlp-XXXXXXXX)
+ local TEST_DIFF=$(mktemp --tmpdir bwlp-XXXXXXXX)
+ [ -z "$TEST_IN" ] && exit 4
+ [ -z "$TEST_OUT" ] && exit 5
+ [ -z "$TEST_DIFF" ] && exit 6
+ date > "$TEST_IN"
+ openssl smime -encrypt -binary -aes-256-cbc -in "$TEST_IN" -out "$TEST_OUT" -outform DER "$C" || exit 7
+ openssl smime -decrypt -binary -in "$TEST_OUT" -inform DER -out "$TEST_DIFF" -inkey "$K" || exit 8
+ diff -q "$TEST_IN" "$TEST_DIFF" || exit 9
+ exit 0 # No restart either way
+}
+
+op_import ()
+{
+ [ $# -eq 2 ] || exit 1
+ local K=$1
+ local C=$2
+ [ -r "$K" ] || exit 2
+ [ -r "$C" ] || exit 3
+ # Create server.pem
+ cat "$C" "$K" > "$CERT"
+ chmod 0600 "$CERT" || exit 4
+ rm -f -- "$C" "$K"
+}
+
+op_random ()
+{
+ [ -z "$1" ] && exit 1
+ openssl req -x509 -new -newkey rsa:4096 -keyout "$CERT" -out "$CERT" -days 5000 -nodes -subj "/C=DE/ST=Nowhere/L=Springfield/O=bwLehrpool/CN=$1" || exit 2
+}
+
+OP=$1
+shift
+
+case "$OP" in
+ --random) op_random "$@" ;;
+ --test) op_test "$@" ;;
+ --import) op_import "$@" ;;
+ --disable) op_disable ;;
+ *)
+ echo "Invalid operation: $1"
+ exit 1
+ ;;
+esac
+
+service lighttpd restart
+
+exit 0
+
diff --git a/scripts/system-backup b/scripts/system-backup
index 666180b..8042b08 100755
--- a/scripts/system-backup
+++ b/scripts/system-backup
@@ -15,7 +15,7 @@ fi
mkdir -p "$DIR"
cd "$DIR" || exit 1
-mysqldump --add-locks --defaults-extra-file=/etc/mysql/debian.cnf --default-character-set=utf8 --databases openslx bwLehrpool > db.sql
+mysqldump --defaults-extra-file=/etc/mysql/debian.cnf --add-locks --add-drop-database --default-character-set=utf8 --databases openslx bwLehrpool > db.sql
RET=$?
if [ $RET -ne 0 ]; then
echo "Database dump failed with exit code $RET"
@@ -25,6 +25,7 @@ fi
FILELIST="
/opt/openslx/configs
/opt/syncdaemon/config/identity.properties
+ /etc/lighttpd/server.pem
"
tar --ignore-failed-read -k -c -p -z -f files.tgz $FILELIST # no quotes here!
@@ -46,7 +47,7 @@ fi
chown www-data backup.tgz
chmod 0600 backup.tgz
-FILE="/tmp/bwlp-backup-$(date +%s).tgz"
+FILE="/tmp/bwlp-backup-$(date +%s)-${RANDOM}.tgz"
if ! mv backup.tgz "$FILE"; then
echo "moving backup to $FILE failed."
exit 1
diff --git a/scripts/system-restore b/scripts/system-restore
new file mode 100755
index 0000000..a95a185
--- /dev/null
+++ b/scripts/system-restore
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+BACKUP="$1"
+if [ -z "$BACKUP" ] || [ ! -f "$BACKUP" ]; then
+ echo "Backup file not found: $BACKUP"
+ exit 1
+fi
+
+if [ "$(whoami)" != "root" ]; then
+ echo "Must be running as root!"
+ exit 1
+fi
+
+DIR="/root/restore/$(date +%s)"
+
+if [ -d "$DIR" ]; then
+ echo "Restore already running!?"
+ exit 1
+fi
+
+mkdir -p "$DIR"
+if ! cd "$DIR"; then
+ echo "Could not cd to $DIR"
+ exit 1
+fi
+
+if ! tar --ignore-failed-read -x -f "$BACKUP"; then
+ echo "Could not extract $BACKUP - make sure it's a valid .tar.gz / .tgz"
+ exit 1
+fi
+
+if [ ! -f db.sql ]; then
+ echo "Error: database dump not found in backup - are you sure this is a valid backup?"
+ exit 1
+fi
+
+if [ ! -f files.tgz ]; then
+ echo "Error: files.tgz not found in backup - are your sure this is a valid backup?"
+ exit 1
+fi
+
+mysql --defaults-extra-file=/etc/mysql/debian.cnf --default-character-set=utf8 < db.sql
+RET=$?
+if [ $RET -ne 0 ]; then
+ echo "Error: Restoring database contents failed with exit code $RET"
+ exit 1
+fi
+echo "UPDATE openslx.property SET value = 'invalid' WHERE name = 'server-ip' LIMIT 1" | mysql --defaults-extra-file=/etc/mysql/debian.cnf --default-character-set=utf8
+
+tar --ignore-failed-read -x -f files.tgz -C /
+RET=$?
+if [ $RET -ne 0 ]; then
+ echo "WARNING: Restoring filesystem contents failed with exit code $RET - backup might be incomplete!"
+fi
+
+rm -rf -- "$DIR"
+rm -f -- "$BACKUP"
+
+echo "Success."
+
+exit 0
+
diff --git a/src/main/java/org/openslx/satserver/util/Exec.java b/src/main/java/org/openslx/satserver/util/Exec.java
index e7b27da..1f810eb 100644
--- a/src/main/java/org/openslx/satserver/util/Exec.java
+++ b/src/main/java/org/openslx/satserver/util/Exec.java
@@ -6,17 +6,23 @@ import java.io.IOException;
public class Exec
{
+ /**
+ * Run command, return exit status of process, or -1 on error
+ *
+ * @param command Command and arguments
+ * @return exit code
+ */
public static int sync( String... command )
{
ProcessBuilder pb = new ProcessBuilder( command );
pb.directory( new File( "/" ) );
- Process p;
- try {
- p = pb.start();
- return p.waitFor();
- } catch ( IOException | InterruptedException e ) {
- return -1;
- }
+ Process p;
+ try {
+ p = pb.start();
+ return p.waitFor();
+ } catch ( IOException | InterruptedException e ) {
+ return -1;
+ }
}
}
diff --git a/src/main/java/org/openslx/satserver/util/ProxyHandler.java b/src/main/java/org/openslx/satserver/util/ProxyHandler.java
index 9a702fe..f70a496 100644
--- a/src/main/java/org/openslx/satserver/util/ProxyHandler.java
+++ b/src/main/java/org/openslx/satserver/util/ProxyHandler.java
@@ -3,19 +3,36 @@ package org.openslx.satserver.util;
import org.openslx.network.ProxyConfiguration;
/**
- * Class for handling proxy configuration in task manager. Just configure proxy
- * setting system wide, if it was not done already.
+ * Class for handling proxy configuration in task manager.
+ *
* @author bjoern
- *
+ *
*/
-public class ProxyHandler {
+public class ProxyHandler
+{
private static boolean hasDoneConfigProxy = false;
+ private static final Object proxyMutex = new Object();
- public static void configProxy() {
- // Just configuring proxy settings system wide, if not done already.
- if (!hasDoneConfigProxy) {
- ProxyConfiguration.configProxy();
- hasDoneConfigProxy = true;
+ /**
+ * Do proxy setup if not done already
+ */
+ public static void configProxy()
+ {
+ configProxy( false );
+ }
+
+ /**
+ * Do proxy setup if not done already, or if explicitly forced.
+ *
+ * @param force Do setup even if already done
+ */
+ public static synchronized void configProxy( boolean force )
+ {
+ synchronized ( proxyMutex ) {
+ if ( !hasDoneConfigProxy || force ) {
+ ProxyConfiguration.configProxy();
+ hasDoneConfigProxy = true;
+ }
}
}
}
diff --git a/src/main/java/org/openslx/satserver/util/Util.java b/src/main/java/org/openslx/satserver/util/Util.java
index fe7eb6e..2df4c73 100644
--- a/src/main/java/org/openslx/satserver/util/Util.java
+++ b/src/main/java/org/openslx/satserver/util/Util.java
@@ -5,6 +5,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
@@ -30,6 +31,7 @@ public class Util
/**
* Close all given Closables. Can handle null references.
+ *
* @param streams one or more closables/streams
*/
public static void multiClose( Closeable... streams )
@@ -64,14 +66,15 @@ public class Util
}
return true;
}
-
- public static String readFileToString(String file)
+
+ public static String readFileToString( String file ) throws IOException
{
- try {
- return FileUtils.readFileToString( new File( file ) );
- } catch ( Exception e ) {
- return null;
- }
+ return FileUtils.readFileToString( new File( file ), StandardCharsets.UTF_8 );
}
-
+
+ public static void writeStringToFile( File file, String string ) throws IOException
+ {
+ FileUtils.writeStringToFile( file, string, StandardCharsets.UTF_8 );
+ }
+
}
diff --git a/src/main/java/org/openslx/taskmanager/tasks/DownloadFile.java b/src/main/java/org/openslx/taskmanager/tasks/DownloadFile.java
index ac9ea0e..1129200 100644
--- a/src/main/java/org/openslx/taskmanager/tasks/DownloadFile.java
+++ b/src/main/java/org/openslx/taskmanager/tasks/DownloadFile.java
@@ -6,9 +6,11 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
+import org.openslx.satserver.util.Exec;
import org.openslx.satserver.util.ProxyHandler;
import org.openslx.satserver.util.Util;
import org.openslx.taskmanager.api.AbstractTask;
@@ -22,11 +24,13 @@ public class DownloadFile extends AbstractTask
private String url = null;
@Expose
private String destination = null;
+ @Expose
+ private String gpg = null;
private Output status = new Output();
private static final String[] ALLOWED_DIRS =
- { "/srv/openslx/www/boot/" };
+ { "/srv/openslx/www/boot/", "/tmp/" };
@Override
protected boolean initTask()
@@ -50,30 +54,57 @@ public class DownloadFile extends AbstractTask
URLConnection connection = null;
BufferedInputStream in = null;
FileOutputStream fout = null;
-
+
// Handle proxy settings before opening connection for downloading.
ProxyHandler.configProxy();
try {
- File dest = new File( this.destination );
- FileUtils.forceMkdir( new File( dest.getParent() ) );
- FileUtils.deleteQuietly( dest );
+ File tmpFile = File.createTempFile( "bwlp-", ".tmp", null );
connection = new URL( this.url ).openConnection();
in = new BufferedInputStream( connection.getInputStream() );
- fout = new FileOutputStream( dest );
+ fout = new FileOutputStream( tmpFile );
status.size = connection.getContentLengthLong();
+ if ( status.size <= 0 ) // If size is unknown, fake progress...
+ status.progress = 10;
- final byte data[] = new byte[ 9000 ];
+ final byte data[] = new byte[ 90000 ];
int count;
while ( ( count = in.read( data, 0, data.length ) ) != -1 ) {
fout.write( data, 0, count );
status.complete += count;
if ( status.size > 0 )
status.progress = (int) ( 100l * status.complete / status.size );
+ else if ( status.progress < 99 && System.currentTimeMillis() % 20 == 0 )
+ status.progress++;
+ }
+ fout.close();
+ // If we have a gpg sig, validate
+ if ( this.gpg != null ) {
+ File gpgTempFile = null;
+ try {
+ gpgTempFile = File.createTempFile( "bwlp-", ".gpg", null );
+ Util.writeStringToFile( gpgTempFile, this.gpg );
+ } catch ( Exception e ) {
+ status.error = "Could not create temporary file for gpg signature";
+ return false;
+ }
+ if ( 0 != Exec.sync( "gpg", "--homedir", "/opt/openslx/gpg", "--verify", gpgTempFile.getAbsolutePath(), tmpFile.getAbsolutePath() ) ) {
+ status.error = "GPG signature of downloaded file not valid!";
+ return false;
+ }
+ gpgTempFile.delete();
+ }
+ // Move file to destination
+ File dest = new File( this.destination );
+ FileUtils.forceMkdir( new File( dest.getParent() ) );
+ if ( dest.exists() )
+ dest.delete();
+ if ( !tmpFile.renameTo( dest ) ) {
+ status.error = "Could not move downloaded file to destination directory!";
+ return false;
}
return true;
} catch ( IOException e ) {
status.error = "Download error: " + e.toString();
- FileUtils.deleteQuietly( new File( this.destination ) );
return false;
} finally {
Util.multiClose( in, fout );
diff --git a/src/main/java/org/openslx/taskmanager/tasks/LdapSearch.java b/src/main/java/org/openslx/taskmanager/tasks/LdapSearch.java
index 157b5e1..dbb76b1 100644
--- a/src/main/java/org/openslx/taskmanager/tasks/LdapSearch.java
+++ b/src/main/java/org/openslx/taskmanager/tasks/LdapSearch.java
@@ -93,9 +93,9 @@ public class LdapSearch extends SystemCommandTask
exitCode = 0;
if ( exitCode != 0 )
status.addMessage( "Exit code is " + exitCode );
- if ( exitCode == 0 && this.userCount < 4 )
+ if ( exitCode == 0 && this.userCount < 4 && !this.getDn )
status.addMessage( "Found less than 4 users. Are you sure you got the right credentials." );
- return this.userCount >= 4;
+ return this.userCount >= 4 || (this.getDn && status.dn != null);
}
@Override
@@ -105,6 +105,10 @@ public class LdapSearch extends SystemCommandTask
status.addMessage( "Found AD user " + line.substring( 16 ) + " :-)" );
this.userCount++;
}
+ if ( line.startsWith( "sAMAccountName:: " ) ) {
+ status.addMessage( "Found AD user " + line.substring( 17 ) + " :-)" );
+ this.userCount++;
+ }
if ( this.getDn && line.startsWith( "dn: " ) ) {
status.dn = line.substring( 4 );
}
diff --git a/src/main/java/org/openslx/taskmanager/tasks/LighttpdHttps.java b/src/main/java/org/openslx/taskmanager/tasks/LighttpdHttps.java
new file mode 100644
index 0000000..1b5e8e8
--- /dev/null
+++ b/src/main/java/org/openslx/taskmanager/tasks/LighttpdHttps.java
@@ -0,0 +1,105 @@
+package org.openslx.taskmanager.tasks;
+
+import java.io.File;
+
+import org.openslx.satserver.util.Exec;
+import org.openslx.satserver.util.Util;
+import org.openslx.taskmanager.api.AbstractTask;
+
+import com.google.gson.annotations.Expose;
+
+public class LighttpdHttps extends AbstractTask
+{
+
+ private Output status = new Output();
+
+ @Expose
+ private String importcert = null;
+ @Expose
+ private String importkey = null;
+
+ @Expose
+ private String proxyip = null;
+
+ @Override
+ protected boolean initTask()
+ {
+ this.setStatusObject( this.status );
+ return true;
+ }
+
+ @Override
+ protected boolean execute()
+ {
+ if ( this.importcert != null && this.importkey != null )
+ return createFromInput();
+ if ( this.proxyip != null )
+ return createRandom();
+ return disableHttps();
+ }
+
+ private boolean createRandom()
+ {
+ int ret = Exec.sync( "sudo", "-n", "-u", "root", "/opt/taskmanager/scripts/install-https", "--random", this.proxyip );
+ if ( ret != 0 ) {
+ status.error = "generator exited with code " + ret;
+ return false;
+ }
+ return true;
+ }
+
+ private boolean createFromInput()
+ {
+ // Import supplied certificate and key. Test if they are valid first
+ File tmpKey = null;
+ File tmpCert = null;
+ try {
+ try {
+ tmpKey = File.createTempFile( "bwlp-", ".pem" );
+ tmpCert = File.createTempFile( "bwlp-", ".pem" );
+ Util.writeStringToFile( tmpCert, this.importcert );
+ Util.writeStringToFile( tmpKey, this.importkey );
+ } catch ( Exception e ) {
+ status.error = "Could not create temporary files!";
+ return false;
+ }
+ int ret;
+ ret = Exec.sync( "/opt/taskmanager/scripts/install-https", "--test", tmpKey.getAbsolutePath(), tmpCert.getAbsolutePath() );
+ if ( ret != 0 ) {
+ status.error = "Given key and certificate do not match, or have invalid format (exit code: " + ret + ")";
+ return false;
+ }
+ ret = Exec.sync( "sudo", "-n", "-u", "root", "/opt/taskmanager/scripts/install-https", "--import", tmpKey.getAbsolutePath(), tmpCert.getAbsolutePath() );
+ if ( ret != 0 ) {
+ status.error = "import exited with code " + ret;
+ return false;
+ }
+ return true;
+ } finally {
+ if ( tmpKey != null )
+ tmpKey.delete();
+ if ( tmpCert != null )
+ tmpCert.delete();
+ }
+ }
+
+ private boolean disableHttps()
+ {
+ int ret = Exec.sync( "sudo", "-n", "-u", "root", "/opt/taskmanager/scripts/install-https", "--disable" );
+ if ( ret != 0 ) {
+ status.error = "import exited with code " + ret;
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Output - contains additional status data of this task
+ */
+ @SuppressWarnings( "unused" )
+ private static class Output
+ {
+ protected String error = null;
+ }
+
+}
diff --git a/src/main/java/org/openslx/taskmanager/tasks/ReloadProxy.java b/src/main/java/org/openslx/taskmanager/tasks/ReloadProxy.java
new file mode 100644
index 0000000..b3216dd
--- /dev/null
+++ b/src/main/java/org/openslx/taskmanager/tasks/ReloadProxy.java
@@ -0,0 +1,26 @@
+package org.openslx.taskmanager.tasks;
+
+import org.openslx.satserver.util.ProxyHandler;
+import org.openslx.taskmanager.api.AbstractTask;
+
+/**
+ * Just force reloading and setting up proxy configuration.
+ * Used after modifying settings in the webgui.
+ */
+public class ReloadProxy extends AbstractTask
+{
+
+ @Override
+ protected boolean initTask()
+ {
+ return true;
+ }
+
+ @Override
+ protected boolean execute()
+ {
+ ProxyHandler.configProxy( true );
+ return true;
+ }
+
+}