/* * Copyright © 2016 Cask Data, 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 co.cask.cdap.internal.app.runtime.artifact; import co.cask.cdap.common.conf.CConfiguration; import co.cask.cdap.common.conf.Constants; import co.cask.cdap.gateway.handlers.InMemoryAuthorizer; import co.cask.cdap.internal.AppFabricTestHelper; import co.cask.cdap.internal.test.AppJarHelper; import co.cask.cdap.proto.id.ArtifactId; import co.cask.cdap.proto.id.InstanceId; import co.cask.cdap.proto.id.NamespaceId; import co.cask.cdap.proto.security.Action; import co.cask.cdap.proto.security.Principal; import co.cask.cdap.proto.security.Privilege; import co.cask.cdap.security.authorization.AuthorizerInstantiatorService; import co.cask.cdap.security.spi.authentication.SecurityRequestContext; import co.cask.cdap.security.spi.authorization.Authorizer; import co.cask.cdap.security.spi.authorization.UnauthorizedException; import com.google.common.collect.ImmutableSet; import com.google.inject.Injector; import org.apache.twill.filesystem.LocalLocationFactory; import org.apache.twill.filesystem.Location; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import java.util.Collections; /** * Tests for authorization for system artifacts. These tests are not in AuthorizationTest, because we do not want to * expose system artifacts capabilities in TestBase. This has to be in its own class because we want to enable * authorization in the CDAP that this test starts up. */ public class SystemArtifactsAuthorizationTest { @ClassRule public static final TemporaryFolder TMP_FOLDER = new TemporaryFolder(); private static final Principal ALICE = new Principal("alice", Principal.PrincipalType.USER); private static final String OLD_USER_ID = SecurityRequestContext.getUserId(); private static ArtifactRepository artifactRepository; private static Authorizer authorizer; private static InstanceId instance; @BeforeClass public static void setup() throws Exception { CConfiguration cConf = CConfiguration.create(); cConf.set(Constants.CFG_LOCAL_DATA_DIR, TMP_FOLDER.newFolder().getAbsolutePath()); cConf.setBoolean(Constants.Security.ENABLED, true); cConf.setBoolean(Constants.Security.Authorization.ENABLED, true); Location deploymentJar = AppJarHelper.createDeploymentJar(new LocalLocationFactory(TMP_FOLDER.newFolder()), InMemoryAuthorizer.class); cConf.set(Constants.Security.Authorization.EXTENSION_JAR_PATH, deploymentJar.toURI().getPath()); Injector injector = AppFabricTestHelper.getInjector(cConf); artifactRepository = injector.getInstance(ArtifactRepository.class); AuthorizerInstantiatorService instantiatorService = injector.getInstance(AuthorizerInstantiatorService.class); authorizer = instantiatorService.get(); instance = new InstanceId(cConf.get(Constants.INSTANCE_NAME)); } @Test public void testAuthorizationForSystemArtifacts() throws Exception { // the system user must be able to add system artifacts SecurityRequestContext.setUserId(Principal.SYSTEM.getName()); artifactRepository.addSystemArtifacts(); // alice should not be able to refresh system artifacts because she does not have write privileges on the // CDAP instance SecurityRequestContext.setUserId(ALICE.getName()); try { artifactRepository.addSystemArtifacts(); Assert.fail("Adding system artifacts should have failed because alice does not have write privileges on " + "the CDAP instance."); } catch (UnauthorizedException expected) { // expected } // grant alice write privileges on the CDAP instance authorizer.grant(instance, ALICE, Collections.singleton(Action.WRITE)); Assert.assertEquals(Collections.singleton(new Privilege(instance, Action.WRITE)), authorizer.listPrivileges(ALICE)); // refreshing system artifacts should succeed now artifactRepository.addSystemArtifacts(); // deleting a system artifact should still fail because alice does not have admin privileges on the CDAP instance ArtifactId systemArtifact = NamespaceId.SYSTEM.artifact("system-artifact", "1.0"); try { artifactRepository.deleteArtifact(systemArtifact.toId()); Assert.fail("Deleting a system artifact should have failed because alice does not have admin privileges on " + "the CDAP instance."); } catch (UnauthorizedException expected) { // expected } // grant alice admin privileges on the CDAP instance authorizer.grant(instance, ALICE, Collections.singleton(Action.ADMIN)); Assert.assertEquals( ImmutableSet.of(new Privilege(instance, Action.WRITE), new Privilege(instance, Action.ADMIN)), authorizer.listPrivileges(ALICE) ); // deleting system artifact should succeed now artifactRepository.deleteArtifact(systemArtifact.toId()); } @AfterClass public static void cleanup() throws Exception { authorizer.revoke(instance); Assert.assertEquals(ImmutableSet.<Privilege>of(), authorizer.listPrivileges(ALICE)); SecurityRequestContext.setUserId(OLD_USER_ID); } }