/* * Copyright 2017 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.thoughtworks.go.config; import com.thoughtworks.go.config.server.security.ldap.BaseConfig; import com.thoughtworks.go.config.server.security.ldap.BasesConfig; import com.thoughtworks.go.domain.config.Admin; import com.thoughtworks.go.security.GoCipher; import com.thoughtworks.go.util.ReflectionUtil; import org.bouncycastle.crypto.InvalidCipherTextException; import org.junit.Test; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.*; public class SecurityConfigTest { public static final Role ROLE1 = new RoleConfig(new CaseInsensitiveString("role1"), new RoleUser(new CaseInsensitiveString("chris")), new RoleUser(new CaseInsensitiveString("jez"))); public static final Role ROLE2 = new RoleConfig(new CaseInsensitiveString("role2"), new RoleUser(new CaseInsensitiveString("chris"))); public static final Role[] DEFAULT_ROLES = new Role[]{ROLE1, ROLE2}; @Test public void shouldNotSaySecurityEnabledIfSecurityHasNoAuthenticatorsDefined() { ServerConfig serverConfig = new ServerConfig(); assertFalse("Security should not be enabled by default", serverConfig.isSecurityEnabled()); } @Test public void shouldSaySecurityEnabledIfLdapSecurityEnabled() { ServerConfig serverConfig = server(ldap(), null, admins()); assertTrue("Security should be enabled when LDAP config present", serverConfig.isSecurityEnabled()); } @Test public void twoEmptySecurityConfigsShouldBeTheSame() throws Exception { SecurityConfig one = new SecurityConfig(); SecurityConfig two = new SecurityConfig(); assertThat(one, is(two)); } @Test public void shouldSaySecurityEnabledIfPasswordFileSecurityEnabled() { ServerConfig serverConfig = server(null, pwordFile(), admins()); assertTrue("Security should be enabled when password file config present", serverConfig.isSecurityEnabled()); } @Test public void shouldKnowIfUserIsAdmin() throws Exception { SecurityConfig security = security(new LdapConfig(new GoCipher()), new PasswordFileConfig(), admins(user("chris"))); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("chris"))), is(true)); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("evilHacker"))), is(true)); security = security(null, pwordFile(), admins(user("chris"))); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("chris"))), is(true)); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("evilHacker"))), is(false)); } @Test public void shouldKnowIfRoleIsAdmin() throws Exception { SecurityConfig security = security(null, pwordFile(), admins(role("role1"))); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("chris"))), is(true)); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("jez"))), is(true)); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("evilHacker"))), is(false)); } @Test public void shouldNotCareIfValidUserInRoleOrUser() throws Exception { SecurityConfig security = security(null, pwordFile(), admins(role("role2"))); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("chris"))), is(true)); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("jez"))), is(false)); security = security(null, pwordFile(), admins(role("role2"), user("jez"))); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("chris"))), is(true)); assertThat(security.isAdmin(new AdminUser(new CaseInsensitiveString("jez"))), is(true)); } @Test public void shouldValidateRoleAsAdmin() throws Exception { SecurityConfig security = security(null, pwordFile(), admins(role("role2"))); assertThat(security.isAdmin(new AdminRole(new CaseInsensitiveString("role2"))), is(true)); } @Test public void shouldReturnTheMemberRoles() throws Exception { SecurityConfig securityConfig = security(null, pwordFile(), admins()); assertUserRoles(securityConfig, "chris", DEFAULT_ROLES); assertUserRoles(securityConfig, "jez", DEFAULT_ROLES[0]); assertUserRoles(securityConfig, "loser"); } @Test public void shouldReturnTrueIfDeletingARoleGoesThroughSuccessfully() throws Exception { SecurityConfig securityConfig = security(null, pwordFile(), admins()); securityConfig.deleteRole(ROLE1); assertUserRoles(securityConfig, "chris", ROLE2); assertUserRoles(securityConfig, "jez"); } @Test public void shouldBombIfDeletingARoleWhichDoesNotExist() throws Exception { try { SecurityConfig securityConfig = security(null, pwordFile(), admins()); securityConfig.deleteRole(new RoleConfig(new CaseInsensitiveString("role99"))); fail("Should have blown up with an exception on the previous line as deleting role99 should blow up"); } catch (RuntimeException e) { assertTrue(Pattern.compile("does not exist").matcher(e.getMessage()).find()); } } @Test public void testEqualsAndHashCode() { SecurityConfig one = new SecurityConfig(null, null, true, null, true); SecurityConfig two = new SecurityConfig(null, null, true, null, false); SecurityConfig three = new SecurityConfig(null, null, true, null, true); assertThat(one, is(three)); assertThat(one, not(is(two))); assertThat(one.hashCode(), is(three.hashCode())); assertThat(one.hashCode(), not(is(two.hashCode()))); } @Test public void shouldNotUpdateManagerPasswordForLDAPIfNotChangedOrNull() throws InvalidCipherTextException { SecurityConfig securityConfig = new SecurityConfig(); securityConfig.modifyLdap(new LdapConfig("ldap://uri", "dn", "p", null, true, new BasesConfig(new BaseConfig("")), "")); assertThat(ReflectionUtil.getField(securityConfig.ldapConfig(), "managerPassword"), is("")); assertThat(securityConfig.ldapConfig().managerPassword(), is("p")); String encryptedPassword = new GoCipher().encrypt("p"); assertThat(securityConfig.ldapConfig().getEncryptedManagerPassword(), is(encryptedPassword)); securityConfig.modifyLdap(new LdapConfig("ldap://uri", "dn", "notP", null, false, new BasesConfig(new BaseConfig("")), "")); assertThat(ReflectionUtil.getField(securityConfig.ldapConfig(), "managerPassword"), is("")); assertThat(securityConfig.ldapConfig().managerPassword(), is("p")); assertThat(securityConfig.ldapConfig().getEncryptedManagerPassword(), is(encryptedPassword)); securityConfig.modifyLdap(new LdapConfig("ldap://uri", "dn", "", null, true, new BasesConfig(new BaseConfig("")), "")); assertThat(securityConfig.ldapConfig().managerPassword(), is("")); assertThat(securityConfig.ldapConfig().getEncryptedManagerPassword(), is(nullValue())); } @Test public void shouldTellSecurityMethodHasNotChanged() { assertFalse(new SecurityConfig().hasSecurityMethodChanged(new SecurityConfig())); } @Test public void shouldBeAbleToTellIfSecurityMethodChangedFromNothingToLdap() { SecurityConfig ldapSecurity = new SecurityConfig(); ldapSecurity.modifyLdap(new LdapConfig("ldap://uri", "dn", "p", null, true, new BasesConfig(new BaseConfig("")), "")); assertTrue(new SecurityConfig().hasSecurityMethodChanged(ldapSecurity)); } private void assertUserRoles(SecurityConfig securityConfig, String username, Role... roles) { assertThat(securityConfig.memberRoleFor(new CaseInsensitiveString(username)), is(Arrays.asList(roles))); } private ServerConfig server(LdapConfig ldap, PasswordFileConfig pwordFile, AdminsConfig admins) { return new ServerConfig("", security(ldap, pwordFile, admins)); } public static SecurityConfig security(LdapConfig ldap, PasswordFileConfig pwordFile, AdminsConfig admins) { ldap = ldap == null ? new LdapConfig(new GoCipher()) : ldap; pwordFile = pwordFile == null ? new PasswordFileConfig() : pwordFile; SecurityConfig security = new SecurityConfig(ldap, pwordFile, true, admins); for (Role role : DEFAULT_ROLES) { security.addRole(role); } return security; } public static AdminsConfig admins(Admin... admins) { return new AdminsConfig(admins); } public static AdminUser user(String name) { return new AdminUser(new CaseInsensitiveString(name)); } public static AdminRole role(String name) { return new AdminRole(new CaseInsensitiveString(name)); } public static LdapConfig ldap() { return new LdapConfig("test", "test", "test", null, true, new BasesConfig(new BaseConfig("test")), "test"); } public static PasswordFileConfig pwordFile() { return new PasswordFileConfig("test"); } @Test public void shouldGetPluginRolesWhichBelogsToSpecifiedPlugin() throws Exception { SecurityConfig securityConfig = new SecurityConfig(); securityConfig.addRole(new PluginRoleConfig("foo", "ldap")); securityConfig.addRole(new PluginRoleConfig("bar", "github")); securityConfig.addRole(new RoleConfig(new CaseInsensitiveString("xyz"))); securityConfig.securityAuthConfigs().add(new SecurityAuthConfig("ldap", "cd.go.ldap")); securityConfig.securityAuthConfigs().add(new SecurityAuthConfig("github", "cd.go.github")); List<PluginRoleConfig> pluginRolesConfig = securityConfig.getPluginRoles("cd.go.ldap"); assertThat(pluginRolesConfig, hasSize(1)); assertThat(pluginRolesConfig, contains(new PluginRoleConfig("foo", "ldap"))); } @Test public void getPluginRolesConfig_shouldReturnNothingWhenBadPluginIdSpecified() throws Exception { SecurityConfig securityConfig = new SecurityConfig(); securityConfig.addRole(new PluginRoleConfig("foo", "ldap")); securityConfig.addRole(new PluginRoleConfig("bar", "github")); securityConfig.addRole(new RoleConfig(new CaseInsensitiveString("xyz"))); securityConfig.securityAuthConfigs().add(new SecurityAuthConfig("ldap", "cd.go.ldap")); securityConfig.securityAuthConfigs().add(new SecurityAuthConfig("github", "cd.go.github")); List<PluginRoleConfig> pluginRolesConfig = securityConfig.getPluginRoles("non-existant-plugin"); assertThat(pluginRolesConfig, hasSize(0)); } }