use of co.cask.cdap.proto.id.KerberosPrincipalId in project cdap by caskdata.
the class AuthorizationTest method deployDummyAppWithImpersonation.
private void deployDummyAppWithImpersonation(NamespaceMeta nsMeta, @Nullable String appOwner) throws Exception {
NamespaceId namespaceId = nsMeta.getNamespaceId();
ApplicationId dummyAppId = namespaceId.app(DummyApp.class.getSimpleName());
ArtifactId artifactId = namespaceId.artifact(DummyApp.class.getSimpleName(), "1.0-SNAPSHOT");
DatasetId datasetId = namespaceId.dataset("whom");
DatasetTypeId datasetTypeId = namespaceId.datasetType(KeyValueTable.class.getName());
StreamId streamId = namespaceId.stream("who");
String owner = appOwner != null ? appOwner : nsMeta.getConfig().getPrincipal();
KerberosPrincipalId principalId = new KerberosPrincipalId(owner);
Principal principal = new Principal(owner, Principal.PrincipalType.USER);
DatasetId dummyDatasetId = namespaceId.dataset("customDataset");
DatasetTypeId dummyTypeId = namespaceId.datasetType(DummyApp.CustomDummyDataset.class.getName());
DatasetModuleId dummyModuleId = namespaceId.datasetModule((DummyApp.CustomDummyDataset.class.getName()));
// these are the privileges that are needed to deploy the app if no impersonation is involved,
// can check testApps() for more info
Map<EntityId, Set<Action>> neededPrivileges = ImmutableMap.<EntityId, Set<Action>>builder().put(dummyAppId, EnumSet.of(Action.ADMIN)).put(artifactId, EnumSet.of(Action.ADMIN)).put(datasetId, EnumSet.of(Action.ADMIN)).put(streamId, EnumSet.of(Action.ADMIN)).put(datasetTypeId, EnumSet.of(Action.ADMIN)).put(principalId, EnumSet.of(Action.ADMIN)).put(dummyDatasetId, EnumSet.of(Action.ADMIN)).put(dummyTypeId, EnumSet.of(Action.ADMIN)).put(dummyModuleId, EnumSet.of(Action.ADMIN)).build();
setUpPrivilegeAndRegisterForDeletion(ALICE, neededPrivileges);
// add the artifact
addAppArtifact(artifactId, DummyApp.class);
AppRequest<? extends Config> appRequest = new AppRequest<>(new ArtifactSummary(artifactId.getArtifact(), artifactId.getVersion()), null, appOwner);
try {
deployApplication(dummyAppId, appRequest);
Assert.fail();
} catch (Exception e) {
// expected
}
// revoke privileges on datasets and streams from alice, she does not need these privileges to deploy the app
// the owner will need these privileges to deploy
revokeAndAssertSuccess(datasetId);
revokeAndAssertSuccess(datasetTypeId);
revokeAndAssertSuccess(streamId);
revokeAndAssertSuccess(dummyDatasetId);
revokeAndAssertSuccess(dummyTypeId);
revokeAndAssertSuccess(dummyModuleId);
// grant ADMIN privileges to owner
grantAndAssertSuccess(datasetId, principal, EnumSet.of(Action.ADMIN));
grantAndAssertSuccess(datasetTypeId, principal, EnumSet.of(Action.ADMIN));
grantAndAssertSuccess(streamId, principal, EnumSet.of(Action.ADMIN));
grantAndAssertSuccess(dummyDatasetId, principal, EnumSet.of(Action.ADMIN));
grantAndAssertSuccess(dummyTypeId, principal, EnumSet.of(Action.ADMIN));
grantAndAssertSuccess(dummyModuleId, principal, EnumSet.of(Action.ADMIN));
// this time it should be successful
deployApplication(dummyAppId, appRequest);
// clean up the privilege on the owner principal id
revokeAndAssertSuccess(principalId);
}
use of co.cask.cdap.proto.id.KerberosPrincipalId in project cdap by caskdata.
the class AuthorizationTest method testDeployAppWithoutOwner.
private void testDeployAppWithoutOwner() throws Exception {
NamespaceId namespaceId = new NamespaceId("namespaceImpersonation");
// We will create a namespace as owner bob, the keytab url is provided to pass the check for DefaultNamespaceAdmin
// in unit test, it is useless, since impersonation will never happen
NamespaceMeta ownerNSMeta = new NamespaceMeta.Builder().setName(namespaceId.getNamespace()).setPrincipal(BOB.getName()).setKeytabURI("/tmp/").build();
KerberosPrincipalId bobPrincipalId = new KerberosPrincipalId(BOB.getName());
// grant alice admin to the namespace, but creation should still fail since alice needs to have privilege on
// principal bob
grantAndAssertSuccess(namespaceId, ALICE, EnumSet.of(Action.ADMIN));
cleanUpEntities.add(namespaceId);
try {
getNamespaceAdmin().create(ownerNSMeta);
Assert.fail("Namespace creation should fail since alice does not have privilege on principal bob");
} catch (UnauthorizedException e) {
// expected
}
// grant alice admin on principal bob, now creation of namespace should work
grantAndAssertSuccess(bobPrincipalId, ALICE, EnumSet.of(Action.ADMIN));
cleanUpEntities.add(bobPrincipalId);
getNamespaceAdmin().create(ownerNSMeta);
// deploy dummy app with ns impersonation
deployDummyAppWithImpersonation(ownerNSMeta, null);
}
use of co.cask.cdap.proto.id.KerberosPrincipalId in project cdap by caskdata.
the class AppLifecycleHttpHandler method deployAppFromArtifact.
// normally we wouldn't want to use a body consumer but would just want to read the request body directly
// since it wont be big. But the deploy app API has one path with different behavior based on content type
// the other behavior requires a BodyConsumer and only have one method per path is allowed,
// so we have to use a BodyConsumer
private BodyConsumer deployAppFromArtifact(final ApplicationId appId) throws IOException {
// createTempFile() needs a prefix of at least 3 characters
return new AbstractBodyConsumer(File.createTempFile("apprequest-" + appId, ".json", tmpDir)) {
@Override
protected void onFinish(HttpResponder responder, File uploadedFile) {
try (FileReader fileReader = new FileReader(uploadedFile)) {
AppRequest<?> appRequest = DECODE_GSON.fromJson(fileReader, AppRequest.class);
ArtifactSummary artifactSummary = appRequest.getArtifact();
KerberosPrincipalId ownerPrincipalId = appRequest.getOwnerPrincipal() == null ? null : new KerberosPrincipalId(appRequest.getOwnerPrincipal());
// if we don't null check, it gets serialized to "null"
String configString = appRequest.getConfig() == null ? null : GSON.toJson(appRequest.getConfig());
try {
applicationLifecycleService.deployApp(appId.getParent(), appId.getApplication(), appId.getVersion(), artifactSummary, configString, createProgramTerminator(), ownerPrincipalId, appRequest.canUpdateSchedules());
} catch (DatasetManagementException e) {
if (e.getCause() instanceof UnauthorizedException) {
throw (UnauthorizedException) e.getCause();
} else {
throw e;
}
}
responder.sendString(HttpResponseStatus.OK, "Deploy Complete");
} catch (ArtifactNotFoundException e) {
responder.sendString(HttpResponseStatus.NOT_FOUND, e.getMessage());
} catch (ConflictException e) {
responder.sendString(HttpResponseStatus.CONFLICT, e.getMessage());
} catch (UnauthorizedException e) {
responder.sendString(HttpResponseStatus.FORBIDDEN, e.getMessage());
} catch (InvalidArtifactException e) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
} catch (IOException e) {
LOG.error("Error reading request body for creating app {}.", appId);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, String.format("Error while reading json request body for app %s.", appId));
} catch (Exception e) {
LOG.error("Deploy failure", e);
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
}
}
};
}
use of co.cask.cdap.proto.id.KerberosPrincipalId in project cdap by caskdata.
the class CreateStreamsStage method process.
/**
* Receives an input containing application specification and location
* and verifies both.
*
* @param input An instance of {@link ApplicationDeployable}
*/
@Override
public void process(ApplicationDeployable input) throws Exception {
// create stream instances
ApplicationSpecification specification = input.getSpecification();
NamespaceId namespaceId = input.getApplicationId().getParent();
KerberosPrincipalId ownerPrincipal = input.getOwnerPrincipal();
// get the authorizing user
String authorizingUser = AuthorizationUtil.getAppAuthorizingUser(ownerAdmin, authenticationContext, input.getApplicationId(), ownerPrincipal);
streamCreator.createStreams(namespaceId, specification.getStreams().values(), ownerPrincipal, authorizingUser);
// Emit the input to next stage.
emit(input);
}
use of co.cask.cdap.proto.id.KerberosPrincipalId in project cdap by caskdata.
the class CreateDatasetInstancesStage method process.
/**
* Receives an input containing application specification and location
* and verifies both.
*
* @param input An instance of {@link ApplicationDeployable}
*/
@Override
public void process(ApplicationDeployable input) throws Exception {
// create dataset instances
ApplicationSpecification specification = input.getSpecification();
NamespaceId namespaceId = input.getApplicationId().getParent();
KerberosPrincipalId ownerPrincipal = input.getOwnerPrincipal();
// get the authorizing user
String authorizingUser = AuthorizationUtil.getAppAuthorizingUser(ownerAdmin, authenticationContext, input.getApplicationId(), ownerPrincipal);
datasetInstanceCreator.createInstances(namespaceId, specification.getDatasets(), ownerPrincipal, authorizingUser);
// Emit the input to next stage.
emit(input);
}
Aggregations