diff --git a/graylog2-server/src/main/java/org/graylog2/security/AESTools.java b/graylog2-server/src/main/java/org/graylog2/security/AESTools.java index 31dde237fc1f..d68199da1019 100644 --- a/graylog2-server/src/main/java/org/graylog2/security/AESTools.java +++ b/graylog2-server/src/main/java/org/graylog2/security/AESTools.java @@ -20,6 +20,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nullable; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; @@ -27,6 +28,7 @@ public class AESTools { private static final Logger LOG = LoggerFactory.getLogger(AESTools.class); + @Nullable public static String encrypt(String plainText, String encryptionKey, String salt) { try { Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126Padding", "SunJCE"); @@ -36,9 +38,10 @@ public static String encrypt(String plainText, String encryptionKey, String salt } catch (Exception e) { LOG.error("Could not encrypt value.", e); } - return null; + return null; } + @Nullable public static String decrypt(String cipherText, String encryptionKey, String salt) { try { Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126Padding", "SunJCE"); @@ -50,5 +53,4 @@ public static String decrypt(String cipherText, String encryptionKey, String sal } return null; } - } diff --git a/graylog2-server/src/main/java/org/graylog2/security/ldap/LdapSettingsService.java b/graylog2-server/src/main/java/org/graylog2/security/ldap/LdapSettingsService.java index 5e91b73c120e..ee040206809d 100644 --- a/graylog2-server/src/main/java/org/graylog2/security/ldap/LdapSettingsService.java +++ b/graylog2-server/src/main/java/org/graylog2/security/ldap/LdapSettingsService.java @@ -19,10 +19,10 @@ import org.graylog2.plugin.database.PersistedService; import org.graylog2.shared.security.ldap.LdapSettings; -/** - * @author Dennis Oelkers - */ +import javax.annotation.Nullable; + public interface LdapSettingsService extends PersistedService { + @Nullable LdapSettings load(); void delete(); diff --git a/graylog2-server/src/main/java/org/graylog2/security/ldap/LdapSettingsServiceImpl.java b/graylog2-server/src/main/java/org/graylog2/security/ldap/LdapSettingsServiceImpl.java index 50f666b1e54c..566607badf79 100644 --- a/graylog2-server/src/main/java/org/graylog2/security/ldap/LdapSettingsServiceImpl.java +++ b/graylog2-server/src/main/java/org/graylog2/security/ldap/LdapSettingsServiceImpl.java @@ -25,6 +25,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nullable; import javax.inject.Inject; import java.util.List; @@ -39,9 +40,9 @@ public LdapSettingsServiceImpl(MongoConnection mongoConnection, LdapSettingsImpl } @Override + @Nullable public LdapSettings load() { - DBObject query = new BasicDBObject(); - final List results = query(LdapSettingsImpl.class, query); + final List results = query(LdapSettingsImpl.class, new BasicDBObject()); if (results.size() == 0) { return null; } @@ -51,13 +52,16 @@ public LdapSettings load() { results.size()); return null; } - final DBObject settingsObject = results.get(0); - return ldapSettingsFactory.create((ObjectId) settingsObject.get("_id"), settingsObject.toMap()); + final DBObject settings = results.get(0); + final LdapSettingsImpl ldapSettings = ldapSettingsFactory.create((ObjectId) settings.get("_id"), settings.toMap()); + if (null == ldapSettings.getSystemPassword()) { + return null; + } + return ldapSettings; } @Override public void delete() { - DBObject query = new BasicDBObject(); - destroyAll(LdapSettingsImpl.class, query); + destroyAll(LdapSettingsImpl.class); } } diff --git a/graylog2-server/src/test/java/org/graylog2/security/ldap/LdapSettingsServiceImplTest.java b/graylog2-server/src/test/java/org/graylog2/security/ldap/LdapSettingsServiceImplTest.java new file mode 100644 index 000000000000..48e1e2b0cee4 --- /dev/null +++ b/graylog2-server/src/test/java/org/graylog2/security/ldap/LdapSettingsServiceImplTest.java @@ -0,0 +1,119 @@ +/** + * This file is part of Graylog. + * + * Graylog is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Graylog is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Graylog. If not, see . + */ +package org.graylog2.security.ldap; + +import com.lordofthejars.nosqlunit.annotation.UsingDataSet; +import com.lordofthejars.nosqlunit.core.LoadStrategyEnum; +import com.lordofthejars.nosqlunit.mongodb.InMemoryMongoDb; +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import org.bson.types.ObjectId; +import org.graylog2.Configuration; +import org.graylog2.database.MongoConnectionRule; +import org.graylog2.shared.security.ldap.LdapSettings; +import org.graylog2.users.RoleService; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.net.URI; +import java.util.Map; + +import static com.lordofthejars.nosqlunit.mongodb.InMemoryMongoDb.InMemoryMongoRuleBuilder.newInMemoryMongoDbRule; +import static org.assertj.core.api.Assertions.assertThat; + +public class LdapSettingsServiceImplTest { + @ClassRule + public static final InMemoryMongoDb IN_MEMORY_MONGO_DB = newInMemoryMongoDbRule().build(); + + @Rule + public final MongoConnectionRule mongoRule = MongoConnectionRule.build("test"); + + @Rule + public final MockitoRule mockitoRule = MockitoJUnit.rule(); + + private final Configuration configuration = new Configuration() { + @Override + public String getPasswordSecret() { + return "asdfasdfasdfasdfasdf"; + } + }; + private final LdapSettingsImpl.Factory factory = new LdapSettingsImpl.Factory() { + @Override + public LdapSettingsImpl createEmpty() { + return new LdapSettingsImpl(configuration, roleService); + } + + @Override + public LdapSettingsImpl create(ObjectId objectId, Map fields) { + return new LdapSettingsImpl(configuration, roleService, objectId, fields); + } + }; + + @Mock + private RoleService roleService; + private LdapSettingsServiceImpl ldapSettingsService; + + @Before + public void setUp() throws Exception { + ldapSettingsService = new LdapSettingsServiceImpl(mongoRule.getMongoConnection(), factory); + } + + @Test + @UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT) + public void loadReturnsLdapSettings() throws Exception { + final LdapSettings ldapSettings = ldapSettingsService.load(); + assertThat(ldapSettings).isNotNull(); + assertThat(ldapSettings.getId()).isEqualTo("54e3deadbeefdeadbeefaffe"); + assertThat(ldapSettings.getUri()).isEqualTo(URI.create("ldap://localhost:389")); + assertThat(ldapSettings.getSystemPassword()).isEqualTo("password"); + } + + @Test + @UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations = "LdapSettingsServiceImplTest-invalid-password.json") + public void loadReturnNullIfPasswordSecretIsWrong() throws Exception { + final LdapSettings ldapSettings = ldapSettingsService.load(); + assertThat(ldapSettings).isNull(); + } + + @Test + @UsingDataSet(loadStrategy = LoadStrategyEnum.DELETE_ALL) + public void loadReturnsNullIfDatabaseIsEmpty() throws Exception { + assertThat(ldapSettingsService.load()).isNull(); + } + + @Test + @UsingDataSet(loadStrategy = LoadStrategyEnum.DELETE_ALL) + public void loadReturnsNullIfDatabaseHasMoreThanOneEntry() throws Exception { + final DBCollection collection = mongoRule.getMongoConnection().getDatabase().getCollection("ldap_settings"); + collection.insert(new BasicDBObject("foo", "bar"), new BasicDBObject("quux", "baz")); + assertThat(ldapSettingsService.load()).isNull(); + } + + @Test + @UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT) + public void deleteRemovesAllLdapSettings() throws Exception { + final DBCollection collection = mongoRule.getMongoConnection().getDatabase().getCollection("ldap_settings"); + assertThat(collection.count()).isEqualTo(1L); + ldapSettingsService.delete(); + assertThat(collection.count()).isEqualTo(0); + } +} diff --git a/graylog2-server/src/test/resources/org/graylog2/security/ldap/LdapSettingsServiceImplTest-invalid-password.json b/graylog2-server/src/test/resources/org/graylog2/security/ldap/LdapSettingsServiceImplTest-invalid-password.json new file mode 100644 index 000000000000..803b9f67c435 --- /dev/null +++ b/graylog2-server/src/test/resources/org/graylog2/security/ldap/LdapSettingsServiceImplTest-invalid-password.json @@ -0,0 +1,26 @@ +{ + "ldap_settings": [ + { + "_id": { + "$oid": "54e3deadbeefdeadbeefaffe" + }, + "use_start_tls": false, + "system_password": "deadbeefcafebabe12345678deadbeef", + "principal_search_pattern": "(&(objectClass=inetOrgPerson)(uid={0}))", + "username_attribute": "cn", + "system_password_salt": "455f07a629b2d830", + "system_username": "uid=admin,ou=system", + "trust_all_certificates": false, + "group_search_base": "cn=users,dc=example,dc=com", + "default_group": "55ce0ae8c02622ddd63de149", + "group_search_pattern": "(objectClass=groupOfNames)", + "active_directory": false, + "enabled": true, + "group_id_attribute": "cn", + "search_base": "cn=users,dc=example,dc=com", + "group_role_mapping_list": [ + ], + "ldap_uri": "ldap://localhost:389" + } + ] +} diff --git a/graylog2-server/src/test/resources/org/graylog2/security/ldap/LdapSettingsServiceImplTest.json b/graylog2-server/src/test/resources/org/graylog2/security/ldap/LdapSettingsServiceImplTest.json new file mode 100644 index 000000000000..d1b0bd75ac52 --- /dev/null +++ b/graylog2-server/src/test/resources/org/graylog2/security/ldap/LdapSettingsServiceImplTest.json @@ -0,0 +1,26 @@ +{ + "ldap_settings": [ + { + "_id": { + "$oid": "54e3deadbeefdeadbeefaffe" + }, + "use_start_tls": false, + "system_password": "0ebc21625f0e65ee36adb65e0448703a", + "principal_search_pattern": "(&(objectClass=inetOrgPerson)(uid={0}))", + "username_attribute": "cn", + "system_password_salt": "455f07a629b2d830", + "system_username": "uid=admin,ou=system", + "trust_all_certificates": false, + "group_search_base": "cn=users,dc=example,dc=com", + "default_group": "55ce0ae8c02622ddd63de149", + "group_search_pattern": "(objectClass=groupOfNames)", + "active_directory": false, + "enabled": true, + "group_id_attribute": "cn", + "search_base": "cn=users,dc=example,dc=com", + "group_role_mapping_list": [ + ], + "ldap_uri": "ldap://localhost:389" + } + ] +}