Search in sources :

Example 1 with ProgramRecord

use of co.cask.cdap.proto.ProgramRecord in project cdap by caskdata.

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();
    Authorizer authorizer = getAuthorizer();
    ApplicationId dummyAppId = AUTH_NAMESPACE.app(DummyApp.class.getSimpleName());
    Map<EntityId, Set<Action>> neededPrivileges = ImmutableMap.<EntityId, Set<Action>>builder().put(dummyAppId, EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.artifact(DummyApp.class.getSimpleName(), "1.0-SNAPSHOT"), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.dataset("whom"), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.stream("who"), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.dataset("customDataset"), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.datasetType(KeyValueTable.class.getName()), EnumSet.of(Action.ADMIN)).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(Action.ADMIN));
    cleanUpEntities.add(AUTH_NAMESPACE.datasetType(DummyApp.CustomDummyDataset.class.getName()));
    grantAndAssertSuccess(AUTH_NAMESPACE.datasetModule(DummyApp.CustomDummyDataset.class.getName()), ALICE, EnumSet.of(Action.ADMIN));
    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", authorizer.listPrivileges(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(dummyAppId, BOB, ImmutableSet.of(Action.READ, Action.WRITE));
    // delete should fail
    try {
        appManager.delete();
    } catch (UnauthorizedException expected) {
    // expected
    }
    // grant ADMIN to Bob. Now delete should succeed
    grantAndAssertSuccess(dummyAppId, BOB, ImmutableSet.of(Action.ADMIN));
    // 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(!getAuthorizer().isVisible(Collections.singleton(dummyAppId), BOB).isEmpty());
    // bob should still have privileges granted to him
    Assert.assertEquals(3, authorizer.listPrivileges(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<Action>> anotherAppNeededPrivilege = ImmutableMap.<EntityId, Set<Action>>builder().put(appId, EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.artifact(AllProgramsApp.class.getSimpleName(), "1.0-SNAPSHOT"), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.dataset(AllProgramsApp.DATASET_NAME), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.dataset(AllProgramsApp.DATASET_NAME2), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.dataset(AllProgramsApp.DATASET_NAME3), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.dataset(AllProgramsApp.DS_WITH_SCHEMA_NAME), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.stream(AllProgramsApp.STREAM_NAME), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.datasetType(ObjectMappedTable.class.getName()), EnumSet.of(Action.ADMIN)).build();
    setUpPrivilegeAndRegisterForDeletion(ALICE, anotherAppNeededPrivilege);
    Map<EntityId, Set<Action>> bobDatasetPrivileges = ImmutableMap.<EntityId, Set<Action>>builder().put(AUTH_NAMESPACE.dataset(AllProgramsApp.DATASET_NAME), EnumSet.of(Action.ADMIN)).put(AUTH_NAMESPACE.dataset(AllProgramsApp.DATASET_NAME2), EnumSet.of(Action.ADMIN)).build();
    Map<EntityId, Set<Action>> bobProgramPrivileges = ImmutableMap.<EntityId, Set<Action>>builder().put(appId.program(ProgramType.FLOW, AllProgramsApp.NoOpFlow.NAME), EnumSet.of(Action.EXECUTE)).put(appId.program(ProgramType.SERVICE, AllProgramsApp.NoOpService.NAME), EnumSet.of(Action.EXECUTE)).put(appId.program(ProgramType.WORKER, AllProgramsApp.NoOpWorker.NAME), EnumSet.of(Action.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
    }
    ApplicationDetail applicationDetail = getAppDetail(appId);
    Assert.assertEquals(bobDatasetPrivileges.keySet(), Sets.<EntityId>newHashSet(Iterables.transform(applicationDetail.getDatasets(), new Function<DatasetDetail, DatasetId>() {

        @Override
        public DatasetId apply(DatasetDetail input) {
            return appId.getNamespaceId().dataset(input.getName());
        }
    })));
    Assert.assertEquals(bobProgramPrivileges.keySet(), Sets.<EntityId>newHashSet(Iterables.transform(applicationDetail.getPrograms(), new Function<ProgramRecord, ProgramId>() {

        @Override
        public ProgramId apply(ProgramRecord input) {
            return appId.program(input.getType(), input.getName());
        }
    })));
    Assert.assertEquals(Collections.emptyList(), applicationDetail.getStreams());
    // Switch to ALICE, deletion should be successful since ALICE has ADMIN privileges
    SecurityRequestContext.setUserId(ALICE.getName());
    deleteAllApplications(AUTH_NAMESPACE);
}
Also used : DatasetDetail(co.cask.cdap.proto.DatasetDetail) PrivilegedAction(java.security.PrivilegedAction) Action(co.cask.cdap.proto.security.Action) ApplicationManager(co.cask.cdap.test.ApplicationManager) EnumSet(java.util.EnumSet) Set(java.util.Set) ImmutableSet(com.google.common.collect.ImmutableSet) HashSet(java.util.HashSet) PartitionedFileSet(co.cask.cdap.api.dataset.lib.PartitionedFileSet) AllProgramsApp(co.cask.cdap.AllProgramsApp) ProgramId(co.cask.cdap.proto.id.ProgramId) AppRequest(co.cask.cdap.proto.artifact.AppRequest) DatasetId(co.cask.cdap.proto.id.DatasetId) EntityId(co.cask.cdap.proto.id.EntityId) ArtifactSummary(co.cask.cdap.api.artifact.ArtifactSummary) ApplicationDetail(co.cask.cdap.proto.ApplicationDetail) ProgramRecord(co.cask.cdap.proto.ProgramRecord) KeyValueTable(co.cask.cdap.api.dataset.lib.KeyValueTable) InMemoryAuthorizer(co.cask.cdap.security.authorization.InMemoryAuthorizer) Authorizer(co.cask.cdap.security.spi.authorization.Authorizer) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) DummyApp(co.cask.cdap.test.app.DummyApp) ApplicationId(co.cask.cdap.proto.id.ApplicationId) ObjectMappedTable(co.cask.cdap.api.dataset.lib.ObjectMappedTable) Category(org.junit.experimental.categories.Category) Test(org.junit.Test)

Example 2 with ProgramRecord

use of co.cask.cdap.proto.ProgramRecord in project cdap by caskdata.

the class ProgramClient method stopAll.

/**
 * Stops all currently running programs.
 */
public void stopAll(NamespaceId namespace) throws IOException, UnauthenticatedException, InterruptedException, TimeoutException, UnauthorizedException, ApplicationNotFoundException {
    List<ApplicationRecord> allApps = applicationClient.list(namespace);
    for (ApplicationRecord applicationRecord : allApps) {
        ApplicationId appId = new ApplicationId(namespace.getNamespace(), applicationRecord.getName(), applicationRecord.getAppVersion());
        List<ProgramRecord> programRecords = applicationClient.listPrograms(appId);
        for (ProgramRecord programRecord : programRecords) {
            try {
                ProgramId program = appId.program(programRecord.getType(), programRecord.getName());
                String status = this.getStatus(program);
                if (!status.equals("STOPPED")) {
                    try {
                        this.stop(program);
                    } catch (IOException ioe) {
                        // ProgramClient#stop calls RestClient, which throws an IOException if the HTTP response code is 400,
                        // which can be due to the program already being stopped when calling stop on it.
                        // Most likely, there was a race condition that the program stopped between the time we checked its
                        // status and calling the stop method.
                        LOG.warn("Program {} is already stopped, proceeding even though the following exception is raised.", program, ioe);
                    }
                    this.waitForStatus(program, ProgramStatus.STOPPED, 60, TimeUnit.SECONDS);
                }
            } catch (ProgramNotFoundException e) {
            // IGNORE
            }
        }
    }
}
Also used : ProgramRecord(co.cask.cdap.proto.ProgramRecord) IOException(java.io.IOException) ApplicationId(co.cask.cdap.proto.id.ApplicationId) ProgramId(co.cask.cdap.proto.id.ProgramId) ProgramNotFoundException(co.cask.cdap.common.ProgramNotFoundException) ApplicationRecord(co.cask.cdap.proto.ApplicationRecord)

Example 3 with ProgramRecord

use of co.cask.cdap.proto.ProgramRecord in project cdap by caskdata.

the class ApplicationClient method listAllPrograms.

/**
 * Lists all programs.
 *
 * @return list of {@link ProgramRecord}s
 * @throws IOException if a network error occurred
 * @throws UnauthenticatedException if the request is not authorized successfully in the gateway server
 */
public Map<ProgramType, List<ProgramRecord>> listAllPrograms(NamespaceId namespace) throws IOException, UnauthenticatedException, UnauthorizedException {
    ImmutableMap.Builder<ProgramType, List<ProgramRecord>> allPrograms = ImmutableMap.builder();
    for (ProgramType programType : ProgramType.values()) {
        if (programType.isListable()) {
            List<ProgramRecord> programRecords = Lists.newArrayList();
            programRecords.addAll(listAllPrograms(namespace, programType));
            allPrograms.put(programType, programRecords);
        }
    }
    return allPrograms.build();
}
Also used : ProgramRecord(co.cask.cdap.proto.ProgramRecord) List(java.util.List) ProgramType(co.cask.cdap.proto.ProgramType) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 4 with ProgramRecord

use of co.cask.cdap.proto.ProgramRecord in project cdap by caskdata.

the class ApplicationClient method listPrograms.

/**
 * Lists programs of a type belonging to an application.
 *
 * @param app the application
 * @param programType type of the programs to list
 * @return list of {@link ProgramRecord}s
 * @throws ApplicationNotFoundException if the application with the given ID was not found
 * @throws IOException if a network error occurred
 * @throws UnauthenticatedException if the request is not authorized successfully in the gateway server
 */
public List<ProgramRecord> listPrograms(ApplicationId app, ProgramType programType) throws ApplicationNotFoundException, IOException, UnauthenticatedException, UnauthorizedException {
    Preconditions.checkArgument(programType.isListable());
    List<ProgramRecord> programs = Lists.newArrayList();
    for (ProgramRecord program : listPrograms(app)) {
        if (programType.equals(program.getType())) {
            programs.add(program);
        }
    }
    return programs;
}
Also used : ProgramRecord(co.cask.cdap.proto.ProgramRecord)

Example 5 with ProgramRecord

use of co.cask.cdap.proto.ProgramRecord in project cdap by caskdata.

the class ApplicationLifecycleService method filterApplicationDetail.

/**
 * Filter the {@link ApplicationDetail} by only returning the visible entities
 */
private ApplicationDetail filterApplicationDetail(final ApplicationId appId, ApplicationDetail applicationDetail) throws Exception {
    Principal principal = authenticationContext.getPrincipal();
    List<ProgramRecord> filteredPrograms = AuthorizationUtil.isVisible(applicationDetail.getPrograms(), authorizationEnforcer, principal, new Function<ProgramRecord, EntityId>() {

        @Override
        public EntityId apply(ProgramRecord input) {
            return appId.program(input.getType(), input.getName());
        }
    }, null);
    List<StreamDetail> filteredStreams = AuthorizationUtil.isVisible(applicationDetail.getStreams(), authorizationEnforcer, principal, new Function<StreamDetail, EntityId>() {

        @Override
        public EntityId apply(StreamDetail input) {
            return appId.getNamespaceId().stream(input.getName());
        }
    }, null);
    List<DatasetDetail> filteredDatasets = AuthorizationUtil.isVisible(applicationDetail.getDatasets(), authorizationEnforcer, principal, new Function<DatasetDetail, EntityId>() {

        @Override
        public EntityId apply(DatasetDetail input) {
            return appId.getNamespaceId().dataset(input.getName());
        }
    }, null);
    return new ApplicationDetail(applicationDetail.getName(), applicationDetail.getAppVersion(), applicationDetail.getDescription(), applicationDetail.getConfiguration(), filteredStreams, filteredDatasets, filteredPrograms, applicationDetail.getPlugins(), applicationDetail.getArtifact(), applicationDetail.getOwnerPrincipal());
}
Also used : DatasetDetail(co.cask.cdap.proto.DatasetDetail) StreamDetail(co.cask.cdap.proto.StreamDetail) EntityId(co.cask.cdap.proto.id.EntityId) ApplicationDetail(co.cask.cdap.proto.ApplicationDetail) ProgramRecord(co.cask.cdap.proto.ProgramRecord) Principal(co.cask.cdap.proto.security.Principal)

Aggregations

ProgramRecord (co.cask.cdap.proto.ProgramRecord)14 ApplicationId (co.cask.cdap.proto.id.ApplicationId)5 ProgramId (co.cask.cdap.proto.id.ProgramId)4 RowMaker (co.cask.cdap.cli.util.RowMaker)3 Table (co.cask.cdap.cli.util.table.Table)3 ApplicationDetail (co.cask.cdap.proto.ApplicationDetail)3 ProgramType (co.cask.cdap.proto.ProgramType)3 UnauthorizedException (co.cask.cdap.security.spi.authorization.UnauthorizedException)3 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 BadRequestException (co.cask.cdap.common.BadRequestException)2 ConflictException (co.cask.cdap.common.ConflictException)2 NotFoundException (co.cask.cdap.common.NotFoundException)2 ProgramNotFoundException (co.cask.cdap.common.ProgramNotFoundException)2 BatchProgramStatus (co.cask.cdap.proto.BatchProgramStatus)2 DatasetDetail (co.cask.cdap.proto.DatasetDetail)2 EntityId (co.cask.cdap.proto.id.EntityId)2 NamespaceId (co.cask.cdap.proto.id.NamespaceId)2 Test (org.junit.Test)2