package org.openslx.taskmanager.tasks;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.io.FileUtils;
import org.openslx.satserver.util.Archive;
import org.openslx.satserver.util.Constants;
import org.openslx.satserver.util.Exec;
import org.openslx.satserver.util.Template;
import org.openslx.satserver.util.Util;
import org.openslx.taskmanager.api.AbstractTask;
import com.google.gson.annotations.Expose;
public class CreateLdapConfig extends AbstractTask
{
@Expose
private int moduleid = 0;
@Expose
private String filename = null;
@Expose
private String server = null;
@Expose
private String searchbase = null;
@Expose
private String binddn = null;
@Expose
private String bindpw = null;
@Expose
private String proxyip = null;
@Expose
private int proxyport = 0;
@Expose
private int adport = 0;
@Expose
private String home = null;
@Expose
private String fingerprint = "";
@Expose
private boolean plainldap = false;
private Output status = new Output();
@Override
protected boolean initTask()
{
// TODO: Check path is allowed
this.setStatusObject( this.status );
if ( filename == null || server == null || searchbase == null || proxyip == null || proxyport == 0 || moduleid == 0 ) {
status.error = "Missing argument to task";
return false;
}
if ( this.home == null )
this.home = "";
if ( this.binddn == null )
this.binddn = "";
if ( this.bindpw == null )
this.bindpw = "";
return true;
}
@Override
protected boolean execute()
{
TarArchiveOutputStream outArchive = null;
String keyFile = "/opt/ldadp/configs/" + this.moduleid + ".key.pem";
String certFile = "/opt/ldadp/configs/" + this.moduleid + ".crt.pem";
String uri = "ldaps://" + this.proxyip + ":" + this.proxyport + "/";
String cacertPath = "/etc/ldap-proxy.pem";
try {
// Generate keys
{
int ret = Exec.sync( 20, "openssl", "req",
"-x509", "-new", "-newkey", "rsa:4096", "-keyout", keyFile, "-out", certFile, "-days", "5000", "-nodes",
"-subj", "/C=DE/ST=Nowhere/L=Springfield/O=Dis/CN=" + this.proxyip );
if ( ret == -1 ) {
status.error = "openssl process didn't finish in time.";
} else if ( ret == -2 ) {
status.error = "Internal error generating certificate.";
} else if ( ret != 0 ) {
status.error = "openssl exited with code " + ret;
}
if ( ret != 0 )
return false;
}
// ldadp config
String ldadpConf = String.format(
"[%s]\n"
+ "binddn=%s\n"
+ "bindpw=%s\n"
+ "base=%s\n"
+ "home=%s\n"
+ "port=%s\n"
+ "fingerprint=%s\n"
+ "plainldap=%s\n"
+ "[local]\n"
+ "port=%s\n"
+ "cert=%s\n"
+ "privkey=%s\n"
+ "\n",
this.server,
this.binddn,
this.bindpw,
this.searchbase,
this.home,
this.adport,
this.fingerprint,
Boolean.toString( this.plainldap ),
this.proxyport,
certFile,
keyFile );
// Generic ldap config
final Template ldapConf = new Template( "./data/ad/ldap.conf.template" );
ldapConf.replace( "%URI%", uri );
ldapConf.replace( "%SEARCHBASE%", this.searchbase );
ldapConf.replace( "%CACERT%", cacertPath );
// sssd config
final Template sssdConf = new Template( "./data/ad/sssd.conf.template" );
sssdConf.replace( "%URI%", uri );
sssdConf.replace( "%SEARCHBASE%", this.searchbase );
sssdConf.replace( "%CACERT%", cacertPath );
String fileName = "/opt/ldadp/configs/" + this.moduleid + ".cfg";
try {
Files.deleteIfExists( Paths.get( this.filename ) );
} catch ( IOException e1 ) {
}
try {
FileUtils.writeStringToFile( new File( fileName ), ldadpConf, StandardCharsets.UTF_8 );
if ( 0 != Exec.sync( 10,
"/usr/bin/sudo",
"-n",
"-u", "root",
Constants.BASEDIR + "/scripts/ldadp-setperms",
Integer.toString( this.moduleid ) ) )
status.error = "Warning: Could not chown/chmod ldadp config!";
} catch ( IOException e ) {
status.error = e.toString();
return false;
}
try {
outArchive = Archive.createTarArchive( this.filename );
} catch ( IOException e ) {
status.error = "Could not create archive at " + this.filename;
return false;
}
// The cert we just created
if ( !Archive.tarAddFile( outArchive, cacertPath, new File( certFile ), 0644 ) ) {
status.error = "Could not add ldap-proxy.pem to module";
return false;
}
// nsswitch.conf with ldap enabled
if ( !Archive.tarAddFile( outArchive, "/etc/nsswitch.conf", new File( "./data/ad/nsswitch.conf" ), 0644 ) ) {
status.error = "Could not add nsswitch.conf to module";
return false;
}
// All the pam.d common-XXXX files
for ( String file : new String[] { "common-auth", "common-account", "common-session", "common-session-noninteractive", "common-password" } ) {
if ( !Archive.tarAddFile( outArchive, "/etc/pam.d/" + file, new File( "./data/ad/" + file ), 0644 ) ) {
status.error = "Could not add " + file + " to module";
return false;
}
}
// Home if present
if ( !Archive.tarAddFile( outArchive, "/opt/openslx/scripts/pam_script_mount_persistent", new File( "./data/ad/mountscript" ), 0644 ) ) {
status.error = "Could not add mount script to module";
return false;
}
boolean ret = Archive.tarCreateFileFromString( outArchive, "/etc/ldap.conf", ldapConf.toString(), 0644 )
&& Archive.tarCreateFileFromString( outArchive, "/etc/sssd/sssd.conf", sssdConf.toString(), 0600 )
&& Archive.tarCreateSymlink( outArchive, "/etc/ldap.conf", "/etc/ldap/ldap.conf" )
&& Archive.tarCreateSymlink( outArchive, "/etc/ldap.conf", "/etc/openldap/ldap.conf" )
&& Archive.tarCreateSymlink( outArchive, "../sssd.service", "/etc/systemd/system/basic.target.wants/sssd.service" );
if ( !ret ) {
status.error = "Could not add ldap configs to module";
}
return ret;
} catch ( IOException e ) {
status.error = e.toString();
return false;
} finally {
Util.multiClose( outArchive );
}
}
/**
* Output - contains additional status data of this task
*/
@SuppressWarnings( "unused" )
private static class Output
{
protected String error = null;
}
}