Search in sources :

Example 16 with AccessController

use of io.cdap.cdap.security.spi.authorization.AccessController in project cdap by cdapio.

the class AccessControllerInstantiator method createAccessController.

/**
 * Creates a new instance of the configured {@link AccessController} extension, based on the provided extension jar
 * file and initialize it.
 *
 * @return a new instance of the configured {@link AccessController} extension
 */
private AccessController createAccessController(AccessControllerClassLoader classLoader) throws InvalidAccessControllerException {
    Class<?> accessControllerClass = loadAccessControllerClass(classLoader);
    // Set the context class loader to the AccessControllerClassLoader before creating a new instance of the extension,
    // so all classes required in this process are created from the AccessControllerClassLoader.
    ClassLoader oldClassLoader = ClassLoaders.setContextClassLoader(classLoader);
    LOG.trace("Setting context classloader to {}. Old classloader was {}.", classLoader, oldClassLoader);
    try {
        AccessController accessController;
        try {
            Object extensionClass = instantiatorFactory.get(TypeToken.of(accessControllerClass)).create();
            if (extensionClass instanceof AccessController) {
                accessController = (AccessController) extensionClass;
            } else {
                accessController = new AuthorizerWrapper((Authorizer) extensionClass);
            }
        } catch (Exception e) {
            throw new InvalidAccessControllerException(String.format("Error while instantiating for access controller extension %s. " + "Please make sure that the extension " + "is a public class with a default constructor.", accessControllerClass.getName()), e);
        }
        AuthorizationContext context = authorizationContextFactory.create(createExtensionProperties());
        try {
            accessController.initialize(context);
        } catch (Exception e) {
            throw new InvalidAccessControllerException(String.format("Error while initializing access control extension %s.", accessControllerClass.getName()), e);
        }
        return accessController;
    } finally {
        // After the process of creation of a new instance has completed (success or failure), reset the context
        // classloader back to the original class loader.
        ClassLoaders.setContextClassLoader(oldClassLoader);
        LOG.trace("Resetting context classloader to {} from {}.", oldClassLoader, classLoader);
    }
}
Also used : AccessController(io.cdap.cdap.security.spi.authorization.AccessController) NoOpAccessController(io.cdap.cdap.security.spi.authorization.NoOpAccessController) Authorizer(io.cdap.cdap.security.spi.authorization.Authorizer) AuthorizationContext(io.cdap.cdap.security.spi.authorization.AuthorizationContext) IOException(java.io.IOException)

Example 17 with AccessController

use of io.cdap.cdap.security.spi.authorization.AccessController in project cdap by cdapio.

the class AccessControllerInstantiator method close.

@Override
public void close() throws IOException {
    try {
        synchronized (this) {
            closed = true;
            AccessController accessController = this.accessController;
            if (accessController != null) {
                accessController.destroy();
            }
        }
    } catch (Throwable t) {
        LOG.warn("Failed to destroy accessController.", t);
    } finally {
        Closeables.closeQuietly(accessControllerClassLoader);
    }
}
Also used : AccessController(io.cdap.cdap.security.spi.authorization.AccessController) NoOpAccessController(io.cdap.cdap.security.spi.authorization.NoOpAccessController)

Example 18 with AccessController

use of io.cdap.cdap.security.spi.authorization.AccessController in project cdap by cdapio.

the class AuthorizationTest method testApps.

@Test
@Category(SlowTests.class)
public void testApps() throws Exception {
    try {
        deployApplication(NamespaceId.DEFAULT, DummyApp.class);
        Assert.fail("App deployment should fail because alice does not have ADMIN privilege on the application");
    } catch (UnauthorizedException e) {
    // Expected
    }
    createAuthNamespace();
    AccessController accessController = getAccessController();
    ApplicationId dummyAppId = AUTH_NAMESPACE.app(DummyApp.class.getSimpleName());
    Map<EntityId, Set<? extends Permission>> neededPrivileges = ImmutableMap.<EntityId, Set<? extends Permission>>builder().put(dummyAppId, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET, StandardPermission.DELETE)).put(AUTH_NAMESPACE.artifact(DummyApp.class.getSimpleName(), "1.0-SNAPSHOT"), EnumSet.of(StandardPermission.CREATE)).put(AUTH_NAMESPACE.dataset("whom"), EnumSet.of(StandardPermission.GET, StandardPermission.CREATE)).put(AUTH_NAMESPACE.dataset("customDataset"), EnumSet.of(StandardPermission.GET, StandardPermission.CREATE)).put(AUTH_NAMESPACE.datasetType(KeyValueTable.class.getName()), EnumSet.of(StandardPermission.UPDATE)).build();
    setUpPrivilegeAndRegisterForDeletion(ALICE, neededPrivileges);
    // alice will not be able to deploy the app since she does not have privilege on the implicit dataset module
    try {
        deployApplication(AUTH_NAMESPACE, DummyApp.class);
        Assert.fail();
    } catch (UnauthorizedException e) {
    // expected
    }
    // grant alice the required implicit type and module
    grantAndAssertSuccess(AUTH_NAMESPACE.datasetType(DummyApp.CustomDummyDataset.class.getName()), ALICE, EnumSet.of(StandardPermission.GET, StandardPermission.CREATE));
    cleanUpEntities.add(AUTH_NAMESPACE.datasetType(DummyApp.CustomDummyDataset.class.getName()));
    grantAndAssertSuccess(AUTH_NAMESPACE.datasetModule(DummyApp.CustomDummyDataset.class.getName()), ALICE, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET));
    cleanUpEntities.add(AUTH_NAMESPACE.datasetModule(DummyApp.CustomDummyDataset.class.getName()));
    // this time it should be successful
    ApplicationManager appManager = deployApplication(AUTH_NAMESPACE, DummyApp.class);
    // Bob should not have any privileges on Alice's app
    Assert.assertTrue("Bob should not have any privileges on alice's app", accessController.listGrants(BOB).isEmpty());
    // update should succeed because alice has admin privileges on the app
    appManager.update(new AppRequest(new ArtifactSummary(DummyApp.class.getSimpleName(), "1.0-SNAPSHOT")));
    // Update should fail for Bob
    SecurityRequestContext.setUserId(BOB.getName());
    try {
        appManager.update(new AppRequest(new ArtifactSummary(DummyApp.class.getSimpleName(), "1.0-SNAPSHOT")));
        Assert.fail("App update should have failed because Bob does not have admin privileges on the app.");
    } catch (UnauthorizedException expected) {
    // expected
    }
    // grant READ and WRITE to Bob
    grantAndAssertSuccess(AUTH_NAMESPACE, BOB, ImmutableSet.of(StandardPermission.GET));
    grantAndAssertSuccess(dummyAppId, BOB, ImmutableSet.of(StandardPermission.GET, StandardPermission.UPDATE));
    // delete should fail
    try {
        appManager.delete();
    } catch (UnauthorizedException expected) {
    // expected
    }
    // grant DELETE to Bob. Now delete should succeed
    grantAndAssertSuccess(dummyAppId, BOB, ImmutableSet.of(StandardPermission.DELETE));
    // deletion should succeed since BOB has privileges on the app
    appManager.delete();
    // Should still have the privilege for the app since we no longer revoke privileges after deletion of an entity
    Assert.assertTrue(!getAccessController().isVisible(Collections.singleton(dummyAppId), BOB).isEmpty());
    // bob should still have privileges granted to him
    Assert.assertEquals(4, accessController.listGrants(BOB).size());
    // switch back to Alice
    SecurityRequestContext.setUserId(ALICE.getName());
    // Deploy a couple of apps in the namespace
    // Deploy dummy app should be successful since we already pre-grant the required privileges
    deployApplication(AUTH_NAMESPACE, DummyApp.class);
    final ApplicationId appId = AUTH_NAMESPACE.app(AllProgramsApp.NAME);
    Map<EntityId, Set<? extends Permission>> anotherAppNeededPrivilege = ImmutableMap.<EntityId, Set<? extends Permission>>builder().put(appId, EnumSet.of(StandardPermission.GET, StandardPermission.CREATE, StandardPermission.DELETE)).put(AUTH_NAMESPACE.artifact(AllProgramsApp.class.getSimpleName(), "1.0-SNAPSHOT"), EnumSet.of(StandardPermission.GET, StandardPermission.CREATE)).put(AUTH_NAMESPACE.dataset(AllProgramsApp.DATASET_NAME), EnumSet.of(StandardPermission.GET, StandardPermission.CREATE)).put(AUTH_NAMESPACE.dataset(AllProgramsApp.DATASET_NAME2), EnumSet.of(StandardPermission.GET, StandardPermission.CREATE)).put(AUTH_NAMESPACE.dataset(AllProgramsApp.DATASET_NAME3), EnumSet.of(StandardPermission.GET, StandardPermission.CREATE)).put(AUTH_NAMESPACE.dataset(AllProgramsApp.DS_WITH_SCHEMA_NAME), EnumSet.of(StandardPermission.GET, StandardPermission.CREATE)).put(AUTH_NAMESPACE.datasetType(ObjectMappedTable.class.getName()), EnumSet.of(StandardPermission.GET, StandardPermission.CREATE)).build();
    setUpPrivilegeAndRegisterForDeletion(ALICE, anotherAppNeededPrivilege);
    Map<EntityId, Set<? extends Permission>> bobDatasetPrivileges = ImmutableMap.<EntityId, Set<? extends Permission>>builder().put(AUTH_NAMESPACE.dataset(AllProgramsApp.DATASET_NAME), EnumSet.of(StandardPermission.UPDATE)).put(AUTH_NAMESPACE.dataset(AllProgramsApp.DATASET_NAME2), EnumSet.of(StandardPermission.UPDATE)).build();
    Map<EntityId, Set<? extends Permission>> bobProgramPrivileges = ImmutableMap.<EntityId, Set<? extends Permission>>builder().put(appId, EnumSet.of(StandardPermission.GET)).put(appId.program(ProgramType.SERVICE, AllProgramsApp.NoOpService.NAME), EnumSet.of(ApplicationPermission.EXECUTE)).put(appId.program(ProgramType.WORKER, AllProgramsApp.NoOpWorker.NAME), EnumSet.of(ApplicationPermission.EXECUTE)).build();
    setUpPrivilegeAndRegisterForDeletion(BOB, bobDatasetPrivileges);
    setUpPrivilegeAndRegisterForDeletion(BOB, bobProgramPrivileges);
    deployApplication(AUTH_NAMESPACE, AllProgramsApp.class);
    // Switch to BOB since he does not have any privilege
    SecurityRequestContext.setUserId(BOB.getName());
    // deleting all apps should fail because bob does not have admin privileges on the apps and the namespace
    try {
        deleteAllApplications(AUTH_NAMESPACE);
        Assert.fail("Deleting all applications in the namespace should have failed because bob does not have ADMIN " + "privilege on the workflow app.");
    } catch (UnauthorizedException expected) {
    // expected
    }
    // Switch to ALICE, deletion should be successful since ALICE has ADMIN privileges
    SecurityRequestContext.setUserId(ALICE.getName());
    deleteAllApplications(AUTH_NAMESPACE);
}
Also used : ApplicationManager(io.cdap.cdap.test.ApplicationManager) PartitionedFileSet(io.cdap.cdap.api.dataset.lib.PartitionedFileSet) EnumSet(java.util.EnumSet) Set(java.util.Set) ImmutableSet(com.google.common.collect.ImmutableSet) HashSet(java.util.HashSet) AppRequest(io.cdap.cdap.proto.artifact.AppRequest) EntityId(io.cdap.cdap.proto.id.EntityId) InMemoryAccessController(io.cdap.cdap.security.authorization.InMemoryAccessController) AccessController(io.cdap.cdap.security.spi.authorization.AccessController) ArtifactSummary(io.cdap.cdap.api.artifact.ArtifactSummary) KeyValueTable(io.cdap.cdap.api.dataset.lib.KeyValueTable) UnauthorizedException(io.cdap.cdap.security.spi.authorization.UnauthorizedException) DummyApp(io.cdap.cdap.test.app.DummyApp) GrantedPermission(io.cdap.cdap.proto.security.GrantedPermission) ApplicationPermission(io.cdap.cdap.proto.security.ApplicationPermission) AccessPermission(io.cdap.cdap.proto.security.AccessPermission) Permission(io.cdap.cdap.proto.security.Permission) StandardPermission(io.cdap.cdap.proto.security.StandardPermission) ApplicationId(io.cdap.cdap.proto.id.ApplicationId) ObjectMappedTable(io.cdap.cdap.api.dataset.lib.ObjectMappedTable) Category(org.junit.experimental.categories.Category) Test(org.junit.Test)

Example 19 with AccessController

use of io.cdap.cdap.security.spi.authorization.AccessController in project cdap by cdapio.

the class AuthorizationTest method afterTest.

@After
@Override
public void afterTest() throws Exception {
    AccessController accessController = getAccessController();
    SecurityRequestContext.setUserId(ALICE.getName());
    grantAndAssertSuccess(AUTH_NAMESPACE, SecurityRequestContext.toPrincipal(), EnumSet.of(StandardPermission.DELETE, StandardPermission.GET));
    for (EntityId entityId : cleanUpEntities) {
        grantAndAssertSuccess(entityId, SecurityRequestContext.toPrincipal(), EnumSet.of(StandardPermission.DELETE, StandardPermission.GET));
    }
    // clean up. remove the namespace if it exists
    if (getNamespaceAdmin().exists(AUTH_NAMESPACE)) {
        getNamespaceAdmin().delete(AUTH_NAMESPACE);
        Assert.assertFalse(getNamespaceAdmin().exists(AUTH_NAMESPACE));
    }
    revokeAndAssertSuccess(AUTH_NAMESPACE);
    for (EntityId entityId : cleanUpEntities) {
        revokeAndAssertSuccess(entityId);
    }
    Assert.assertEquals(Collections.emptySet(), accessController.listGrants(ALICE));
}
Also used : EntityId(io.cdap.cdap.proto.id.EntityId) InMemoryAccessController(io.cdap.cdap.security.authorization.InMemoryAccessController) AccessController(io.cdap.cdap.security.spi.authorization.AccessController) After(org.junit.After)

Example 20 with AccessController

use of io.cdap.cdap.security.spi.authorization.AccessController in project cdap by cdapio.

the class AuthorizationTest method testNamespaces.

@Test
public void testNamespaces() throws Exception {
    NamespaceAdmin namespaceAdmin = getNamespaceAdmin();
    AccessController accessController = getAccessController();
    try {
        namespaceAdmin.create(AUTH_NAMESPACE_META);
        Assert.fail("Namespace create should have failed because alice is not authorized on " + AUTH_NAMESPACE);
    } catch (UnauthorizedException expected) {
    // expected
    }
    createAuthNamespace();
    Assert.assertTrue(namespaceAdmin.list().contains(AUTH_NAMESPACE_META));
    namespaceAdmin.get(AUTH_NAMESPACE);
    // revoke privileges
    revokeAndAssertSuccess(AUTH_NAMESPACE);
    try {
        Assert.assertTrue(namespaceAdmin.list().isEmpty());
        namespaceAdmin.exists(AUTH_NAMESPACE);
        Assert.fail("Namespace existence check should fail since the privilege of alice has been revoked");
    } catch (UnauthorizedException expected) {
    // expected
    }
    // grant privileges again
    grantAndAssertSuccess(AUTH_NAMESPACE, ALICE, ImmutableSet.of(StandardPermission.GET, StandardPermission.UPDATE));
    namespaceAdmin.exists(AUTH_NAMESPACE);
    Assert.assertEquals(ImmutableSet.of(new GrantedPermission(AUTH_NAMESPACE, StandardPermission.GET), new GrantedPermission(AUTH_NAMESPACE, StandardPermission.UPDATE)), accessController.listGrants(ALICE));
    NamespaceMeta updated = new NamespaceMeta.Builder(AUTH_NAMESPACE_META).setDescription("new desc").build();
    namespaceAdmin.updateProperties(AUTH_NAMESPACE, updated);
    Assert.assertEquals(updated, namespaceAdmin.get(AUTH_NAMESPACE));
}
Also used : InMemoryAccessController(io.cdap.cdap.security.authorization.InMemoryAccessController) AccessController(io.cdap.cdap.security.spi.authorization.AccessController) NamespaceMeta(io.cdap.cdap.proto.NamespaceMeta) NamespaceAdmin(io.cdap.cdap.common.namespace.NamespaceAdmin) UnauthorizedException(io.cdap.cdap.security.spi.authorization.UnauthorizedException) GrantedPermission(io.cdap.cdap.proto.security.GrantedPermission) Test(org.junit.Test)

Aggregations

AccessController (io.cdap.cdap.security.spi.authorization.AccessController)50 NoOpAccessController (io.cdap.cdap.security.spi.authorization.NoOpAccessController)30 Test (org.junit.Test)24 InMemoryAccessController (io.cdap.cdap.security.authorization.InMemoryAccessController)18 CConfiguration (io.cdap.cdap.common.conf.CConfiguration)12 Principal (io.cdap.cdap.proto.security.Principal)12 Credential (io.cdap.cdap.proto.security.Credential)10 GrantedPermission (io.cdap.cdap.proto.security.GrantedPermission)10 DatasetId (io.cdap.cdap.proto.id.DatasetId)8 StandardPermission (io.cdap.cdap.proto.security.StandardPermission)8 ImmutableSet (com.google.common.collect.ImmutableSet)6 SConfiguration (io.cdap.cdap.common.conf.SConfiguration)6 EntityId (io.cdap.cdap.proto.id.EntityId)6 NamespaceId (io.cdap.cdap.proto.id.NamespaceId)6 TinkCipher (io.cdap.cdap.security.auth.TinkCipher)6 File (java.io.File)6 IOException (java.io.IOException)6 AuthorizationClient (io.cdap.cdap.client.AuthorizationClient)4 CommonNettyHttpServiceBuilder (io.cdap.cdap.common.http.CommonNettyHttpServiceBuilder)4 MasterAuthenticationContext (io.cdap.cdap.security.auth.context.MasterAuthenticationContext)4