use of io.cdap.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class AuthorizationTest method testScheduleAuth.
@Test
public void testScheduleAuth() throws Exception {
createAuthNamespace();
ApplicationId appId = AUTH_NAMESPACE.app(AppWithSchedule.class.getSimpleName());
Map<EntityId, Set<? extends Permission>> neededPrivileges = ImmutableMap.<EntityId, Set<? extends Permission>>builder().put(appId, EnumSet.of(StandardPermission.CREATE, StandardPermission.GET)).put(AUTH_NAMESPACE.artifact(AppWithSchedule.class.getSimpleName(), "1.0-SNAPSHOT"), EnumSet.of(StandardPermission.CREATE)).put(AUTH_NAMESPACE.dataset(AppWithSchedule.INPUT_NAME), EnumSet.of(StandardPermission.CREATE, StandardPermission.GET)).put(AUTH_NAMESPACE.dataset(AppWithSchedule.OUTPUT_NAME), EnumSet.of(StandardPermission.CREATE, StandardPermission.GET)).put(AUTH_NAMESPACE.datasetType(ObjectStore.class.getName()), EnumSet.of(StandardPermission.UPDATE)).build();
setUpPrivilegeAndRegisterForDeletion(ALICE, neededPrivileges);
ApplicationManager appManager = deployApplication(AUTH_NAMESPACE, AppWithSchedule.class);
String workflowName = AppWithSchedule.SampleWorkflow.class.getSimpleName();
ProgramId workflowID = new ProgramId(AUTH_NAMESPACE.getNamespace(), AppWithSchedule.class.getSimpleName(), ProgramType.WORKFLOW, workflowName);
cleanUpEntities.add(workflowID);
final WorkflowManager workflowManager = appManager.getWorkflowManager(workflowName);
ScheduleManager scheduleManager = workflowManager.getSchedule(AppWithSchedule.EVERY_HOUR_SCHEDULE);
// switch to BOB
SecurityRequestContext.setUserId(BOB.getName());
// try to resume schedule as BOB. It should fail since BOB does not have execute privileges on the programs
try {
scheduleManager.resume();
Assert.fail("Resuming schedule should have failed since BOB does not have EXECUTE on the program");
} catch (UnauthorizedException e) {
// Expected
}
// bob should also not be able see the status of the schedule
try {
scheduleManager.status(HttpURLConnection.HTTP_FORBIDDEN);
Assert.fail("Getting schedule status should have failed since BOB does not have any privilege on the program");
} catch (UnauthorizedException e) {
// Expected
}
// give BOB READ permission in the workflow
grantAndAssertSuccess(workflowID, BOB, EnumSet.of(StandardPermission.GET));
// switch to BOB
SecurityRequestContext.setUserId(BOB.getName());
// try to resume schedule as BOB. It should fail since BOB has READ but not EXECUTE on the workflow
try {
scheduleManager.resume();
Assert.fail("Resuming schedule should have failed since BOB does not have EXECUTE on the program");
} catch (UnauthorizedException e) {
// Expected
}
// but BOB should be able to get schedule status now
Assert.assertEquals(ProgramScheduleStatus.SUSPENDED.name(), scheduleManager.status(HttpURLConnection.HTTP_OK));
// give BOB EXECUTE permission in the workflow
grantAndAssertSuccess(workflowID, BOB, EnumSet.of(ApplicationPermission.EXECUTE));
// switch to BOB
SecurityRequestContext.setUserId(BOB.getName());
// try to resume the schedule. This should pass and workflow should run
scheduleManager.resume();
Assert.assertEquals(ProgramScheduleStatus.SCHEDULED.name(), scheduleManager.status(HttpURLConnection.HTTP_OK));
// suspend the schedule so that it does not start running again
scheduleManager.suspend();
Assert.assertEquals(ProgramScheduleStatus.SUSPENDED.name(), scheduleManager.status(HttpURLConnection.HTTP_OK));
ScheduleId scheduleId = new ScheduleId(appId.getNamespace(), appId.getApplication(), appId.getVersion(), "testSchedule");
ScheduleDetail scheduleDetail = new ScheduleDetail(AUTH_NAMESPACE.getNamespace(), AppWithSchedule.class.getSimpleName(), "1.0-SNAPSHOT", "testSchedule", "Something 2", new ScheduleProgramInfo(SchedulableProgramType.WORKFLOW, workflowName), Collections.<String, String>emptyMap(), new TimeTrigger("*/1 * * * *"), Collections.<Constraint>emptyList(), TimeUnit.HOURS.toMillis(6), null, null);
try {
addSchedule(scheduleId, scheduleDetail);
Assert.fail("Adding schedule should fail since BOB does not have AMDIN on the app");
} catch (UnauthorizedException e) {
// expected
}
// grant BOB EXECUTE on the app
grantAndAssertSuccess(appId, BOB, EnumSet.of(ApplicationPermission.EXECUTE));
// add schedule should succeed
addSchedule(scheduleId, scheduleDetail);
Assert.assertEquals(ProgramScheduleStatus.SUSPENDED.name(), workflowManager.getSchedule(scheduleId.getSchedule()).status(HttpURLConnection.HTTP_OK));
// update schedule should succeed
updateSchedule(scheduleId, scheduleDetail);
Assert.assertEquals(ProgramScheduleStatus.SUSPENDED.name(), workflowManager.getSchedule(scheduleId.getSchedule()).status(HttpURLConnection.HTTP_OK));
// revoke EXECUTE from BOB
getAccessController().revoke(Authorizable.fromEntityId(appId), BOB, EnumSet.of(ApplicationPermission.EXECUTE));
try {
// delete schedule should fail since we revoke the ADMIN privilege from BOB
deleteSchedule(scheduleId);
Assert.fail("Deleting schedule should fail since BOB does not have AMDIN on the app");
} catch (UnauthorizedException e) {
// expected
}
try {
updateSchedule(scheduleId, scheduleDetail);
Assert.fail("Updating schedule should fail since BOB does not have AMDIN on the app");
} catch (UnauthorizedException e) {
// expected
}
// grant BOB EXECUTE on the app again
grantAndAssertSuccess(appId, BOB, EnumSet.of(ApplicationPermission.EXECUTE));
deleteSchedule(scheduleId);
workflowManager.getSchedule(scheduleId.getSchedule()).status(HttpURLConnection.HTTP_NOT_FOUND);
// switch to Alice
SecurityRequestContext.setUserId(ALICE.getName());
}
use of io.cdap.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class AuthorizationTest method testDeleteSystemDatasets.
/**
* This test is to make sure we do not bypass the authorization check for datasets in system namespace
*/
@Test
public void testDeleteSystemDatasets() throws Exception {
// create a random user and try to delete a system dataset
UserGroupInformation remoteUser = UserGroupInformation.createRemoteUser("random");
remoteUser.doAs(new PrivilegedAction<Void>() {
@Override
public Void run() {
try {
deleteDatasetInstance(NamespaceId.SYSTEM.dataset("app.meta"));
Assert.fail();
} catch (UnauthorizedException e) {
// Expected
} catch (Exception e) {
if (!(e.getCause() instanceof UnauthorizedException)) {
throw new AssertionError("Getting incorrect exception", e);
}
}
return null;
}
});
}
use of io.cdap.cdap.security.spi.authorization.UnauthorizedException in project cdap by cdapio.
the class RESTClient method execute.
public HttpResponse execute(HttpRequest request, int... allowedErrorCodes) throws IOException, UnauthenticatedException, UnauthorizedException {
int currentTry = 0;
HttpResponse response;
int responseCode;
boolean allowUnavailable = ArrayUtils.contains(allowedErrorCodes, HttpURLConnection.HTTP_UNAVAILABLE);
do {
onRequest(request, currentTry);
response = HttpRequests.execute(request, clientConfig.getDefaultRequestConfig());
responseCode = response.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_UNAVAILABLE || allowUnavailable) {
// only retry if unavailable
break;
}
currentTry++;
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
break;
}
} while (currentTry <= clientConfig.getUnavailableRetryLimit());
onResponse(request, response, currentTry);
if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
throw new UnauthenticatedException("Unauthorized status code received from the server.");
}
if (responseCode == HttpURLConnection.HTTP_FORBIDDEN) {
throw new UnauthorizedException(response.getResponseBodyAsString());
}
if (!isSuccessful(responseCode) && !ArrayUtils.contains(allowedErrorCodes, responseCode)) {
throw new IOException(responseCode + ": " + response.getResponseBodyAsString());
}
return response;
}
use of io.cdap.cdap.security.spi.authorization.UnauthorizedException in project cdap by cdapio.
the class DefaultAccessEnforcerTest method testPropagationDisabled.
@Test
public void testPropagationDisabled() throws IOException, AccessException {
CConfiguration cConfCopy = CConfiguration.copy(CCONF);
ControllerWrapper controllerWrapper = createControllerWrapper(cConfCopy, SCONF, null);
controllerWrapper.accessController.grant(Authorizable.fromEntityId(NS), ALICE, ImmutableSet.of(StandardPermission.UPDATE));
DefaultAccessEnforcer accessEnforcer = controllerWrapper.defaultAccessEnforcer;
accessEnforcer.enforce(NS, ALICE, StandardPermission.UPDATE);
try {
accessEnforcer.enforce(APP, ALICE, StandardPermission.UPDATE);
Assert.fail("Alice should not have ADMIN privilege on the APP.");
} catch (UnauthorizedException ignored) {
// expected
}
// Verify the metrics context was called with correct metrics
verify(controllerWrapper.mockMetricsContext, times(1)).increment(Constants.Metrics.Authorization.EXTENSION_CHECK_SUCCESS_COUNT, 1);
verify(controllerWrapper.mockMetricsContext, times(1)).increment(Constants.Metrics.Authorization.EXTENSION_CHECK_FAILURE_COUNT, 1);
verify(controllerWrapper.mockMetricsContext, times(2)).gauge(eq(Constants.Metrics.Authorization.EXTENSION_CHECK_MILLIS), any(Long.class));
}
use of io.cdap.cdap.security.spi.authorization.UnauthorizedException in project cdap by cdapio.
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);
}
}
Aggregations