/* * 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.server.service; import com.thoughtworks.go.config.*; import com.thoughtworks.go.helper.GoConfigMother; import com.thoughtworks.go.helper.StageConfigMother; import com.thoughtworks.go.server.domain.Username; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import java.util.HashSet; import java.util.List; import java.util.Set; import static com.thoughtworks.go.helper.PipelineTemplateConfigMother.createTemplate; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.notNull; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class SecurityServiceTest { private GoConfigService goConfigService; private SecurityService securityService; @Before public void setUp() { goConfigService = mock(GoConfigService.class); when(goConfigService.security()).thenReturn(new SecurityConfig()); securityService = new SecurityService(goConfigService); } @Test public void shouldReturnTrueIfUserIsOnlyATemplateAdmin() { final Username user = new Username(new CaseInsensitiveString("user")); when(goConfigService.isGroupAdministrator(user.getUsername())).thenReturn(false); when(goConfigService.isUserAdmin(user)).thenReturn(false); SecurityService spy = spy(securityService); doReturn(true).when(spy).isAuthorizedToViewAndEditTemplates(user); assertThat(spy.canViewAdminPage(new Username(new CaseInsensitiveString("user"))), is(true)); } @Test public void shouldBeAbleToViewAdminPageIfUserCanViewTemplates() { CaseInsensitiveString username = new CaseInsensitiveString("user"); final Username user = new Username(username); CruiseConfig config = new BasicCruiseConfig(); config.addTemplate(createTemplate("s", new Authorization(new ViewConfig(new AdminUser(username))))); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isGroupAdministrator(user.getUsername())).thenReturn(false); when(goConfigService.isUserAdmin(user)).thenReturn(false); assertThat(securityService.canViewAdminPage(user), is(true)); } @Test public void shouldReturnFalseForViewingAdminPageForARegularUser() { final Username user = new Username(new CaseInsensitiveString("user")); CruiseConfig config = new BasicCruiseConfig(); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isUserAdmin(user)).thenReturn(false); when(goConfigService.isGroupAdministrator(user.getUsername())).thenReturn(false); SecurityService spy = spy(securityService); doReturn(false).when(spy).isAuthorizedToViewAndEditTemplates(user); doReturn(false).when(spy).isAuthorizedToViewTemplates(user); assertThat(spy.canViewAdminPage(user), is(false)); } @Test public void shouldBeAbleToTellIfAUserIsAnAdmin() { Username username = new Username(new CaseInsensitiveString("user")); when(goConfigService.isUserAdmin(username)).thenReturn(Boolean.TRUE); assertThat(securityService.canViewAdminPage(username), is(true)); verify(goConfigService).isUserAdmin(username); } @Test public void shouldBeAbleToTellIfAnUserCanViewTheAdminPage() { final Username user = new Username(new CaseInsensitiveString("user")); when(goConfigService.isGroupAdministrator(user.getUsername())).thenReturn(Boolean.TRUE); assertThat(securityService.canViewAdminPage(new Username(new CaseInsensitiveString("user"))), is(true)); } @Test public void shouldBeAbleToTellIfAnUserISNotAllowedToViewTheAdminPage() { final Username user = new Username(new CaseInsensitiveString("user")); when(goConfigService.isGroupAdministrator(user.getUsername())).thenReturn(Boolean.FALSE); SecurityService spy = spy(securityService); doReturn(false).when(spy).isAuthorizedToViewAndEditTemplates(user); doReturn(false).when(spy).isAuthorizedToViewTemplates(user); assertThat(spy.canViewAdminPage(new Username(new CaseInsensitiveString("user"))), is(false)); } @Test public void shouldBeAbleToCreatePipelineIfUserIsSuperOrPipelineGroupAdmin() { final Username groupAdmin = new Username(new CaseInsensitiveString("groupAdmin")); when(goConfigService.isGroupAdministrator(groupAdmin.getUsername())).thenReturn(Boolean.TRUE); final Username admin = new Username(new CaseInsensitiveString("admin")); when(goConfigService.isGroupAdministrator(admin.getUsername())).thenReturn(Boolean.TRUE); assertThat(securityService.canCreatePipelines(new Username(new CaseInsensitiveString("groupAdmin"))), is(true)); assertThat(securityService.canCreatePipelines(new Username(new CaseInsensitiveString("admin"))), is(true)); } @Test public void shouldNotBeAbleToCreatePipelineIfUserIsTemplateAdmin() { final Username user = new Username(new CaseInsensitiveString("user")); when(goConfigService.isGroupAdministrator(user.getUsername())).thenReturn(false); when(goConfigService.isUserAdmin(user)).thenReturn(false); SecurityService spy = spy(securityService); doReturn(true).when(spy).isAuthorizedToViewAndEditTemplates(user); assertThat(spy.canCreatePipelines(new Username(new CaseInsensitiveString("user"))), is(false)); } @Test public void shouldSayThatAUserIsAuthorizedToEditTemplateWhenTheUserIsAnAdminOfThisTemplate() throws Exception { CruiseConfig config = new BasicCruiseConfig(); String templateName = "template"; CaseInsensitiveString templateAdminName = new CaseInsensitiveString("templateAdmin"); GoConfigMother.enableSecurityWithPasswordFile(config); GoConfigMother.addUserAsSuperAdmin(config, "theSuperAdmin"); config.addTemplate(createTemplate(templateName, new Authorization(new AdminsConfig(new AdminUser(templateAdminName))))); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isUserAdmin(new Username(templateAdminName))).thenReturn(false); assertThat(securityService.isAuthorizedToEditTemplate(templateName, new Username(templateAdminName)), is(true)); assertThat(securityService.isAuthorizedToEditTemplate(templateName, new Username(new CaseInsensitiveString("someOtherUserWhoIsNotAnAdmin"))), is(false)); } @Test public void shouldSayThatAUserIsAuthorizedToEditTemplateWhenTheUserIsASuperAdmin() throws Exception { CruiseConfig cruiseConfig = new BasicCruiseConfig(); String adminName = "theSuperAdmin"; String templateName = "template"; GoConfigMother.enableSecurityWithPasswordFile(cruiseConfig); GoConfigMother.addUserAsSuperAdmin(cruiseConfig, adminName).addTemplate(createTemplate(templateName)); when(goConfigService.cruiseConfig()).thenReturn(cruiseConfig); when(goConfigService.isUserAdmin(new Username(new CaseInsensitiveString(adminName)))).thenReturn(true); assertThat(securityService.isAuthorizedToEditTemplate(templateName, new Username(new CaseInsensitiveString(adminName))), is(true)); } @Test public void shouldSayThatAUserIsAuthorizedToViewAndEditTemplatesWhenTheUserHasPermissionsForAtLeastOneTemplate() throws Exception { CruiseConfig config = new BasicCruiseConfig(); String theSuperAdmin = "theSuperAdmin"; String templateName = "template"; String secondTemplateName = "secondTemplate"; CaseInsensitiveString templateAdminName = new CaseInsensitiveString("templateAdmin"); CaseInsensitiveString secondTemplateAdminName = new CaseInsensitiveString("secondTemplateAdmin"); GoConfigMother.enableSecurityWithPasswordFile(config); GoConfigMother.addUserAsSuperAdmin(config, theSuperAdmin); config.addTemplate(createTemplate(templateName, new Authorization(new AdminsConfig(new AdminUser(templateAdminName))))); config.addTemplate(createTemplate(secondTemplateName, new Authorization(new AdminsConfig(new AdminUser(secondTemplateAdminName))))); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isUserAdmin(new Username(templateAdminName))).thenReturn(false); when(goConfigService.isUserAdmin(new Username(secondTemplateName))).thenReturn(false); when(goConfigService.isUserAdmin(new Username(new CaseInsensitiveString(theSuperAdmin)))).thenReturn(true); when(goConfigService.isUserAdmin(new Username(new CaseInsensitiveString("someOtherUserWhoIsNotAdminOfAnyTemplates")))).thenReturn(false); assertThat(securityService.isAuthorizedToViewAndEditTemplates(new Username(templateAdminName)), is(true)); assertThat(securityService.isAuthorizedToViewAndEditTemplates(new Username(secondTemplateAdminName)), is(true)); assertThat(securityService.isAuthorizedToViewAndEditTemplates(new Username(new CaseInsensitiveString(theSuperAdmin))), is(true)); assertThat(securityService.isAuthorizedToViewAndEditTemplates(new Username(new CaseInsensitiveString("someOtherUserWhoIsNotAdminOfAnyTemplates"))), is(false)); } @Test public void shouldReturnTrueForSuperAdminToViewTemplateConfiguration() { BasicCruiseConfig cruiseConfig = getCruiseConfigWithSecurityEnabled(); String templateName = "template"; Username admin = new Username(new CaseInsensitiveString("admin")); GoConfigMother.addUserAsSuperAdmin(cruiseConfig, "admin").addTemplate(createTemplate(templateName)); when(goConfigService.cruiseConfig()).thenReturn(cruiseConfig); when(goConfigService.isUserAdmin(admin)).thenReturn(true); assertThat(securityService.isAuthorizedToViewTemplate(templateName, admin), is(true)); } @Test public void shouldReturnTrueForTemplateAdminsToViewTemplateConfiguration() { CruiseConfig config = getCruiseConfigWithSecurityEnabled(); CaseInsensitiveString templateAdmin = new CaseInsensitiveString("templateAdmin"); String templateName = "template"; config.addTemplate(createTemplate(templateName, new Authorization(new AdminsConfig(new AdminUser(templateAdmin))))); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isUserAdmin(new Username(templateAdmin))).thenReturn(false); assertThat(securityService.isAuthorizedToViewTemplate(templateName, new Username(templateAdmin)), is(true)); } @Test public void shouldReturnTrueForTemplateViewUsersToViewTemplateConfiguration() { CruiseConfig config = getCruiseConfigWithSecurityEnabled(); CaseInsensitiveString templateViewUser = new CaseInsensitiveString("templateView"); String templateName = "template"; config.addTemplate(createTemplate(templateName, new Authorization(new ViewConfig(new AdminUser(templateViewUser))))); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isUserAdmin(new Username(templateViewUser))).thenReturn(false); assertThat(securityService.isAuthorizedToViewTemplate(templateName, new Username(templateViewUser)), is(true)); } @Test public void shouldReturnTrueForGroupAdminsToViewTemplateConfigurationByDefault() { CruiseConfig config = getCruiseConfigWithSecurityEnabled(); CaseInsensitiveString groupAdmin = new CaseInsensitiveString("groupAdmin"); setUpGroupWithAuthorization(config, new Authorization(new AdminsConfig(new AdminUser(groupAdmin)))); String templateName = "template"; config.addTemplate(createTemplate(templateName)); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isUserAdmin(new Username(groupAdmin))).thenReturn(false); when(goConfigService.isGroupAdministrator(groupAdmin)).thenReturn(true); assertThat(securityService.isAuthorizedToViewTemplate(templateName, new Username(groupAdmin)), is(true)); } @Test public void shouldReturnFalseForGroupAdminsToViewTemplateConfigurationIfDisallowed() { CruiseConfig config = getCruiseConfigWithSecurityEnabled(); CaseInsensitiveString groupAdmin = new CaseInsensitiveString("groupAdmin"); setUpGroupWithAuthorization(config, new Authorization(new AdminsConfig(new AdminUser(groupAdmin)))); String templateName = "template"; PipelineTemplateConfig template = createTemplate(templateName); template.getAuthorization().setAllowGroupAdmins(false); config.addTemplate(template); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isUserAdmin(new Username(groupAdmin))).thenReturn(false); when(goConfigService.isGroupAdministrator(groupAdmin)).thenReturn(true); assertThat(securityService.isAuthorizedToViewTemplate(templateName, new Username(groupAdmin)), is(false)); } @Test public void shouldReturnTrueForGroupAdminsWithinARoleToViewTemplate() { CaseInsensitiveString groupAdmin = new CaseInsensitiveString("groupAdmin"); BasicCruiseConfig config = new BasicCruiseConfig(); ServerConfig serverConfig = new ServerConfig(new SecurityConfig(null, null, false, new AdminsConfig(new AdminUser(new CaseInsensitiveString("admin")))), null); RoleConfig role = new RoleConfig(new CaseInsensitiveString("role1"), new RoleUser(groupAdmin)); serverConfig.security().addRole(role); config.setServerConfig(serverConfig); GoConfigMother.enableSecurityWithPasswordFile(config); setUpGroupWithAuthorization(config, new Authorization(new AdminsConfig(new AdminRole(role)))); String templateName = "template"; config.addTemplate(createTemplate(templateName)); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isUserAdmin(new Username(groupAdmin))).thenReturn(false); when(goConfigService.isGroupAdministrator(groupAdmin)).thenReturn(true); assertThat(securityService.isAuthorizedToViewTemplate(templateName, new Username(groupAdmin)), is(true)); } @Test public void shouldReturnFalseForGroupAdminsWithinARoleToVIewTemplateIfDisallowed() { CaseInsensitiveString groupAdmin = new CaseInsensitiveString("groupAdmin"); BasicCruiseConfig config = new BasicCruiseConfig(); ServerConfig serverConfig = new ServerConfig(new SecurityConfig(null, null, false, new AdminsConfig(new AdminUser(new CaseInsensitiveString("admin")))), null); RoleConfig role = new RoleConfig(new CaseInsensitiveString("role1"), new RoleUser(groupAdmin)); serverConfig.security().addRole(role); config.setServerConfig(serverConfig); GoConfigMother.enableSecurityWithPasswordFile(config); setUpGroupWithAuthorization(config, new Authorization(new AdminsConfig(new AdminRole(role)))); String templateName = "template"; PipelineTemplateConfig template = createTemplate(templateName); template.getAuthorization().setAllowGroupAdmins(false); config.addTemplate(template); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isUserAdmin(new Username(groupAdmin))).thenReturn(false); when(goConfigService.isGroupAdministrator(groupAdmin)).thenReturn(true); assertThat(securityService.isAuthorizedToViewTemplate(templateName, new Username(groupAdmin)), is(false)); } @Test public void shouldSayUserIsAuthorizedToViewTemplatesWhenTheUserHasViewPermissionsToAtLeastOneTemplate() { CruiseConfig config = new BasicCruiseConfig(); String theSuperAdmin = "theSuperAdmin"; String templateName = "template"; String secondTemplateName = "secondTemplate"; CaseInsensitiveString templateAdminName = new CaseInsensitiveString("templateAdmin"); CaseInsensitiveString templateViewUser = new CaseInsensitiveString("templateViewUser"); GoConfigMother.enableSecurityWithPasswordFile(config); GoConfigMother.addUserAsSuperAdmin(config, theSuperAdmin); config.addTemplate(createTemplate(templateName, new Authorization(new AdminsConfig(new AdminUser(templateAdminName))))); config.addTemplate(createTemplate(secondTemplateName, new Authorization(new ViewConfig(new AdminUser(templateViewUser))))); when(goConfigService.cruiseConfig()).thenReturn(config); when(goConfigService.isUserAdmin(new Username(templateAdminName))).thenReturn(false); when(goConfigService.isUserAdmin(new Username(templateViewUser))).thenReturn(false); when(goConfigService.isUserAdmin(new Username(new CaseInsensitiveString(theSuperAdmin)))).thenReturn(true); when(goConfigService.isUserAdmin(new Username(new CaseInsensitiveString("regularUser")))).thenReturn(false); assertThat(securityService.isAuthorizedToViewTemplates(new Username(templateAdminName)), is(true)); assertThat(securityService.isAuthorizedToViewTemplates(new Username(templateViewUser)), is(true)); assertThat(securityService.isAuthorizedToViewTemplates(new Username(new CaseInsensitiveString(theSuperAdmin))), is(true)); assertThat(securityService.isAuthorizedToViewTemplates(new Username(new CaseInsensitiveString("regularUser"))), is(false)); } private BasicCruiseConfig getCruiseConfigWithSecurityEnabled() { BasicCruiseConfig cruiseConfig = new BasicCruiseConfig(); ServerConfig serverConfig = new ServerConfig(new SecurityConfig(null, null, false, new AdminsConfig(new AdminUser(new CaseInsensitiveString("admin")))), null); cruiseConfig.setServerConfig(serverConfig); GoConfigMother.enableSecurityWithPasswordFile(cruiseConfig); return cruiseConfig; } private void setUpGroupWithAuthorization(CruiseConfig config, Authorization authorization) { new GoConfigMother().addPipelineWithGroup(config, "group", "pipeline", "stage", "job"); config.getGroups().findGroup("group").setAuthorization(authorization); } }