Search in sources :

Example 26 with UnauthorizedException

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());
            }
        }
    };
}
Also used : HttpResponder(co.cask.http.HttpResponder) ConflictException(co.cask.cdap.common.ConflictException) WriteConflictException(co.cask.cdap.internal.app.runtime.artifact.WriteConflictException) IOException(java.io.IOException) ApplicationNotFoundException(co.cask.cdap.common.ApplicationNotFoundException) NamespaceNotFoundException(co.cask.cdap.common.NamespaceNotFoundException) ArtifactNotFoundException(co.cask.cdap.common.ArtifactNotFoundException) ArtifactAlreadyExistsException(co.cask.cdap.common.ArtifactAlreadyExistsException) ConflictException(co.cask.cdap.common.ConflictException) BadRequestException(co.cask.cdap.common.BadRequestException) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) DatasetManagementException(co.cask.cdap.api.dataset.DatasetManagementException) WriteConflictException(co.cask.cdap.internal.app.runtime.artifact.WriteConflictException) JsonSyntaxException(com.google.gson.JsonSyntaxException) IOException(java.io.IOException) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException) ExecutionException(java.util.concurrent.ExecutionException) NotFoundException(co.cask.cdap.common.NotFoundException) ArtifactAlreadyExistsException(co.cask.cdap.common.ArtifactAlreadyExistsException) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) AbstractBodyConsumer(co.cask.cdap.common.http.AbstractBodyConsumer) WriteConflictException(co.cask.cdap.internal.app.runtime.artifact.WriteConflictException) ApplicationWithPrograms(co.cask.cdap.internal.app.deploy.pipeline.ApplicationWithPrograms) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) ProgramId(co.cask.cdap.proto.id.ProgramId) Id(co.cask.cdap.common.id.Id) NamespaceId(co.cask.cdap.proto.id.NamespaceId) KerberosPrincipalId(co.cask.cdap.proto.id.KerberosPrincipalId) ApplicationId(co.cask.cdap.proto.id.ApplicationId) EntityId(co.cask.cdap.proto.id.EntityId) KerberosPrincipalId(co.cask.cdap.proto.id.KerberosPrincipalId) File(java.io.File) InvalidArtifactException(co.cask.cdap.common.InvalidArtifactException) Location(org.apache.twill.filesystem.Location)

Example 27 with UnauthorizedException

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");
    }
}
Also used : JsonSyntaxException(com.google.gson.JsonSyntaxException) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) BadRequestException(co.cask.cdap.common.BadRequestException) ProgramType(co.cask.cdap.proto.ProgramType) ApplicationId(co.cask.cdap.proto.id.ApplicationId)

Example 28 with UnauthorizedException

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);
    }
}
Also used : DatasetModuleConflictException(co.cask.cdap.data2.datafabric.dataset.type.DatasetModuleConflictException) DatasetModuleMeta(co.cask.cdap.proto.DatasetModuleMeta) ConflictException(co.cask.cdap.common.ConflictException) DatasetModuleConflictException(co.cask.cdap.data2.datafabric.dataset.type.DatasetModuleConflictException) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) Principal(co.cask.cdap.proto.security.Principal)

Example 29 with UnauthorizedException

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;
    }
}
Also used : UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) NamespaceId(co.cask.cdap.proto.id.NamespaceId) Principal(co.cask.cdap.proto.security.Principal) NamespaceNotFoundException(co.cask.cdap.common.NamespaceNotFoundException) ConflictException(co.cask.cdap.common.ConflictException) DatasetModuleConflictException(co.cask.cdap.data2.datafabric.dataset.type.DatasetModuleConflictException) DatasetTypeNotFoundException(co.cask.cdap.common.DatasetTypeNotFoundException) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) DatasetModuleNotFoundException(co.cask.cdap.common.DatasetModuleNotFoundException) IOException(java.io.IOException) DatasetModuleCannotBeDeletedException(co.cask.cdap.common.DatasetModuleCannotBeDeletedException) NotFoundException(co.cask.cdap.common.NotFoundException)

Example 30 with UnauthorizedException

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);
}
Also used : DatasetModuleNotFoundException(co.cask.cdap.common.DatasetModuleNotFoundException) DatasetModuleConflictException(co.cask.cdap.data2.datafabric.dataset.type.DatasetModuleConflictException) DatasetModuleMeta(co.cask.cdap.proto.DatasetModuleMeta) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) NamespaceId(co.cask.cdap.proto.id.NamespaceId) DatasetModuleCannotBeDeletedException(co.cask.cdap.common.DatasetModuleCannotBeDeletedException) Principal(co.cask.cdap.proto.security.Principal)

Aggregations

UnauthorizedException (co.cask.cdap.security.spi.authorization.UnauthorizedException)49 Test (org.junit.Test)18 IOException (java.io.IOException)15 EntityId (co.cask.cdap.proto.id.EntityId)13 Principal (co.cask.cdap.proto.security.Principal)13 Action (co.cask.cdap.proto.security.Action)12 BadRequestException (co.cask.cdap.common.BadRequestException)11 ApplicationId (co.cask.cdap.proto.id.ApplicationId)10 NamespaceNotFoundException (co.cask.cdap.common.NamespaceNotFoundException)9 JsonSyntaxException (com.google.gson.JsonSyntaxException)9 ExecutionException (java.util.concurrent.ExecutionException)9 NotFoundException (co.cask.cdap.common.NotFoundException)8 NamespaceId (co.cask.cdap.proto.id.NamespaceId)7 DatasetManagementException (co.cask.cdap.api.dataset.DatasetManagementException)6 ConflictException (co.cask.cdap.common.ConflictException)6 StreamId (co.cask.cdap.proto.id.StreamId)6 ArtifactAlreadyExistsException (co.cask.cdap.common.ArtifactAlreadyExistsException)5 ArtifactNotFoundException (co.cask.cdap.common.ArtifactNotFoundException)5 WriteConflictException (co.cask.cdap.internal.app.runtime.artifact.WriteConflictException)5 NamespaceMeta (co.cask.cdap.proto.NamespaceMeta)5