use of co.cask.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class AppLifecycleHttpHandler method deployApplication.
private BodyConsumer deployApplication(final HttpResponder responder, final NamespaceId namespace, final String appId, final String archiveName, final String configString, @Nullable final String ownerPrincipal, final boolean updateSchedules) throws IOException {
Id.Namespace idNamespace = Id.Namespace.fromEntityId(namespace);
Location namespaceHomeLocation = namespacedLocationFactory.get(namespace);
if (!namespaceHomeLocation.exists()) {
String msg = String.format("Home directory %s for namespace %s not found", namespaceHomeLocation, namespace.getNamespace());
LOG.error(msg);
responder.sendString(HttpResponseStatus.NOT_FOUND, msg);
return null;
}
if (archiveName == null || archiveName.isEmpty()) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, String.format("%s header not present. Please include the header and set its value to the jar name.", ARCHIVE_NAME_HEADER), new DefaultHttpHeaders().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE));
return null;
}
// TODO: (CDAP-3258) error handling needs to be refactored here, should be able just to throw the exception,
// but the caller catches all exceptions and responds with a 500
final Id.Artifact artifactId;
try {
artifactId = Id.Artifact.parse(idNamespace, archiveName);
} catch (IllegalArgumentException e) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
return null;
}
KerberosPrincipalId ownerPrincipalId = ownerPrincipal == null ? null : new KerberosPrincipalId(ownerPrincipal);
// Store uploaded content to a local temp file
String namespacesDir = configuration.get(Constants.Namespace.NAMESPACES_DIR);
File localDataDir = new File(configuration.get(Constants.CFG_LOCAL_DATA_DIR));
File namespaceBase = new File(localDataDir, namespacesDir);
File tempDir = new File(new File(namespaceBase, namespace.getNamespace()), configuration.get(Constants.AppFabric.TEMP_DIR)).getAbsoluteFile();
if (!DirUtils.mkdirs(tempDir)) {
throw new IOException("Could not create temporary directory at: " + tempDir);
}
final KerberosPrincipalId finalOwnerPrincipalId = ownerPrincipalId;
return new AbstractBodyConsumer(File.createTempFile("app-", ".jar", tempDir)) {
@Override
protected void onFinish(HttpResponder responder, File uploadedFile) {
try {
// deploy app
ApplicationWithPrograms app = applicationLifecycleService.deployAppAndArtifact(namespace, appId, artifactId, uploadedFile, configString, finalOwnerPrincipalId, createProgramTerminator(), updateSchedules);
LOG.info("Successfully deployed app {} in namespace {} from artifact {} with configuration {} and " + "principal {}", app.getApplicationId().getApplication(), namespace.getNamespace(), artifactId, configString, finalOwnerPrincipalId);
responder.sendString(HttpResponseStatus.OK, String.format("Successfully deployed app %s", app.getApplicationId().getApplication()));
} catch (InvalidArtifactException e) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
} catch (ArtifactAlreadyExistsException e) {
responder.sendString(HttpResponseStatus.CONFLICT, String.format("Artifact '%s' already exists. Please use the API that creates an application from an existing artifact. " + "If you are trying to replace the artifact, please delete it and then try again.", artifactId));
} catch (WriteConflictException e) {
// don't really expect this to happen. It means after multiple retries there were still write conflicts.
LOG.warn("Write conflict while trying to add artifact {}.", artifactId, e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Write conflict while adding artifact. This can happen if multiple requests to add " + "the same artifact occur simultaneously. Please try again.");
} catch (UnauthorizedException e) {
responder.sendString(HttpResponseStatus.FORBIDDEN, e.getMessage());
} catch (ConflictException e) {
responder.sendString(HttpResponseStatus.CONFLICT, e.getMessage());
} catch (Exception e) {
LOG.error("Deploy failure", e);
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
}
}
};
}
use of co.cask.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method resetLogLevels.
private void resetLogLevels(FullHttpRequest request, HttpResponder responder, String namespace, String appName, String appVersion, String type, String programName, @Nullable String component, String runId) throws Exception {
ProgramType programType = getProgramType(type);
if (programType == null) {
throw new BadRequestException("Invalid program type provided");
}
try {
Set<String> loggerNames = parseBody(request, SET_STRING_TYPE);
lifecycleService.resetProgramLogLevels(new ApplicationId(namespace, appName, appVersion).program(programType, programName), loggerNames == null ? Collections.emptySet() : loggerNames, component, runId);
responder.sendStatus(HttpResponseStatus.OK);
} catch (JsonSyntaxException e) {
throw new BadRequestException("Invalid JSON in body");
} catch (SecurityException e) {
throw new UnauthorizedException("Unauthorized to reset the log levels");
}
}
use of co.cask.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class DatasetTypeService method deleteAll.
/**
* Deletes all {@link DatasetModuleMeta dataset modules} in the specified {@link NamespaceId namespace}.
*/
void deleteAll(NamespaceId namespaceId) throws Exception {
Principal principal = authenticationContext.getPrincipal();
authorizationEnforcer.enforce(namespaceId, principal, Action.ADMIN);
if (NamespaceId.SYSTEM.equals(namespaceId)) {
throw new UnauthorizedException(String.format("Cannot delete modules from '%s' namespace.", namespaceId));
}
ensureNamespaceExists(namespaceId);
// revoke all privileges on all modules
for (DatasetModuleMeta meta : typeManager.getModules(namespaceId)) {
privilegesManager.revoke(namespaceId.datasetModule(meta.getName()));
}
try {
typeManager.deleteModules(namespaceId);
} catch (DatasetModuleConflictException e) {
throw new ConflictException(e.getMessage(), e);
}
}
use of co.cask.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class DatasetTypeService method addModule.
/**
* Adds a new {@link DatasetModule}.
*
* @param datasetModuleId the {@link DatasetModuleId} for the module to be added
* @param className the module class name specified in the HTTP header
* @param forceUpdate if true, an update will be allowed even if there are conflicts with other modules, or if
* removal of a type would break other modules' dependencies
* @return a {@link BodyConsumer} to upload the module jar in chunks
* @throws NotFoundException if the namespace in which the module is being added is not found
* @throws IOException if there are issues while performing I/O like creating temporary directories, moving/unpacking
* module jar files
* @throws DatasetModuleConflictException if #forceUpdate is {@code false}, and there are conflicts with other modules
*/
BodyConsumer addModule(final DatasetModuleId datasetModuleId, final String className, final boolean forceUpdate) throws Exception {
NamespaceId namespaceId = datasetModuleId.getParent();
final Principal principal = authenticationContext.getPrincipal();
// enforce that the principal has WRITE access on the namespace
authorizationEnforcer.enforce(namespaceId, principal, Action.WRITE);
if (NamespaceId.SYSTEM.equals(namespaceId)) {
throw new UnauthorizedException(String.format("Cannot add module '%s' to '%s' namespace.", datasetModuleId.getModule(), datasetModuleId.getNamespace()));
}
ensureNamespaceExists(namespaceId);
// It is now determined that a new dataset module will be deployed. First grant privileges, then deploy the module.
// If creation fails, revoke the granted privileges. This ensures that just like delete, there may be orphaned
// privileges in rare scenarios, but there can never be orphaned datasets.
// If the module previously existed and was deleted, but revoking privileges somehow failed, there may be orphaned
// privileges for the module. Revoke them first, so no users unintentionally get privileges on the dataset.
revokeAllPrivilegesOnModule(datasetModuleId);
grantAllPrivilegesOnModule(datasetModuleId, principal);
try {
return createModuleConsumer(datasetModuleId, className, forceUpdate, principal);
} catch (Exception e) {
revokeAllPrivilegesOnModule(datasetModuleId);
throw e;
}
}
use of co.cask.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.
the class DatasetTypeService method delete.
/**
* Deletes the specified {@link DatasetModuleId}
*/
void delete(DatasetModuleId datasetModuleId) throws Exception {
NamespaceId namespaceId = datasetModuleId.getParent();
if (NamespaceId.SYSTEM.equals(namespaceId)) {
throw new UnauthorizedException(String.format("Cannot delete module '%s' from '%s' namespace.", datasetModuleId.getModule(), datasetModuleId.getNamespace()));
}
ensureNamespaceExists(namespaceId);
DatasetModuleMeta moduleMeta = typeManager.getModule(datasetModuleId);
if (moduleMeta == null) {
throw new DatasetModuleNotFoundException(datasetModuleId);
}
Principal principal = authenticationContext.getPrincipal();
authorizationEnforcer.enforce(datasetModuleId, principal, Action.ADMIN);
try {
typeManager.deleteModule(datasetModuleId);
} catch (DatasetModuleConflictException e) {
throw new DatasetModuleCannotBeDeletedException(datasetModuleId, e.getMessage());
}
// revoke all privileges on the module to be deleted
revokeAllPrivilegesOnModule(datasetModuleId, moduleMeta);
}
Aggregations