use of io.cdap.cdap.proto.id.ArtifactId in project cdap by caskdata.
the class AuthorizationTest method testArtifacts.
@Test
public void testArtifacts() throws Exception {
String appArtifactName = "app-artifact";
String appArtifactVersion = "1.1.1";
try {
ArtifactId defaultNsArtifact = NamespaceId.DEFAULT.artifact(appArtifactName, appArtifactVersion);
addAppArtifact(defaultNsArtifact, ConfigTestApp.class);
Assert.fail("Should not be able to add an app artifact to the default namespace because alice does not have " + "admin privileges on the artifact.");
} catch (UnauthorizedException expected) {
// expected
}
String pluginArtifactName = "plugin-artifact";
String pluginArtifactVersion = "1.2.3";
try {
ArtifactId defaultNsArtifact = NamespaceId.DEFAULT.artifact(pluginArtifactName, pluginArtifactVersion);
addAppArtifact(defaultNsArtifact, ToStringPlugin.class);
Assert.fail("Should not be able to add a plugin artifact to the default namespace because alice does not have " + "admin privileges on the artifact.");
} catch (UnauthorizedException expected) {
// expected
}
// create a new namespace
createAuthNamespace();
ArtifactId appArtifactId = AUTH_NAMESPACE.artifact(appArtifactName, appArtifactVersion);
grantAndAssertSuccess(appArtifactId, ALICE, EnumSet.of(StandardPermission.CREATE, StandardPermission.UPDATE, StandardPermission.DELETE));
cleanUpEntities.add(appArtifactId);
ArtifactManager appArtifactManager = addAppArtifact(appArtifactId, ConfigTestApp.class);
ArtifactId pluginArtifactId = AUTH_NAMESPACE.artifact(pluginArtifactName, pluginArtifactVersion);
grantAndAssertSuccess(pluginArtifactId, ALICE, EnumSet.of(StandardPermission.CREATE, StandardPermission.DELETE));
cleanUpEntities.add(pluginArtifactId);
ArtifactManager pluginArtifactManager = addPluginArtifact(pluginArtifactId, appArtifactId, ToStringPlugin.class);
// Bob should not be able to delete or write properties to artifacts since he does not have ADMIN permission on
// the artifacts
SecurityRequestContext.setUserId(BOB.getName());
try {
appArtifactManager.writeProperties(ImmutableMap.of("authorized", "no"));
Assert.fail("Writing properties to artifact should have failed because Bob does not have admin privileges on " + "the artifact");
} catch (UnauthorizedException expected) {
// expected
}
try {
appArtifactManager.delete();
Assert.fail("Deleting artifact should have failed because Bob does not have admin privileges on the artifact");
} catch (UnauthorizedException expected) {
// expected
}
try {
pluginArtifactManager.writeProperties(ImmutableMap.of("authorized", "no"));
Assert.fail("Writing properties to artifact should have failed because Bob does not have admin privileges on " + "the artifact");
} catch (UnauthorizedException expected) {
// expected
}
try {
pluginArtifactManager.removeProperties();
Assert.fail("Removing properties to artifact should have failed because Bob does not have admin privileges on " + "the artifact");
} catch (UnauthorizedException expected) {
// expected
}
try {
pluginArtifactManager.delete();
Assert.fail("Deleting artifact should have failed because Bob does not have admin privileges on the artifact");
} catch (UnauthorizedException expected) {
// expected
}
// alice should be permitted to update properties/delete artifact
SecurityRequestContext.setUserId(ALICE.getName());
appArtifactManager.writeProperties(ImmutableMap.of("authorized", "yes"));
appArtifactManager.removeProperties();
appArtifactManager.delete();
pluginArtifactManager.delete();
}
use of io.cdap.cdap.proto.id.ArtifactId 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());
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<? extends Permission>> neededPrivileges = ImmutableMap.<EntityId, Set<? extends Permission>>builder().put(dummyAppId, EnumSet.of(StandardPermission.GET, StandardPermission.CREATE)).put(artifactId, EnumSet.of(StandardPermission.CREATE)).put(datasetId, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET)).put(datasetTypeId, EnumSet.of(StandardPermission.UPDATE)).put(principalId, EnumSet.of(AccessPermission.SET_OWNER)).put(dummyDatasetId, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET)).put(dummyTypeId, EnumSet.of(StandardPermission.UPDATE)).put(dummyModuleId, EnumSet.of(StandardPermission.UPDATE)).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 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(dummyDatasetId);
revokeAndAssertSuccess(dummyTypeId);
revokeAndAssertSuccess(dummyModuleId);
// grant privileges to owner
grantAndAssertSuccess(namespaceId, principal, EnumSet.of(StandardPermission.GET));
grantAndAssertSuccess(datasetId, principal, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET));
grantAndAssertSuccess(datasetTypeId, principal, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET));
grantAndAssertSuccess(dummyDatasetId, principal, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET));
grantAndAssertSuccess(dummyTypeId, principal, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET));
grantAndAssertSuccess(dummyModuleId, principal, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET));
// this time it should be successful
deployApplication(dummyAppId, appRequest);
// clean up the privilege on the owner principal id
revokeAndAssertSuccess(principalId);
}
use of io.cdap.cdap.proto.id.ArtifactId in project cdap by caskdata.
the class AuthorizationTest method testAddDropPartitions.
@Test
public void testAddDropPartitions() throws Exception {
createAuthNamespace();
ApplicationId appId = AUTH_NAMESPACE.app(PartitionTestApp.class.getSimpleName());
DatasetId datasetId = AUTH_NAMESPACE.dataset(PartitionTestApp.PFS_NAME);
ArtifactId artifact = AUTH_NAMESPACE.artifact(PartitionTestApp.class.getSimpleName(), "1.0-SNAPSHOT");
Map<EntityId, Set<? extends Permission>> neededPrivileges = ImmutableMap.<EntityId, Set<? extends Permission>>builder().put(appId, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET)).put(artifact, EnumSet.of(StandardPermission.CREATE)).put(datasetId, EnumSet.of(StandardPermission.GET, StandardPermission.CREATE)).put(AUTH_NAMESPACE.datasetType(PartitionedFileSet.class.getName()), EnumSet.of(StandardPermission.UPDATE)).build();
setUpPrivilegeAndRegisterForDeletion(ALICE, neededPrivileges);
ProgramId programId = appId.program(ProgramType.SERVICE, PartitionTestApp.PFS_SERVICE_NAME);
grantAndAssertSuccess(AUTH_NAMESPACE, BOB, EnumSet.of(StandardPermission.GET));
grantAndAssertSuccess(programId, BOB, ImmutableSet.of(StandardPermission.GET, ApplicationPermission.EXECUTE));
cleanUpEntities.add(programId);
grantAndAssertSuccess(datasetId, BOB, EnumSet.of(StandardPermission.GET));
cleanUpEntities.add(datasetId);
// new privilege required due to capability validations
grantAndAssertSuccess(artifact, BOB, EnumSet.of(StandardPermission.GET));
ApplicationManager appMgr = deployApplication(AUTH_NAMESPACE, PartitionTestApp.class);
SecurityRequestContext.setUserId(BOB.getName());
String partition = "p1";
String subPartition = "1";
String text = "some random text for pfs";
ServiceManager pfsService = appMgr.getServiceManager(PartitionTestApp.PFS_SERVICE_NAME);
pfsService.start();
pfsService.waitForRun(ProgramRunStatus.RUNNING, 1, TimeUnit.MINUTES);
URL pfsURL = pfsService.getServiceURL();
String apiPath = String.format("partitions/%s/subpartitions/%s", partition, subPartition);
URL url = new URL(pfsURL, apiPath);
HttpResponse response;
try {
response = executeAuthenticated(HttpRequest.post(url).withBody(text));
// should fail because bob does not have write privileges on the dataset
Assert.assertEquals(500, response.getResponseCode());
} finally {
pfsService.stop();
pfsService.waitForRun(ProgramRunStatus.KILLED, 1, TimeUnit.MINUTES);
}
// grant read and write on dataset and restart
grantAndAssertSuccess(datasetId, BOB, EnumSet.of(StandardPermission.UPDATE, StandardPermission.GET));
pfsService.start();
pfsService.waitForRun(ProgramRunStatus.RUNNING, 1, TimeUnit.MINUTES);
pfsURL = pfsService.getServiceURL();
url = new URL(pfsURL, apiPath);
try {
response = executeAuthenticated(HttpRequest.post(url).withBody(text));
// should succeed now because bob was granted write privileges on the dataset
Assert.assertEquals(200, response.getResponseCode());
// make sure that the partition was added
response = executeAuthenticated(HttpRequest.get(url));
Assert.assertEquals(200, response.getResponseCode());
Assert.assertEquals(text, response.getResponseBodyAsString());
// drop the partition
response = executeAuthenticated(HttpRequest.delete(url));
Assert.assertEquals(200, response.getResponseCode());
} finally {
pfsService.stop();
pfsService.waitForRuns(ProgramRunStatus.KILLED, 2, 1, TimeUnit.MINUTES);
SecurityRequestContext.setUserId(ALICE.getName());
}
}
use of io.cdap.cdap.proto.id.ArtifactId in project cdap by caskdata.
the class AdminAppTestRun method testAdminService.
@Test
public void testAdminService() throws Exception {
// Start the service
ServiceManager serviceManager = appManager.getServiceManager(AdminApp.SERVICE_NAME).start();
String namespaceX = "x";
try {
URI serviceURI = serviceManager.getServiceURL(10, TimeUnit.SECONDS).toURI();
// dataset nn should not exist
HttpResponse response = executeHttp(HttpRequest.get(serviceURI.resolve("exists/nn").toURL()).build());
Assert.assertEquals(200, response.getResponseCode());
Assert.assertEquals("false", response.getResponseBodyAsString());
// create nn as a table
response = executeHttp(HttpRequest.put(serviceURI.resolve("create/nn/table").toURL()).build());
Assert.assertEquals(200, response.getResponseCode());
// now nn should exist
response = executeHttp(HttpRequest.get(serviceURI.resolve("exists/nn").toURL()).build());
Assert.assertEquals(200, response.getResponseCode());
Assert.assertEquals("true", response.getResponseBodyAsString());
// create it again as a fileset -> should fail with conflict
response = executeHttp(HttpRequest.put(serviceURI.resolve("create/nn/fileSet").toURL()).build());
Assert.assertEquals(409, response.getResponseCode());
// get the type for xx -> not found
response = executeHttp(HttpRequest.get(serviceURI.resolve("type/xx").toURL()).build());
Assert.assertEquals(404, response.getResponseCode());
// get the type for nn -> table
response = executeHttp(HttpRequest.get(serviceURI.resolve("type/nn").toURL()).build());
Assert.assertEquals(200, response.getResponseCode());
Assert.assertEquals("table", response.getResponseBodyAsString());
// update xx's properties -> should get not-found
Map<String, String> nnProps = TableProperties.builder().setTTL(1000L).build().getProperties();
response = executeHttp(HttpRequest.put(serviceURI.resolve("update/xx").toURL()).withBody(GSON.toJson(nnProps)).build());
Assert.assertEquals(404, response.getResponseCode());
// update nn's properties
response = executeHttp(HttpRequest.put(serviceURI.resolve("update/nn").toURL()).withBody(GSON.toJson(nnProps)).build());
Assert.assertEquals(200, response.getResponseCode());
// get properties for xx -> not found
response = executeHttp(HttpRequest.get(serviceURI.resolve("props/xx").toURL()).build());
Assert.assertEquals(404, response.getResponseCode());
// get properties for nn and validate
response = executeHttp(HttpRequest.get(serviceURI.resolve("props/nn").toURL()).build());
Assert.assertEquals(200, response.getResponseCode());
Map<String, String> returnedProps = GSON.fromJson(response.getResponseBodyAsString(), new TypeToken<Map<String, String>>() {
}.getType());
Assert.assertEquals(nnProps, returnedProps);
// write some data to the table
DataSetManager<Table> nnManager = getDataset("nn");
nnManager.get().put(new Put("x", "y", "z"));
nnManager.flush();
// in a new tx, validate that data is in table
Assert.assertFalse(nnManager.get().get(new Get("x")).isEmpty());
Assert.assertEquals("z", nnManager.get().get(new Get("x", "y")).getString("y"));
nnManager.flush();
// truncate xx -> not found
response = executeHttp(HttpRequest.post(serviceURI.resolve("truncate/xx").toURL()).build());
Assert.assertEquals(404, response.getResponseCode());
// truncate nn
response = executeHttp(HttpRequest.post(serviceURI.resolve("truncate/nn").toURL()).build());
Assert.assertEquals(200, response.getResponseCode());
// validate table is empty
Assert.assertTrue(nnManager.get().get(new Get("x")).isEmpty());
nnManager.flush();
// delete nn
response = executeHttp(HttpRequest.delete(serviceURI.resolve("delete/nn").toURL()).build());
Assert.assertEquals(200, response.getResponseCode());
// delete again -> not found
response = executeHttp(HttpRequest.delete(serviceURI.resolve("delete/nn").toURL()).build());
Assert.assertEquals(404, response.getResponseCode());
// delete xx which never existed -> not found
response = executeHttp(HttpRequest.delete(serviceURI.resolve("delete/xx").toURL()).build());
Assert.assertEquals(404, response.getResponseCode());
// exists should now return false for nn
response = executeHttp(HttpRequest.get(serviceURI.resolve("exists/nn").toURL()).build());
Assert.assertEquals(200, response.getResponseCode());
Assert.assertEquals("false", response.getResponseBodyAsString());
Assert.assertNull(getDataset("nn").get());
// test Admin.namespaceExists()
HttpRequest request = HttpRequest.get(serviceURI.resolve("namespaces/y").toURL()).build();
response = executeHttp(request);
Assert.assertEquals(404, response.getResponseCode());
// test Admin.getNamespaceSummary()
NamespaceMeta namespaceXMeta = new NamespaceMeta.Builder().setName(namespaceX).setGeneration(10L).build();
getNamespaceAdmin().create(namespaceXMeta);
request = HttpRequest.get(serviceURI.resolve("namespaces/" + namespaceX).toURL()).build();
response = executeHttp(request);
NamespaceSummary namespaceSummary = GSON.fromJson(response.getResponseBodyAsString(), NamespaceSummary.class);
NamespaceSummary expectedX = new NamespaceSummary(namespaceXMeta.getName(), namespaceXMeta.getDescription(), namespaceXMeta.getGeneration());
Assert.assertEquals(expectedX, namespaceSummary);
// test ArtifactManager.listArtifacts()
ArtifactId pluginArtifactId = new NamespaceId(namespaceX).artifact("r1", "1.0.0");
// add a plugin artifact to namespace X
addPluginArtifact(pluginArtifactId, ADMIN_APP_ARTIFACT, DummyPlugin.class);
// no plugins should be listed in the default namespace, but the app artifact should
request = HttpRequest.get(serviceURI.resolve("namespaces/default/plugins").toURL()).build();
response = executeHttp(request);
Assert.assertEquals(200, response.getResponseCode());
Type setType = new TypeToken<Set<ArtifactSummary>>() {
}.getType();
Assert.assertEquals(Collections.singleton(ADMIN_ARTIFACT_SUMMARY), GSON.fromJson(response.getResponseBodyAsString(), setType));
// the plugin should be listed in namespace X
request = HttpRequest.get(serviceURI.resolve("namespaces/x/plugins").toURL()).build();
response = executeHttp(request);
Assert.assertEquals(200, response.getResponseCode());
ArtifactSummary expected = new ArtifactSummary(pluginArtifactId.getArtifact(), pluginArtifactId.getVersion());
Assert.assertEquals(Collections.singleton(expected), GSON.fromJson(response.getResponseBodyAsString(), setType));
} finally {
serviceManager.stop();
if (getNamespaceAdmin().exists(new NamespaceId(namespaceX))) {
getNamespaceAdmin().delete(new NamespaceId(namespaceX));
}
}
}
use of io.cdap.cdap.proto.id.ArtifactId in project cdap by caskdata.
the class RuntimeServiceMainTest method testRuntimeService.
@Test
public void testRuntimeService() throws Exception {
ArtifactId artifactId = NamespaceId.DEFAULT.artifact("test", "1.0");
ProgramRunId programRunId = NamespaceId.DEFAULT.app("app").worker("worker").run(RunIds.generate());
Map<String, String> systemArgs = ImmutableMap.of(SystemArguments.PROFILE_PROVISIONER, NativeProvisioner.SPEC.getName(), SystemArguments.PROFILE_NAME, "default");
ProgramOptions programOptions = new SimpleProgramOptions(programRunId.getParent(), new BasicArguments(systemArgs), new BasicArguments());
ProgramDescriptor programDescriptor = new ProgramDescriptor(programRunId.getParent(), null, artifactId);
// Write out program state events to simulate program start
Injector appFabricInjector = getServiceMainInstance(AppFabricServiceMain.class).getInjector();
CConfiguration cConf = appFabricInjector.getInstance(CConfiguration.class);
ProgramStatePublisher programStatePublisher = new MessagingProgramStatePublisher(appFabricInjector.getInstance(MessagingService.class), NamespaceId.SYSTEM.topic(cConf.get(Constants.AppFabric.PROGRAM_STATUS_RECORD_EVENT_TOPIC)), RetryStrategies.fromConfiguration(cConf, "system.program.state."));
new MessagingProgramStateWriter(programStatePublisher).start(programRunId, programOptions, null, programDescriptor);
Injector injector = getServiceMainInstance(RuntimeServiceMain.class).getInjector();
TransactionRunner txRunner = injector.getInstance(TransactionRunner.class);
// Should see a STARTING record in the runtime store
Tasks.waitFor(ProgramRunStatus.STARTING, () -> {
RunRecordDetail detail = TransactionRunners.run(txRunner, context -> {
return AppMetadataStore.create(context).getRun(programRunId);
});
return detail == null ? null : detail.getStatus();
}, 5, TimeUnit.SECONDS);
ProgramStateWriter programStateWriter = createProgramStateWriter(injector, programRunId);
// Write a running state. We should see a RUNNING record in the runtime store
programStateWriter.running(programRunId, null);
Tasks.waitFor(ProgramRunStatus.RUNNING, () -> {
RunRecordDetail detail = TransactionRunners.run(txRunner, context -> {
return AppMetadataStore.create(context).getRun(programRunId);
});
return detail == null ? null : detail.getStatus();
}, 5, TimeUnit.SECONDS);
// Write a complete state. The run record should be removed in the runtime store
programStateWriter.completed(programRunId);
Tasks.waitFor(true, () -> TransactionRunners.run(txRunner, context -> AppMetadataStore.create(context).getRun(programRunId) == null), 5, TimeUnit.SECONDS);
}
Aggregations