use of io.cdap.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method getRunCounts.
/**
* Returns the run counts for all program runnables that are passed into the data. The data is an array of
* Json objects where each object must contain the following three elements: appId, programType, and programId.
* The max number of programs in the request is 100.
* <p>
* Example input:
* <pre><code>
* [{"appId": "App1", "programType": "Service", "programId": "Service1"},
* {"appId": "App1", "programType": "Workflow", "programId": "testWorkflow"},
* {"appId": "App2", "programType": "Workflow", "programId": "DataPipelineWorkflow"}]
* </code></pre>
* </p><p>
* </p><p>
* The response will be an array of JsonObjects each of which will contain the three input parameters
* as well as 2 fields, "runCount" which maps to the count of the program and "statusCode" which maps to the
* status code for the data in that JsonObjects.
* </p><p>
* If an error occurs in the input (for the example above, workflow in app1 does not exist),
* then all JsonObjects for which the parameters have a valid status will have the count field but all JsonObjects
* for which the parameters do not have a valid status will have an error message and statusCode.
* </p><p>
* For example, if there is no workflow in App1 in the data above, then the response would be 200 OK with following
* possible data:
* </p>
* <pre><code>
* [{"appId": "App1", "programType": "Service", "programId": "Service1",
* "statusCode": 200, "runCount": 20},
* {"appId": "App1", "programType": "Workflow", "programId": "testWorkflow", "statusCode": 404,
* "error": "Program 'testWorkflow' is not found"},
* {"appId": "App2", "programType": "Workflow", "programId": "DataPipelineWorkflow",
* "statusCode": 200, "runCount": 300}]
* </code></pre>
*/
@POST
@Path("/runcount")
public void getRunCounts(FullHttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId) throws Exception {
List<BatchProgram> programs = validateAndGetBatchInput(request, BATCH_PROGRAMS_TYPE);
if (programs.size() > 100) {
throw new BadRequestException(String.format("%d programs found in the request, the maximum number " + "supported is 100", programs.size()));
}
List<ProgramId> programIds = programs.stream().map(batchProgram -> new ProgramId(namespaceId, batchProgram.getAppId(), batchProgram.getProgramType(), batchProgram.getProgramId())).collect(Collectors.toList());
List<BatchProgramCount> counts = new ArrayList<>(programs.size());
for (RunCountResult runCountResult : lifecycleService.getProgramRunCounts(programIds)) {
ProgramId programId = runCountResult.getProgramId();
Exception exception = runCountResult.getException();
if (exception == null) {
counts.add(new BatchProgramCount(programId, HttpResponseStatus.OK.code(), null, runCountResult.getCount()));
} else if (exception instanceof NotFoundException) {
counts.add(new BatchProgramCount(programId, HttpResponseStatus.NOT_FOUND.code(), exception.getMessage(), null));
} else if (exception instanceof UnauthorizedException) {
counts.add(new BatchProgramCount(programId, HttpResponseStatus.FORBIDDEN.code(), exception.getMessage(), null));
} else {
counts.add(new BatchProgramCount(programId, HttpResponseStatus.INTERNAL_SERVER_ERROR.code(), exception.getMessage(), null));
}
}
responder.sendJson(HttpResponseStatus.OK, GSON.toJson(counts));
}
use of io.cdap.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class RuntimeHandler method writeMessages.
/**
* Handles call for writing to TMS from the program runtime for a given program run. The POST body is an
* avro array of bytes.
*/
@Path("/topics/{topic}")
@POST
public BodyConsumer writeMessages(HttpRequest request, HttpResponder responder, @PathParam("namespace") String namespace, @PathParam("app") String app, @PathParam("version") String version, @PathParam("program-type") String programType, @PathParam("program") String program, @PathParam("run") String run, @PathParam("topic") String topic) throws Exception {
if (!"avro/binary".equals(request.headers().get(HttpHeaderNames.CONTENT_TYPE))) {
throw new BadRequestException("Only avro/binary content type is supported.");
}
ApplicationId appId = new NamespaceId(namespace).app(app, version);
ProgramRunId programRunId = new ProgramRunId(appId, ProgramType.valueOfCategoryName(programType, BadRequestException::new), program, run);
ProgramRunInfo programRunInfo = requestValidator.getProgramRunStatus(programRunId, request);
if (!allowedTopics.contains(topic)) {
throw new UnauthorizedException("Access denied for topic " + topic);
}
TopicId topicId = NamespaceId.SYSTEM.topic(topic);
if (topic.startsWith(logsTopicPrefix)) {
return new MessageBodyConsumer(topicId, logProcessor::process, programRunInfo);
}
return new MessageBodyConsumer(topicId, payloads -> {
try {
messagingContext.getDirectMessagePublisher().publish(topicId.getNamespace(), topicId.getTopic(), payloads);
} catch (TopicNotFoundException e) {
throw new BadRequestException(e);
}
}, programRunInfo);
}
use of io.cdap.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class LeaderElectionMessagingServiceTest method testFencing.
@Test
public void testFencing() throws IOException, InterruptedException, ExecutionException, TimeoutException, UnauthorizedException {
final TopicId topicId = NamespaceId.SYSTEM.topic("topic");
// Change the fencing time
long oldFencingDelay = cConf.getLong(Constants.MessagingSystem.HA_FENCING_DELAY_SECONDS);
cConf.setLong(Constants.MessagingSystem.HA_FENCING_DELAY_SECONDS, 3L);
try {
Injector injector = createInjector(0);
ZKClientService zkClient = injector.getInstance(ZKClientService.class);
zkClient.startAndWait();
final MessagingService messagingService = injector.getInstance(MessagingService.class);
if (messagingService instanceof Service) {
((Service) messagingService).startAndWait();
}
// Shouldn't be serving request yet.
try {
messagingService.listTopics(NamespaceId.SYSTEM);
Assert.fail("Expected service unavailable exception");
} catch (ServiceUnavailableException e) {
// expected
}
// Retry until pass the fencing delay (with some buffer)
Tasks.waitFor(topicId, new Callable<TopicId>() {
@Override
public TopicId call() throws Exception {
try {
return messagingService.getTopic(topicId).getTopicId();
} catch (ServiceUnavailableException e) {
return null;
}
}
}, 10L, TimeUnit.SECONDS, 200, TimeUnit.MILLISECONDS);
if (messagingService instanceof Service) {
((Service) messagingService).stopAndWait();
}
zkClient.stopAndWait();
} finally {
cConf.setLong(Constants.MessagingSystem.HA_FENCING_DELAY_SECONDS, oldFencingDelay);
}
}
use of io.cdap.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class InMemoryAccessController method enforce.
private void enforce(EntityId entity, @Nullable EntityType childType, Principal principal, Set<? extends Permission> permissions) throws UnauthorizedException {
// super users do not have any enforcement
if (superUsers.contains(principal) || superUsers.contains(allSuperUsers)) {
return;
}
// permissions allowed for this principal
Set<? extends Permission> allowed = getPermissions(entity, childType, principal);
if (allowed.containsAll(permissions)) {
return;
}
Set<Permission> allowedForRoles = new HashSet<>();
// permissions allowed for any of the roles to which this principal belongs if its not a role
if (principal.getType() != Principal.PrincipalType.ROLE) {
for (Role role : getRoles(principal)) {
allowedForRoles.addAll(getPermissions(entity, role));
}
}
if (!allowedForRoles.containsAll(permissions)) {
throw new UnauthorizedException(principal, Sets.difference(permissions, allowed), entity, childType);
}
}
use of io.cdap.cdap.security.spi.authorization.UnauthorizedException 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();
}
Aggregations