From 416c388904d3989fe18b84523f3da3c9531c3b86 Mon Sep 17 00:00:00 2001 From: Felix Sidokhine <felix.sidokhine@randstad.ca> Date: Tue, 12 May 2020 17:14:59 +0300 Subject: [PATCH] functional and tested flow for installation --- .../jami/jams/ad/connector/ADConnector.java | 4 +- .../authmodule/UserAuthenticationModule.java | 18 +++++ .../net/jami/datastore/dao/SystemDao.java | 19 ++++- .../net/jami/datastore/main/DataStore.java | 2 +- integration-test/install-server.py | 72 +++++++++++++++++ .../csr/builders/SystemAccountBuilder.java | 4 +- .../builders/SystemAccountBuilderTest.java | 6 +- jams-common/src/main/java/module-info.java | 1 + .../authentication/AuthenticationSource.java | 2 +- .../local/LocalAuthSettings.java | 11 +++ .../authmodule/AuthenticationModule.java | 1 + .../requests/CreateAuthSourceRequest.java | 19 +++++ .../objects/requests/CreateCARequest.java | 16 ++++ .../objects/requests/CredentialsRequest.java | 13 ++++ .../jams/common/objects/roots/X509Entity.java | 1 - .../jams/common/objects/roots/X509Fields.java | 1 + .../common/objects/system/SystemAccount.java | 25 +++++- .../jams/common/server/ServerSettings.java | 1 + .../net/jami/jams/common/utils/Validator.java | 28 +++++++ .../java/net/jami/jams/server/Server.java | 17 ++-- .../core/workflows/InstallationFinalizer.java | 78 +++++++++++++++++++ .../servlets/api/install/CachedObjects.java | 17 ++++ .../api/install/CreateAuthSourceServlet.java | 36 ++++++++- .../servlets/api/install/CreateCAServlet.java | 12 ++- .../install/CreateGeneralSettingsServlet.java | 23 ------ .../install/CreateServerSettingsServlet.java | 35 +++++++++ .../api/install/StartInstallServlet.java | 14 +++- .../jams/ldap/connector/LDAPConnector.java | 5 +- .../connector/service/UserProfileService.java | 4 +- 29 files changed, 432 insertions(+), 53 deletions(-) create mode 100644 integration-test/install-server.py create mode 100644 jams-common/src/main/java/net/jami/jams/common/authentication/local/LocalAuthSettings.java create mode 100644 jams-common/src/main/java/net/jami/jams/common/objects/requests/CreateAuthSourceRequest.java create mode 100644 jams-common/src/main/java/net/jami/jams/common/objects/requests/CreateCARequest.java create mode 100644 jams-common/src/main/java/net/jami/jams/common/objects/requests/CredentialsRequest.java create mode 100644 jams-common/src/main/java/net/jami/jams/common/utils/Validator.java create mode 100644 jams-server/src/main/java/net/jami/jams/server/core/workflows/InstallationFinalizer.java create mode 100644 jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CachedObjects.java delete mode 100644 jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateGeneralSettingsServlet.java create mode 100644 jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateServerSettingsServlet.java diff --git a/ad-connector/src/main/java/net/jami/jams/ad/connector/ADConnector.java b/ad-connector/src/main/java/net/jami/jams/ad/connector/ADConnector.java index 2be71eb9..de213aa6 100644 --- a/ad-connector/src/main/java/net/jami/jams/ad/connector/ADConnector.java +++ b/ad-connector/src/main/java/net/jami/jams/ad/connector/ADConnector.java @@ -87,8 +87,8 @@ public class ADConnector implements AuthenticationSource { } @Override - public boolean testConfiguration(String configuration) { - return false; + public boolean test() { + return authenticate(settings.getUsername(), settings.getPassword()); } @Override diff --git a/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java b/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java index 2a99fb96..ce3fc7ea 100644 --- a/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java +++ b/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java @@ -33,6 +33,8 @@ public class UserAuthenticationModule implements AuthenticationModule { public UserAuthenticationModule(DataStore dataStore, CertificateAuthority certificateAuthority) { UserAuthenticationModule.datastore = dataStore; UserAuthenticationModule.certificateAuthority = certificateAuthority; + authenticationSources.put(new AuthModuleKey("LOCAL",AuthenticationSourceType.LOCAL),datastore); + log.info("Started authentication module - default local source is already enabled!"); } @Override @@ -103,4 +105,20 @@ public class UserAuthenticationModule implements AuthenticationModule { public HashMap<AuthModuleKey, AuthenticationSource> getAuthSources(){ return authenticationSources; } + + @Override + public boolean testModuleConfiguration(AuthenticationSourceType type, String settings) { + try { + String className = ""; + if (type.equals(AuthenticationSourceType.AD)) className = AD_CONNECTOR_CLASS; + if (type.equals(AuthenticationSourceType.LDAP)) className = LDAP_CONNECTOR_CLASS; + Class<?> cls = LibraryLoader.classLoader.loadClass(className); + AuthenticationSource source = (AuthenticationSource) cls.getConstructor(String.class).newInstance(settings); + return source.test(); + } + catch (Exception e){ + log.error("The testing of the source was unsuccessful!"); + return false; + } + } } diff --git a/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java b/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java index 1d269872..63545e50 100644 --- a/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java +++ b/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java @@ -17,7 +17,7 @@ public class SystemDao extends AbstractDao<SystemAccount> { try { this.setTableName("system"); this.setTClass(SystemAccount.class); - String createTable = "CREATE TABLE system (" + + String createTable = "CREATE TABLE "+ this.getTableName() + " (" + "entity varchar(255), " + "certificate varchar(5000), "+ "privatekey varchar(5000)," + @@ -35,7 +35,22 @@ public class SystemDao extends AbstractDao<SystemAccount> { @Override public boolean storeObject(SystemAccount object) { - return false; + SQLConnection connection = DataStore.connectionPool.getConnection(); + try{ + PreparedStatement ps = connection.getConnection().prepareStatement("INSERT INTO system " + + "(entity,certificate,privatekey)" + + "VALUES " + + "(?, ?, ?)"); + ps = object.getInsert(ps); + return ps.execute(); + } + catch (Exception e){ + log.error("An error has occurred while trying to store a system entity: " + e.toString()); + return false; + } + finally { + DataStore.connectionPool.returnConnection(connection); + } } @Override diff --git a/datastore/src/main/java/net/jami/datastore/main/DataStore.java b/datastore/src/main/java/net/jami/datastore/main/DataStore.java index 76ecca92..457f9074 100644 --- a/datastore/src/main/java/net/jami/datastore/main/DataStore.java +++ b/datastore/src/main/java/net/jami/datastore/main/DataStore.java @@ -67,7 +67,7 @@ public class DataStore implements AuthenticationSource { } @Override - public boolean testConfiguration(String configuration) { + public boolean test() { return true; } diff --git a/integration-test/install-server.py b/integration-test/install-server.py new file mode 100644 index 00000000..ca837e9b --- /dev/null +++ b/integration-test/install-server.py @@ -0,0 +1,72 @@ +import requests +import json + +data = {} +data['username'] = "admin" +data['password'] = "abc123" + +header = {} +header['Content-type'] = "application/json" + +response = requests.put('http://localhost:8080/api/install/start',data=json.dumps(data),headers=header) +if response.status_code == 200: + print("Succesfully created the administrative user!") + token = json.loads(response.text)['token'] +else: + print("Could not create admin user, the test has failed!") + + +header['x-token'] = token + +data = {} +data['fields'] = {} +data['fields']['commonName'] = "TEST CA" +data['fields']['country'] = "FR" +data['fields']['lifetime'] = 10000000 + +response = requests.post('http://localhost:8080/api/install/ca',data=json.dumps(data),headers=header) +if response.status_code == 200: + print("Added CA parameters!") +else: + print("Could not add CA parameters, the test has failed") + + +data = {} +data['type'] = "LDAP" +data['ldapSettings'] = {} +data['ldapSettings']['useStartTLS'] = True +data['ldapSettings']['realm'] = "savoirfairelinux" +data['ldapSettings']['baseDN'] = "ou=users,dc=savoirfairelinux,dc=net" +data['ldapSettings']['host'] = "ldap://annuaire.savoirfairelinux.com" +data['ldapSettings']['username'] = "cn=sipallow,ou=dsa,dc=savoirfairelinux,dc=net" +data['ldapSettings']['password'] = "Dewaaghei3Yo" +data['ldapSettings']['usernameField'] = "uid" +data['ldapSettings']['fieldMappings'] = {} +data['ldapSettings']['fieldMappings']['givenName'] = "FirstName" +data['ldapSettings']['fieldMappings']['sn'] = "LastName" +data['ldapSettings']['fieldMappings']['jpegPhoto'] = "ProfilePicture" +data['ldapSettings']['fieldMappings']['mail'] = "Email" +data['ldapSettings']['fieldMappings']['telephoneNumber'] = "PhoneNumber" +data['ldapSettings']['fieldMappings']['mobile'] = "MobileNumber" +data['ldapSettings']['fieldMappings']['facsimileTelephoneNumber'] = "FaxNumber" +data['ldapSettings']['fieldMappings']['extensionName'] = "PhoneNumberExtension" +data['ldapSettings']['fieldMappings']['o'] = "Organization" + +response = requests.post('http://localhost:8080/api/install/auth',data=json.dumps(data),headers=header) +if response.status_code == 200: + print("Added LDAP parameters!") +else: + print("Could not add LDAP parameters, the test has failed") + + +data['serverDomain'] = "http://localhost" +data['signingAlgorithm'] = "SHA512WITHRSA" +data['crlLifetime'] = 100000 +data['userLifetime'] = 100000 +data['deviceLifetime'] = 100000 + +response = requests.post('http://localhost:8080/api/install/settings',data=json.dumps(data),headers=header) +if response.status_code == 200: + print("Finished Installation Successfully!") +else: + print("Could not finish installation") \ No newline at end of file diff --git a/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilder.java b/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilder.java index f6ab1e77..d656c8ce 100644 --- a/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilder.java +++ b/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilder.java @@ -29,7 +29,7 @@ public class SystemAccountBuilder { new X500Name(systemAccount.getX509Fields().getDN()), new BigInteger(256, new SecureRandom()), new Date(System.currentTimeMillis()), - new Date(System.currentTimeMillis() + systemAccount.getLifetime()), + new Date(System.currentTimeMillis() + systemAccount.getX509Fields().getLifetime()), new X500Name(systemAccount.getX509Fields().getDN()), SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()) ); @@ -54,7 +54,7 @@ public class SystemAccountBuilder { new JcaX509CertificateHolder(JamsCA.CA.getCertificate()).getSubject(), new BigInteger(256, new SecureRandom()), new Date(System.currentTimeMillis()), - new Date(System.currentTimeMillis() + systemAccount.getLifetime()), + new Date(System.currentTimeMillis() + systemAccount.getX509Fields().getLifetime()), new X500Name("CN=" + systemAccount.getX509Fields().getDN()), SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()) ); diff --git a/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java b/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java index 71dba13f..c9fdd70d 100644 --- a/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java +++ b/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java @@ -38,7 +38,7 @@ class SystemAccountBuilderTest { caAccount.setX509Fields(new X509Fields()); caAccount.getX509Fields().setCommonName("Test CA"); caAccount.getX509Fields().setCountry("FR"); - caAccount.setLifetime(10000000L); + caAccount.getX509Fields().setLifetime(10000000L); caAccount = SystemAccountBuilder.generateCA(caAccount); Assertions.assertNotNull(caAccount.getCertificate(),"CA Certificate was not generated!"); @@ -49,7 +49,7 @@ class SystemAccountBuilderTest { ocspAccount.setSystemAccountType(SystemAccountType.OCSP); ocspAccount.setX509Fields(new X509Fields()); ocspAccount.getX509Fields().setCommonName("OCSP Server"); - ocspAccount.setLifetime(10000000L); + ocspAccount.getX509Fields().setLifetime(10000000L); ocspAccount = SystemAccountBuilder.generateOCSP(ocspAccount); Assertions.assertNotNull(ocspAccount.getCertificate(),"OCSP Certificate was not generated!"); @@ -76,7 +76,7 @@ class SystemAccountBuilderTest { caAccount.setX509Fields(new X509Fields()); caAccount.getX509Fields().setCommonName("Test CA"); caAccount.getX509Fields().setCountry("FR"); - caAccount.setLifetime(10000000L); + caAccount.getX509Fields().setLifetime(10000000L); caAccount = SystemAccountBuilder.generateCA(caAccount); Assertions.assertNotNull(caAccount.getCertificate(),"CA Certificate was not generated!"); CertificateAuthorityConfig config = new CertificateAuthorityConfig(); diff --git a/jams-common/src/main/java/module-info.java b/jams-common/src/main/java/module-info.java index fcc8f2d3..2d38ebbb 100644 --- a/jams-common/src/main/java/module-info.java +++ b/jams-common/src/main/java/module-info.java @@ -48,6 +48,7 @@ module jams.common { exports net.jami.jams.common.jami; exports net.jami.jams.common.authmodule; exports net.jami.jams.common.server; + exports net.jami.jams.common.authentication.local; requires jdk.crypto.cryptoki; requires java.base; requires java.sql; diff --git a/jams-common/src/main/java/net/jami/jams/common/authentication/AuthenticationSource.java b/jams-common/src/main/java/net/jami/jams/common/authentication/AuthenticationSource.java index ab1e1b5c..1b27f44b 100644 --- a/jams-common/src/main/java/net/jami/jams/common/authentication/AuthenticationSource.java +++ b/jams-common/src/main/java/net/jami/jams/common/authentication/AuthenticationSource.java @@ -9,7 +9,7 @@ public interface AuthenticationSource { UserProfile[] getUserProfile(String queryString, String field); boolean authenticate(String username, String password); AuthenticationSourceInfo getInfo(); - boolean testConfiguration(String configuration); + boolean test(); boolean updatePassword(User user, String password); } diff --git a/jams-common/src/main/java/net/jami/jams/common/authentication/local/LocalAuthSettings.java b/jams-common/src/main/java/net/jami/jams/common/authentication/local/LocalAuthSettings.java new file mode 100644 index 00000000..d9024e34 --- /dev/null +++ b/jams-common/src/main/java/net/jami/jams/common/authentication/local/LocalAuthSettings.java @@ -0,0 +1,11 @@ +package net.jami.jams.common.authentication.local; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class LocalAuthSettings { + private Boolean publicNames; + private String publicNameServer; +} diff --git a/jams-common/src/main/java/net/jami/jams/common/authmodule/AuthenticationModule.java b/jams-common/src/main/java/net/jami/jams/common/authmodule/AuthenticationModule.java index 78f0860e..a9e7b6ad 100644 --- a/jams-common/src/main/java/net/jami/jams/common/authmodule/AuthenticationModule.java +++ b/jams-common/src/main/java/net/jami/jams/common/authmodule/AuthenticationModule.java @@ -13,4 +13,5 @@ public interface AuthenticationModule { AuthenticationResult authenticateUser(X509Certificate[] certificates); String validateAndGetUsername(String token); HashMap<AuthModuleKey, AuthenticationSource> getAuthSources(); + boolean testModuleConfiguration(AuthenticationSourceType type, String configuration); } diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/requests/CreateAuthSourceRequest.java b/jams-common/src/main/java/net/jami/jams/common/objects/requests/CreateAuthSourceRequest.java new file mode 100644 index 00000000..a167c150 --- /dev/null +++ b/jams-common/src/main/java/net/jami/jams/common/objects/requests/CreateAuthSourceRequest.java @@ -0,0 +1,19 @@ +package net.jami.jams.common.objects.requests; + +import lombok.Getter; +import lombok.Setter; +import net.jami.jams.common.authentication.AuthenticationSourceType; +import net.jami.jams.common.authentication.activedirectory.ActiveDirectorySettings; +import net.jami.jams.common.authentication.ldap.LDAPSettings; +import net.jami.jams.common.authentication.local.LocalAuthSettings; + +@Getter +@Setter +public class CreateAuthSourceRequest { + + private AuthenticationSourceType type; + private LDAPSettings ldapSettings; + private ActiveDirectorySettings activeDirectorySettings; + private LocalAuthSettings localAuthSettings; + +} diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/requests/CreateCARequest.java b/jams-common/src/main/java/net/jami/jams/common/objects/requests/CreateCARequest.java new file mode 100644 index 00000000..82b6b57f --- /dev/null +++ b/jams-common/src/main/java/net/jami/jams/common/objects/requests/CreateCARequest.java @@ -0,0 +1,16 @@ +package net.jami.jams.common.objects.requests; + +import lombok.Getter; +import lombok.Setter; +import net.jami.jams.common.objects.roots.X509Fields; + +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + +@Getter +@Setter +public class CreateCARequest { + private X509Fields fields; + private X509Certificate certificate; + private PrivateKey privateKey; +} diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/requests/CredentialsRequest.java b/jams-common/src/main/java/net/jami/jams/common/objects/requests/CredentialsRequest.java new file mode 100644 index 00000000..c899e2ed --- /dev/null +++ b/jams-common/src/main/java/net/jami/jams/common/objects/requests/CredentialsRequest.java @@ -0,0 +1,13 @@ +package net.jami.jams.common.objects.requests; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CredentialsRequest { + + private String username; + private String password; + +} diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/roots/X509Entity.java b/jams-common/src/main/java/net/jami/jams/common/objects/roots/X509Entity.java index d56b96c1..c4de1279 100644 --- a/jams-common/src/main/java/net/jami/jams/common/objects/roots/X509Entity.java +++ b/jams-common/src/main/java/net/jami/jams/common/objects/roots/X509Entity.java @@ -15,5 +15,4 @@ public class X509Entity { //These can be null because they are only used if this is a request. private X509Fields x509Fields; private PKCS10CertificationRequest certificationRequest; - private Long lifetime; } diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/roots/X509Fields.java b/jams-common/src/main/java/net/jami/jams/common/objects/roots/X509Fields.java index fc635c69..68cd4596 100644 --- a/jams-common/src/main/java/net/jami/jams/common/objects/roots/X509Fields.java +++ b/jams-common/src/main/java/net/jami/jams/common/objects/roots/X509Fields.java @@ -12,6 +12,7 @@ public class X509Fields { private String state; private String organization; private String organizationUnit; + private Long lifetime; public String getDN(){ StringBuilder stringBuilder = new StringBuilder(); diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/system/SystemAccount.java b/jams-common/src/main/java/net/jami/jams/common/objects/system/SystemAccount.java index 4764ec09..eb335177 100644 --- a/jams-common/src/main/java/net/jami/jams/common/objects/system/SystemAccount.java +++ b/jams-common/src/main/java/net/jami/jams/common/objects/system/SystemAccount.java @@ -3,10 +3,33 @@ package net.jami.jams.common.objects.system; import lombok.Getter; import lombok.Setter; import net.jami.jams.common.objects.roots.X509Entity; +import net.jami.jams.common.serialization.database.DatabaseObject; +import net.jami.jams.common.utils.X509Utils; + +import java.sql.PreparedStatement; @Getter @Setter -public class SystemAccount extends X509Entity { +public class SystemAccount extends X509Entity implements DatabaseObject { private SystemAccountType systemAccountType; + + + @Override + public PreparedStatement getInsert(PreparedStatement ps) throws Exception { + ps.setString(1, systemAccountType.toString()); + ps.setString(2, X509Utils.getPEMStringFromCertificate(this.getCertificate())); + ps.setString(3,X509Utils.getPEMStringFromPrivateKey(this.getPrivateKey())); + return ps; + } + + @Override + public PreparedStatement getDelete(PreparedStatement ps) throws Exception { + return null; + } + + @Override + public PreparedStatement getUpdate(PreparedStatement ps) throws Exception { + return null; + } } diff --git a/jams-common/src/main/java/net/jami/jams/common/server/ServerSettings.java b/jams-common/src/main/java/net/jami/jams/common/server/ServerSettings.java index fbfeb1bf..de761bc4 100644 --- a/jams-common/src/main/java/net/jami/jams/common/server/ServerSettings.java +++ b/jams-common/src/main/java/net/jami/jams/common/server/ServerSettings.java @@ -10,5 +10,6 @@ public class ServerSettings { private String ldapConfiguration; private String caConfiguration; private String activeDirectoryConfiguration; + private String localDirectoryConfiguration; } diff --git a/jams-common/src/main/java/net/jami/jams/common/utils/Validator.java b/jams-common/src/main/java/net/jami/jams/common/utils/Validator.java new file mode 100644 index 00000000..ae9ce1e4 --- /dev/null +++ b/jams-common/src/main/java/net/jami/jams/common/utils/Validator.java @@ -0,0 +1,28 @@ +package net.jami.jams.common.utils; + +import net.jami.jams.common.authentication.AuthenticationSource; +import net.jami.jams.common.authentication.AuthenticationSourceType; +import net.jami.jams.common.objects.requests.CreateCARequest; + +import java.math.BigInteger; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; + +public class Validator { + + public static boolean validateCARequests(CreateCARequest request){ + if(request.getCertificate() != null && request.getPrivateKey() != null){ + if(request.getCertificate().getBasicConstraints() != -1){ + RSAPublicKey rsaPublicKey = (RSAPublicKey) request.getCertificate().getPublicKey(); + RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) request.getPrivateKey(); + return rsaPublicKey.getModulus().equals( rsaPrivateKey.getModulus() ) + && BigInteger.valueOf( 2 ).modPow( rsaPublicKey.getPublicExponent() + .multiply( rsaPrivateKey.getPrivateExponent() ).subtract( BigInteger.ONE ), + rsaPublicKey.getModulus() ).equals( BigInteger.ONE ); + } + return false; + } + return true; + } + +} diff --git a/jams-server/src/main/java/net/jami/jams/server/Server.java b/jams-server/src/main/java/net/jami/jams/server/Server.java index ae941021..24119dbf 100644 --- a/jams-server/src/main/java/net/jami/jams/server/Server.java +++ b/jams-server/src/main/java/net/jami/jams/server/Server.java @@ -3,7 +3,7 @@ package net.jami.jams.server; import com.jsoniter.JsonIterator; import lombok.extern.slf4j.Slf4j; import net.jami.datastore.main.DataStore; -import net.jami.jams.common.authentication.AuthenticationSource; +import net.jami.jams.common.authentication.AuthenticationSourceType; import net.jami.jams.common.authmodule.AuthenticationModule; import net.jami.jams.common.cryptoengineapi.CertificateAuthority; import net.jami.jams.common.serialization.JsoniterRegistry; @@ -16,16 +16,11 @@ import net.jami.jams.server.startup.CryptoEngineLoader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @Slf4j public class Server { - public static List<String> authModuleClasses = new ArrayList<>(); - public static HashMap<String, AuthenticationSource> authenticationSources = new HashMap<>(); public static AtomicBoolean isInstalled = new AtomicBoolean(false); static { @@ -49,8 +44,6 @@ public class Server { //Step 1: Create the data store. dataStore = new DataStore("jdbc:derby:jams;create=true"); - - isInstalled.set(new File(System.getProperty("user.dir") + File.separator + "config.json").exists()); log.info("Server is already installed: " + isInstalled.get()); ServerSettings serverSettings = null; @@ -60,6 +53,14 @@ public class Server { serverSettings = JsonIterator.deserialize(path.readAllBytes(),ServerSettings.class); certificateAuthority = CryptoEngineLoader.loadCertificateAuthority(serverSettings.getCaConfiguration(),dataStore); userAuthenticationModule = AuthModuleLoader.loadAuthenticationModule(dataStore,certificateAuthority); + if(serverSettings.getLdapConfiguration() != null) + userAuthenticationModule.attachAuthSource(AuthenticationSourceType.LDAP, + serverSettings.getLdapConfiguration() + ); + if(serverSettings.getActiveDirectoryConfiguration() != null){ + userAuthenticationModule.attachAuthSource(AuthenticationSourceType.AD, + serverSettings.getActiveDirectoryConfiguration()); + } } catch (Exception e){ log.error("Could not load configuration file or initialize some components - this is critical"); diff --git a/jams-server/src/main/java/net/jami/jams/server/core/workflows/InstallationFinalizer.java b/jams-server/src/main/java/net/jami/jams/server/core/workflows/InstallationFinalizer.java new file mode 100644 index 00000000..4d2aac96 --- /dev/null +++ b/jams-server/src/main/java/net/jami/jams/server/core/workflows/InstallationFinalizer.java @@ -0,0 +1,78 @@ +package net.jami.jams.server.core.workflows; + +import com.jsoniter.output.JsonStream; +import lombok.extern.slf4j.Slf4j; +import net.jami.jams.common.authentication.AuthenticationSourceType; +import net.jami.jams.common.objects.roots.X509Fields; +import net.jami.jams.common.objects.system.SystemAccount; +import net.jami.jams.common.objects.system.SystemAccountType; +import net.jami.jams.common.server.ServerSettings; +import net.jami.jams.server.Server; +import net.jami.jams.server.servlets.api.install.CachedObjects; +import net.jami.jams.server.startup.AuthModuleLoader; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; + +import static net.jami.jams.server.Server.*; + +@Slf4j +public class InstallationFinalizer { + + public boolean finalizeInstallation() { + //Basically here we build the config and flush it. + try { + log.info("Building configuration from submitted variables..."); + ServerSettings serverSettings = new ServerSettings(); + serverSettings.setCaConfiguration(JsonStream.serialize(CachedObjects.certificateAuthorityConfig)); + if (CachedObjects.activeDirectorySettings != null) + serverSettings.setActiveDirectoryConfiguration(JsonStream.serialize(CachedObjects.activeDirectorySettings)); + if (CachedObjects.ldapSettings != null) + serverSettings.setLdapConfiguration(JsonStream.serialize(CachedObjects.ldapSettings)); + if (CachedObjects.localAuthSettings != null) + serverSettings.setLocalDirectoryConfiguration(JsonStream.serialize(CachedObjects.localAuthSettings)); + + //Now flush the server settings. + OutputStream os = new FileOutputStream(new File("config.json")); + os.write(JsonStream.serialize(serverSettings).getBytes()); + os.flush(); + os.close(); + log.info("Settings succesfully saved to configuration file..."); + log.info("Attempting to save the CA and generate the OCSP certificate..."); + if (CachedObjects.createCARequest.getFields() != null) { + SystemAccount caAccount = new SystemAccount(); + caAccount.setSystemAccountType(SystemAccountType.CA); + caAccount.setX509Fields(CachedObjects.createCARequest.getFields()); + certificateAuthority.getSignedCertificate(caAccount); + dataStore.getSystemDao().storeObject(caAccount); + log.info("Succesfully stored CA"); + certificateAuthority.init(serverSettings.getCaConfiguration(), caAccount, null); + SystemAccount ocspAccount = new SystemAccount(); + ocspAccount.setX509Fields(new X509Fields()); + ocspAccount.getX509Fields().setCommonName("OCSP Server Certificate"); + ocspAccount.setSystemAccountType(SystemAccountType.OCSP); + ocspAccount.getX509Fields().setLifetime(caAccount.getX509Fields().getLifetime()); + certificateAuthority.getSignedCertificate(ocspAccount); + dataStore.getSystemDao().storeObject(ocspAccount); + log.info("Successfully created and stored the OCSP certificate"); + certificateAuthority.init(serverSettings.getCaConfiguration(), caAccount, ocspAccount); + log.info("Succesfully inited the certificate authority with the appropriate settings..."); + } + log.info("Initializing the selected authentication providers"); + userAuthenticationModule = AuthModuleLoader.loadAuthenticationModule(dataStore, certificateAuthority); + if(serverSettings.getActiveDirectoryConfiguration() != null) + userAuthenticationModule.attachAuthSource(AuthenticationSourceType.AD,serverSettings.getActiveDirectoryConfiguration()); + if(serverSettings.getLdapConfiguration() != null) + userAuthenticationModule.attachAuthSource(AuthenticationSourceType.LDAP,serverSettings.getLdapConfiguration()); + Server.isInstalled.set(true); + log.info("The installation has completed succesfully, you can now use JAMS!"); + } catch (Exception e) { + log.error("Could not save settings to disk with error: " + e.toString()); + return false; + } + return true; + } + + +} diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CachedObjects.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CachedObjects.java new file mode 100644 index 00000000..939fef55 --- /dev/null +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CachedObjects.java @@ -0,0 +1,17 @@ +package net.jami.jams.server.servlets.api.install; + +import net.jami.jams.common.authentication.activedirectory.ActiveDirectorySettings; +import net.jami.jams.common.authentication.ldap.LDAPSettings; +import net.jami.jams.common.authentication.local.LocalAuthSettings; +import net.jami.jams.common.cryptoengineapi.CertificateAuthorityConfig; +import net.jami.jams.common.objects.requests.CreateCARequest; + +public class CachedObjects { + + public static String endpoint = "start"; + public static CertificateAuthorityConfig certificateAuthorityConfig; + public static CreateCARequest createCARequest; + public static LDAPSettings ldapSettings; + public static ActiveDirectorySettings activeDirectorySettings; + public static LocalAuthSettings localAuthSettings; +} diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateAuthSourceServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateAuthSourceServlet.java index 6cf14b18..018ab94b 100644 --- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateAuthSourceServlet.java +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateAuthSourceServlet.java @@ -1,13 +1,21 @@ package net.jami.jams.server.servlets.api.install; +import com.jsoniter.JsonIterator; +import com.jsoniter.output.JsonStream; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import net.jami.jams.common.authentication.AuthenticationSourceType; +import net.jami.jams.common.objects.requests.CreateAuthSourceRequest; +import net.jami.jams.common.objects.requests.CreateCARequest; +import net.jami.jams.common.utils.Validator; import java.io.IOException; +import static net.jami.jams.server.Server.userAuthenticationModule; + @WebServlet("/api/install/auth") public class CreateAuthSourceServlet extends HttpServlet { @@ -18,6 +26,32 @@ public class CreateAuthSourceServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doPost(req, resp); + CreateAuthSourceRequest authSourceRequest = JsonIterator.deserialize( + req.getInputStream().readAllBytes(),CreateAuthSourceRequest.class); + CachedObjects.localAuthSettings = null; + CachedObjects.activeDirectorySettings = null; + CachedObjects.ldapSettings = null; + boolean error = false; + switch (authSourceRequest.getType()){ + case LOCAL: + CachedObjects.localAuthSettings = authSourceRequest.getLocalAuthSettings(); + break; + case LDAP: + if(userAuthenticationModule.testModuleConfiguration(AuthenticationSourceType.LDAP, + JsonStream.serialize(authSourceRequest.getLdapSettings()))){ + CachedObjects.ldapSettings = authSourceRequest.getLdapSettings(); + } + else error = true; + break; + case AD: + if(userAuthenticationModule.testModuleConfiguration(AuthenticationSourceType.AD, + JsonStream.serialize(authSourceRequest.getActiveDirectorySettings()))) { + CachedObjects.activeDirectorySettings = authSourceRequest.getActiveDirectorySettings(); + } + else error = true; + break; + } + if(error) resp.sendError(500,"The supplied configuration is invalid or the connectivity tests has failed"); + else CachedObjects.endpoint = "/api/install/settings"; } } diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateCAServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateCAServlet.java index 30a5c6fd..63faac21 100644 --- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateCAServlet.java +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateCAServlet.java @@ -1,10 +1,13 @@ package net.jami.jams.server.servlets.api.install; +import com.jsoniter.JsonIterator; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import net.jami.jams.common.objects.requests.CreateCARequest; +import net.jami.jams.common.utils.Validator; import java.io.IOException; @@ -18,6 +21,13 @@ public class CreateCAServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doPost(req, resp); + CreateCARequest caRequest = JsonIterator.deserialize(req.getInputStream().readAllBytes(),CreateCARequest.class); + if(!Validator.validateCARequests(caRequest)){ + resp.sendError(500,"Certificate was either not a CA or the private key did not match the certificate"); + } + else{ + CachedObjects.createCARequest = caRequest; + CachedObjects.endpoint = "/api/install/auth"; + } } } diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateGeneralSettingsServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateGeneralSettingsServlet.java deleted file mode 100644 index e6529d42..00000000 --- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateGeneralSettingsServlet.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.jami.jams.server.servlets.api.install; - -import jakarta.servlet.ServletException; -import jakarta.servlet.annotation.WebServlet; -import jakarta.servlet.http.HttpServlet; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import java.io.IOException; - -@WebServlet("/api/install/settings") -public class CreateGeneralSettingsServlet extends HttpServlet { - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doGet(req, resp); - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doPost(req, resp); - } -} diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateServerSettingsServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateServerSettingsServlet.java new file mode 100644 index 00000000..4fdc6399 --- /dev/null +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateServerSettingsServlet.java @@ -0,0 +1,35 @@ +package net.jami.jams.server.servlets.api.install; + +import com.jsoniter.JsonIterator; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import net.jami.jams.common.cryptoengineapi.CertificateAuthorityConfig; +import net.jami.jams.server.core.workflows.InstallationFinalizer; + +import java.io.IOException; + +@WebServlet("/api/install/settings") +public class CreateServerSettingsServlet extends HttpServlet { + + InstallationFinalizer finalizer = new InstallationFinalizer(); + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + super.doGet(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + CertificateAuthorityConfig config = JsonIterator.deserialize( + req.getInputStream().readAllBytes(),CertificateAuthorityConfig.class); + CachedObjects.certificateAuthorityConfig = config; + if(!finalizer.finalizeInstallation()) { + resp.sendError(500, "Could not store settings, a problem occured with finishing the installation"); + return; + } + resp.sendRedirect("/"); + } +} diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java index d6739ecf..c5e451e8 100644 --- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java +++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java @@ -1,5 +1,6 @@ package net.jami.jams.server.servlets.api.install; +import com.jsoniter.JsonIterator; import com.jsoniter.output.JsonStream; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; @@ -9,6 +10,7 @@ import jakarta.servlet.http.HttpServletResponse; import net.jami.jams.common.authentication.AuthenticationSourceType; import net.jami.jams.common.authmodule.AuthenticationResult; import net.jami.jams.common.dao.StatementList; +import net.jami.jams.common.objects.requests.CredentialsRequest; import net.jami.jams.common.objects.user.AccessLevel; import net.jami.jams.common.objects.user.User; @@ -31,10 +33,12 @@ public class StartInstallServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + CredentialsRequest credentialsRequest = JsonIterator.deserialize(req.getInputStream().readAllBytes(),CredentialsRequest.class); AuthenticationResult res = null; - if(req.getParameter("username") != null && req.getParameter("password") != null){ - res = processUsernamePasswordAuth(req.getParameter("username"),req.getParameter("password")); + if(credentialsRequest.getUsername() != null && credentialsRequest.getPassword() != null){ + res = processUsernamePasswordAuth(credentialsRequest.getUsername(),credentialsRequest.getPassword()); } + resp.setHeader("endpoint",CachedObjects.endpoint); resp.getOutputStream().write(JsonStream.serialize(res).getBytes()); } @@ -47,15 +51,17 @@ public class StartInstallServlet extends HttpServlet { resp.sendError(500,"We have tried to create an administrative account where one already exists!"); return; } + CredentialsRequest credentialsRequest = JsonIterator.deserialize(req.getInputStream().readAllBytes(),CredentialsRequest.class); //The admin user has no X509 properties. User user = new User(); - user.setUsername(req.getParameter("username")); - user.setPassword(req.getParameter("password")); + user.setUsername(credentialsRequest.getUsername()); + user.setPassword(credentialsRequest.getPassword()); user.setUserType(AuthenticationSourceType.LOCAL); user.setRealm("LOCAL"); user.setAccessLevel(AccessLevel.ADMIN); dataStore.getUserDao().storeObject(user); AuthenticationResult res = processUsernamePasswordAuth(user.getUsername(),user.getPassword()); resp.getOutputStream().write(JsonStream.serialize(res).getBytes()); + CachedObjects.endpoint = "/api/install/ca"; } } diff --git a/ldap-connector/src/main/java/net/jami/jams/ldap/connector/LDAPConnector.java b/ldap-connector/src/main/java/net/jami/jams/ldap/connector/LDAPConnector.java index ac6cd0cf..6865ba19 100644 --- a/ldap-connector/src/main/java/net/jami/jams/ldap/connector/LDAPConnector.java +++ b/ldap-connector/src/main/java/net/jami/jams/ldap/connector/LDAPConnector.java @@ -60,10 +60,11 @@ public class LDAPConnector implements AuthenticationSource { } @Override - public boolean testConfiguration(String configuration) { - return false; + public boolean test() { + return (getUserProfile("*","LOGON_NAME").length != 0); } + @Override public boolean updatePassword(User user, String password) { return false; diff --git a/ldap-connector/src/main/java/net/jami/jams/ldap/connector/service/UserProfileService.java b/ldap-connector/src/main/java/net/jami/jams/ldap/connector/service/UserProfileService.java index b760025b..fd881025 100644 --- a/ldap-connector/src/main/java/net/jami/jams/ldap/connector/service/UserProfileService.java +++ b/ldap-connector/src/main/java/net/jami/jams/ldap/connector/service/UserProfileService.java @@ -32,8 +32,10 @@ public class UserProfileService { SearchResponse res = search.execute(buildRequest(queryString,field)); if (res.getEntries().size() > 0) profiles = new UserProfile[res.getEntries().size()]; Iterator<LdapEntry> iterator = res.getEntries().iterator(); - for(int i=0; i< profiles.length; i++){ + int i = 0; + while(iterator.hasNext()){ profiles[i] = profileFromResponse(iterator.next()); + i++; } return profiles; } catch (Exception e) { -- GitLab