Search in sources :

Example 46 with UnauthorizedException

use of co.cask.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.

the class ArtifactHttpHandler method addArtifact.

@POST
@Path("/namespaces/{namespace-id}/artifacts/{artifact-name}")
@AuditPolicy(AuditDetail.HEADERS)
public BodyConsumer addArtifact(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") final String namespaceId, @PathParam("artifact-name") final String artifactName, @HeaderParam(VERSION_HEADER) final String artifactVersion, @HeaderParam(EXTENDS_HEADER) final String parentArtifactsStr, @HeaderParam(PLUGINS_HEADER) String pluginClasses) throws NamespaceNotFoundException, BadRequestException {
    final NamespaceId namespace = validateAndGetNamespace(namespaceId);
    // and validated there
    if (artifactVersion != null && !artifactVersion.isEmpty()) {
        validateAndGetArtifactId(namespace, artifactName, artifactVersion);
    }
    final Set<ArtifactRange> parentArtifacts = parseExtendsHeader(namespace, parentArtifactsStr);
    final Set<PluginClass> additionalPluginClasses;
    if (pluginClasses == null) {
        additionalPluginClasses = ImmutableSet.of();
    } else {
        try {
            additionalPluginClasses = GSON.fromJson(pluginClasses, PLUGINS_TYPE);
        } catch (JsonParseException e) {
            responder.sendString(HttpResponseStatus.BAD_REQUEST, String.format("%s header '%s' is invalid: %s", PLUGINS_HEADER, pluginClasses, e.getMessage()));
            return null;
        }
    }
    try {
        // copy the artifact contents to local tmp directory
        final File destination = File.createTempFile("artifact-", ".jar", tmpDir);
        return new AbstractBodyConsumer(destination) {

            @Override
            protected void onFinish(HttpResponder responder, File uploadedFile) {
                try {
                    String version = (artifactVersion == null || artifactVersion.isEmpty()) ? getBundleVersion(uploadedFile) : artifactVersion;
                    ArtifactId artifactId = validateAndGetArtifactId(namespace, artifactName, version);
                    // add the artifact to the repo
                    artifactRepository.addArtifact(Id.Artifact.fromEntityId(artifactId), uploadedFile, parentArtifacts, additionalPluginClasses);
                    responder.sendString(HttpResponseStatus.OK, "Artifact added successfully");
                } catch (ArtifactRangeNotFoundException e) {
                    responder.sendString(HttpResponseStatus.NOT_FOUND, e.getMessage());
                } catch (ArtifactAlreadyExistsException e) {
                    responder.sendString(HttpResponseStatus.CONFLICT, e.getMessage());
                } catch (WriteConflictException e) {
                    responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Conflict while writing artifact, please try again.");
                } catch (IOException e) {
                    LOG.error("Exception while trying to write artifact {}-{}-{}.", namespaceId, artifactName, artifactVersion, e);
                    responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Error performing IO while writing artifact.");
                } catch (BadRequestException e) {
                    responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
                } catch (UnauthorizedException e) {
                    responder.sendString(HttpResponseStatus.FORBIDDEN, e.getMessage());
                } catch (Exception e) {
                    LOG.error("Error while writing artifact {}-{}-{}", namespaceId, artifactName, artifactVersion, e);
                    responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Error while adding artifact.");
                }
            }

            private String getBundleVersion(File file) throws BadRequestException, IOException {
                try (JarFile jarFile = new JarFile(file)) {
                    Manifest manifest = jarFile.getManifest();
                    if (manifest == null) {
                        throw new BadRequestException("Unable to derive version from artifact because it does not contain a manifest. " + "Please package the jar with a manifest, or explicitly specify the artifact version.");
                    }
                    Attributes attributes = manifest.getMainAttributes();
                    String version = attributes == null ? null : attributes.getValue(ManifestFields.BUNDLE_VERSION);
                    if (version == null) {
                        throw new BadRequestException("Unable to derive version from artifact because manifest does not contain Bundle-Version attribute. " + "Please include Bundle-Version in the manifest, or explicitly specify the artifact version.");
                    }
                    return version;
                } catch (ZipException e) {
                    throw new BadRequestException("Artifact is not in zip format. Please make sure it is a jar file.");
                }
            }
        };
    } catch (IOException e) {
        LOG.error("Exception creating temp file to place artifact {} contents", artifactName, e);
        responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Server error creating temp file for artifact.");
        return null;
    }
}
Also used : ArtifactRangeNotFoundException(co.cask.cdap.common.ArtifactRangeNotFoundException) HttpResponder(co.cask.http.HttpResponder) ArtifactId(co.cask.cdap.proto.id.ArtifactId) ArtifactRange(co.cask.cdap.api.artifact.ArtifactRange) Attributes(java.util.jar.Attributes) ZipException(java.util.zip.ZipException) IOException(java.io.IOException) JsonParseException(com.google.gson.JsonParseException) JarFile(java.util.jar.JarFile) Manifest(java.util.jar.Manifest) InvalidArtifactRangeException(co.cask.cdap.api.artifact.InvalidArtifactRangeException) NamespaceNotFoundException(co.cask.cdap.common.NamespaceNotFoundException) ArtifactNotFoundException(co.cask.cdap.common.ArtifactNotFoundException) ZipException(java.util.zip.ZipException) ArtifactAlreadyExistsException(co.cask.cdap.common.ArtifactAlreadyExistsException) InvocationTargetException(java.lang.reflect.InvocationTargetException) BadRequestException(co.cask.cdap.common.BadRequestException) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) JsonParseException(com.google.gson.JsonParseException) PluginNotExistsException(co.cask.cdap.internal.app.runtime.plugin.PluginNotExistsException) ArtifactRangeNotFoundException(co.cask.cdap.common.ArtifactRangeNotFoundException) WriteConflictException(co.cask.cdap.internal.app.runtime.artifact.WriteConflictException) JsonSyntaxException(com.google.gson.JsonSyntaxException) IOException(java.io.IOException) NotFoundException(co.cask.cdap.common.NotFoundException) ArtifactAlreadyExistsException(co.cask.cdap.common.ArtifactAlreadyExistsException) AbstractBodyConsumer(co.cask.cdap.common.http.AbstractBodyConsumer) WriteConflictException(co.cask.cdap.internal.app.runtime.artifact.WriteConflictException) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) BadRequestException(co.cask.cdap.common.BadRequestException) NamespaceId(co.cask.cdap.proto.id.NamespaceId) PluginClass(co.cask.cdap.api.plugin.PluginClass) JarFile(java.util.jar.JarFile) File(java.io.File) Path(javax.ws.rs.Path) AuditPolicy(co.cask.cdap.common.security.AuditPolicy) POST(javax.ws.rs.POST)

Example 47 with UnauthorizedException

use of co.cask.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.

the class DefaultNamespaceAdmin method get.

/**
 * Gets details of a namespace
 *
 * @param namespaceId the {@link Id.Namespace} of the requested namespace
 * @return the {@link NamespaceMeta} of the requested namespace
 * @throws NamespaceNotFoundException if the requested namespace is not found
 * @throws UnauthorizedException if the namespace is not authorized to the logged-user
 */
@Override
public NamespaceMeta get(NamespaceId namespaceId) throws Exception {
    Principal principal = authenticationContext.getPrincipal();
    boolean isAuthorzied = true;
    // See: CDAP-7387
    if (masterShortUserName == null || !masterShortUserName.equals(principal.getName())) {
        try {
            AuthorizationUtil.ensureAccess(namespaceId, authorizationEnforcer, principal);
        } catch (UnauthorizedException e) {
            isAuthorzied = false;
        }
    }
    NamespaceMeta namespaceMeta = null;
    try {
        namespaceMeta = namespaceMetaCache.get(namespaceId);
    } catch (Exception e) {
        if (isAuthorzied) {
            Throwable cause = e.getCause();
            if (cause instanceof NamespaceNotFoundException || cause instanceof IOException || cause instanceof UnauthorizedException) {
                throw (Exception) cause;
            }
            throw e;
        }
    }
    // If the requesting user is same as namespace owner, we do not care about if the user is authorized or not
    if (namespaceMeta != null && principal.getName().equals(namespaceMeta.getConfig().getPrincipal())) {
        return namespaceMeta;
    }
    if (!isAuthorzied) {
        throw new UnauthorizedException(String.format("Namespace %s is not visible to principal %s since the principal does not have any " + "privilege on this namespace or any entity in this namespace.", namespaceId, principal));
    }
    return namespaceMeta;
}
Also used : NamespaceMeta(co.cask.cdap.proto.NamespaceMeta) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) IOException(java.io.IOException) Principal(co.cask.cdap.proto.security.Principal) NamespaceCannotBeCreatedException(co.cask.cdap.common.NamespaceCannotBeCreatedException) NamespaceNotFoundException(co.cask.cdap.common.NamespaceNotFoundException) BadRequestException(co.cask.cdap.common.BadRequestException) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) NamespaceCannotBeDeletedException(co.cask.cdap.common.NamespaceCannotBeDeletedException) DatasetManagementException(co.cask.cdap.api.dataset.DatasetManagementException) IOException(java.io.IOException) NamespaceAlreadyExistsException(co.cask.cdap.common.NamespaceAlreadyExistsException) NamespaceNotFoundException(co.cask.cdap.common.NamespaceNotFoundException)

Example 48 with UnauthorizedException

use of co.cask.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.

the class FlowletProcessDriver method handleProcessEntry.

/**
 * Invokes to perform dequeue and optionally invoke the user process input / tick method if dequeue gave a non
 * empty result.
 *
 * @param entry Contains information about the process method and queue.
 * @param processQueue The queue for queuing up all process input methods in a flowlet instance.
 * @param <T> Type of input of the process method accepted.
 *
 * @return {@code true} if the entry is handled completely (regardless of process result), {@code false} otherwise.
 */
private <T> boolean handleProcessEntry(FlowletProcessEntry<T> entry, PriorityQueue<FlowletProcessEntry<?>> processQueue) {
    if (!entry.shouldProcess()) {
        return false;
    }
    ProcessMethod<T> processMethod = entry.getProcessSpec().getProcessMethod();
    if (processMethod.needsInput()) {
        flowletContext.getProgramMetrics().increment("process.tuples.attempt.read", 1);
    }
    // Begin transaction and dequeue
    try {
        TransactionContext txContext = dataFabricFacade.createTransactionContext();
        startTx(txContext);
        try {
            InputDatum<T> input = entry.getProcessSpec().getQueueReader().dequeue(0, TimeUnit.MILLISECONDS);
            if (!input.needProcess()) {
                entry.backOff();
                // End the transaction if nothing in the queue
                txContext.finish();
                return false;
            }
            // Resetting back-off time to minimum back-off time,
            // since an entry to process was de-queued and most likely more entries will follow.
            entry.resetBackOff();
            // Call the process method and commit the transaction. The current process entry will put
            // back to queue in the postProcess method (either a retry copy or itself).
            ProcessMethod.ProcessResult<?> result = processMethod.invoke(input);
            postProcess(processMethodCallback(processQueue, entry, input), txContext, input, result);
            return true;
        } catch (Throwable t) {
            LOG.error("System failure: {}", flowletContext, t);
            try {
                txContext.abort();
            } catch (Throwable e) {
                LOG.error("Fail to abort transaction: {}", flowletContext, e);
            }
            if (Throwables.getRootCause(t) instanceof UnauthorizedException) {
                throw t;
            }
        }
    } catch (Throwable t) {
        LOG.error("Failed to start transaction.", t);
        if (Throwables.getRootCause(t) instanceof UnauthorizedException) {
            Throwables.propagate(t);
        }
    }
    return false;
}
Also used : TransactionContext(org.apache.tephra.TransactionContext) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException)

Example 49 with UnauthorizedException

use of co.cask.cdap.security.spi.authorization.UnauthorizedException in project cdap by caskdata.

the class DefaultSecureStoreServiceTest method testSecureStoreAccess.

@Test
public void testSecureStoreAccess() throws Exception {
    final SecureKeyId secureKeyId1 = NamespaceId.DEFAULT.secureKey(KEY1);
    SecurityRequestContext.setUserId(ALICE.getName());
    try {
        secureStoreManager.putSecureData(NamespaceId.DEFAULT.getNamespace(), KEY1, VALUE1, DESCRIPTION1, Collections.<String, String>emptyMap());
        Assert.fail("Alice should not be able to store a key since she does not have WRITE privileges on the namespace");
    } catch (UnauthorizedException expected) {
    // expected
    }
    // Grant ALICE admin access to the secure key
    grantAndAssertSuccess(secureKeyId1, ALICE, EnumSet.of(Action.ADMIN));
    // Write should succeed
    secureStoreManager.putSecureData(NamespaceId.DEFAULT.getNamespace(), KEY1, VALUE1, DESCRIPTION1, Collections.<String, String>emptyMap());
    // Listing should return the value just written
    Map<String, String> secureKeyListEntries = secureStore.listSecureData(NamespaceId.DEFAULT.getNamespace());
    Assert.assertEquals(1, secureKeyListEntries.size());
    Assert.assertTrue(secureKeyListEntries.containsKey(KEY1));
    Assert.assertEquals(DESCRIPTION1, secureKeyListEntries.get(KEY1));
    revokeAndAssertSuccess(secureKeyId1, ALICE, EnumSet.allOf(Action.class));
    // Should not be able to list the keys since ALICE does not have privilege on the secure key
    try {
        secureStore.listSecureData(NamespaceId.DEFAULT.getNamespace());
    } catch (UnauthorizedException e) {
    // expected
    }
    // Give BOB read access and verify that he can read the stored data
    SecurityRequestContext.setUserId(BOB.getName());
    grantAndAssertSuccess(NamespaceId.DEFAULT, BOB, EnumSet.of(Action.READ));
    grantAndAssertSuccess(secureKeyId1, BOB, EnumSet.of(Action.READ));
    Assert.assertEquals(VALUE1, new String(secureStore.getSecureData(NamespaceId.DEFAULT.getNamespace(), KEY1).get(), Charsets.UTF_8));
    secureKeyListEntries = secureStore.listSecureData(NamespaceId.DEFAULT.getNamespace());
    Assert.assertEquals(1, secureKeyListEntries.size());
    // BOB should not be able to delete the key
    try {
        secureStoreManager.deleteSecureData(NamespaceId.DEFAULT.getNamespace(), KEY1);
        Assert.fail("Bob should not be able to delete a key since he does not have ADMIN privileges on the key");
    } catch (UnauthorizedException expected) {
    // expected
    }
    // Grant Bob ADMIN access and he should be able to delete the key
    grantAndAssertSuccess(secureKeyId1, BOB, ImmutableSet.of(Action.ADMIN));
    secureStoreManager.deleteSecureData(NamespaceId.DEFAULT.getNamespace(), KEY1);
    Assert.assertEquals(0, secureStore.listSecureData(NamespaceId.DEFAULT.getNamespace()).size());
    Predicate<Privilege> secureKeyIdFilter = new Predicate<Privilege>() {

        @Override
        public boolean apply(Privilege input) {
            return input.getAuthorizable().equals(Authorizable.fromEntityId(secureKeyId1));
        }
    };
}
Also used : Action(co.cask.cdap.proto.security.Action) SecureKeyId(co.cask.cdap.proto.id.SecureKeyId) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) Privilege(co.cask.cdap.proto.security.Privilege) Predicate(com.google.common.base.Predicate) Test(org.junit.Test)

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