Search in sources :

Example 21 with Principal

use of co.cask.cdap.proto.security.Principal in project cdap by caskdata.

the class AuthorizationDatasetTypeService method deleteAll.

@Override
public void deleteAll(NamespaceId namespaceId) throws Exception {
    Principal principal = authenticationContext.getPrincipal();
    for (DatasetModuleMeta meta : delegate.listModules(namespaceId)) {
        DatasetModuleId datasetModuleId = namespaceId.datasetModule(meta.getName());
        authorizationEnforcer.enforce(datasetModuleId, principal, Action.ADMIN);
    }
    delegate.deleteAll(namespaceId);
}
Also used : DatasetModuleId(co.cask.cdap.proto.id.DatasetModuleId) DatasetModuleMeta(co.cask.cdap.proto.DatasetModuleMeta) Principal(co.cask.cdap.proto.security.Principal)

Example 22 with Principal

use of co.cask.cdap.proto.security.Principal in project cdap by caskdata.

the class DatasetInstanceService method create.

/**
 * Creates a dataset instance.
 *
 * @param namespaceId the namespace to create the dataset instance in
 * @param name the name of the new dataset instance
 * @param props the properties for the new dataset instance
 * @throws NamespaceNotFoundException if the specified namespace was not found
 * @throws DatasetAlreadyExistsException if a dataset with the same name already exists
 * @throws DatasetTypeNotFoundException if the dataset type was not found
 * @throws UnauthorizedException if perimeter security and authorization are enabled, and the current user does not
 *  have {@link Action#WRITE} privilege on the #instance's namespace
 */
void create(String namespaceId, String name, DatasetInstanceConfiguration props) throws Exception {
    NamespaceId namespace = ConversionHelpers.toNamespaceId(namespaceId);
    DatasetId datasetId = ConversionHelpers.toDatasetInstanceId(namespaceId, name);
    Principal requestingUser = authenticationContext.getPrincipal();
    String ownerPrincipal = props.getOwnerPrincipal();
    // need to enforce on the principal id if impersonation is involved
    KerberosPrincipalId effectiveOwner = SecurityUtil.getEffectiveOwner(ownerAdmin, namespace, ownerPrincipal);
    if (!DatasetsUtil.isSystemDatasetInUserNamespace(datasetId)) {
        if (effectiveOwner != null) {
            authorizationEnforcer.enforce(effectiveOwner, requestingUser, Action.ADMIN);
        }
        authorizationEnforcer.enforce(datasetId, requestingUser, Action.ADMIN);
    }
    ensureNamespaceExists(namespace);
    DatasetSpecification existing = instanceManager.get(datasetId);
    if (existing != null) {
        throw new DatasetAlreadyExistsException(datasetId);
    }
    // for creation, we need enforcement for dataset type for user dataset, but bypass for system datasets
    DatasetTypeMeta typeMeta = getTypeInfo(namespace, props.getTypeName(), DatasetsUtil.isSystemDatasetInUserNamespace(datasetId));
    if (typeMeta == null) {
        // Type not found in the instance's namespace and the system namespace. Bail out.
        throw new DatasetTypeNotFoundException(ConversionHelpers.toDatasetTypeId(namespace, props.getTypeName()));
    }
    LOG.info("Creating dataset {}.{}, type name: {}, properties: {}", namespaceId, name, props.getTypeName(), props.getProperties());
    // exists or not
    if (ownerPrincipal != null) {
        KerberosPrincipalId owner = new KerberosPrincipalId(ownerPrincipal);
        ownerAdmin.add(datasetId, owner);
    }
    try {
        DatasetSpecification spec = opExecutorClient.create(datasetId, typeMeta, DatasetProperties.builder().addAll(props.getProperties()).setDescription(props.getDescription()).build());
        instanceManager.add(namespace, spec);
        metaCache.invalidate(datasetId);
        publishAudit(datasetId, AuditType.CREATE);
        // Enable explore
        enableExplore(datasetId, spec, props);
    } catch (Exception e) {
        // there was a problem in creating the dataset instance so delete the owner if it got added earlier
        // safe to call for entities which does not have an owner too
        ownerAdmin.delete(datasetId);
        throw e;
    }
}
Also used : DatasetSpecification(co.cask.cdap.api.dataset.DatasetSpecification) DatasetTypeMeta(co.cask.cdap.proto.DatasetTypeMeta) DatasetAlreadyExistsException(co.cask.cdap.common.DatasetAlreadyExistsException) NamespaceId(co.cask.cdap.proto.id.NamespaceId) DatasetTypeNotFoundException(co.cask.cdap.common.DatasetTypeNotFoundException) KerberosPrincipalId(co.cask.cdap.proto.id.KerberosPrincipalId) Principal(co.cask.cdap.proto.security.Principal) NamespaceNotFoundException(co.cask.cdap.common.NamespaceNotFoundException) DatasetNotFoundException(co.cask.cdap.common.DatasetNotFoundException) DatasetTypeNotFoundException(co.cask.cdap.common.DatasetTypeNotFoundException) UnauthorizedException(co.cask.cdap.security.spi.authorization.UnauthorizedException) HandlerException(co.cask.cdap.common.HandlerException) DatasetAlreadyExistsException(co.cask.cdap.common.DatasetAlreadyExistsException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) NotFoundException(co.cask.cdap.common.NotFoundException) DatasetId(co.cask.cdap.proto.id.DatasetId)

Example 23 with Principal

use of co.cask.cdap.proto.security.Principal in project cdap by caskdata.

the class DatasetInstanceService method dropAll.

/**
 * Drops all datasets in the given namespace. If authorization is turned on, only datasets that the current
 * principal that has {@link Action#ADMIN} privilege will be deleted
 *
 * @param namespaceId namespace to operate on
 * @throws Exception if it fails to delete dataset
 */
void dropAll(NamespaceId namespaceId) throws Exception {
    ensureNamespaceExists(namespaceId);
    Principal principal = authenticationContext.getPrincipal();
    Map<DatasetId, DatasetSpecification> datasets = new HashMap<>();
    for (DatasetSpecification spec : instanceManager.getAll(namespaceId)) {
        DatasetId datasetId = namespaceId.dataset(spec.getName());
        if (!DatasetsUtil.isSystemDatasetInUserNamespace(datasetId)) {
            authorizationEnforcer.enforce(datasetId, principal, Action.ADMIN);
        }
        datasets.put(datasetId, spec);
    }
    // auth check passed, we can start deleting the datasets
    for (DatasetId datasetId : datasets.keySet()) {
        dropDataset(datasetId, datasets.get(datasetId));
    }
}
Also used : HashMap(java.util.HashMap) DatasetSpecification(co.cask.cdap.api.dataset.DatasetSpecification) Principal(co.cask.cdap.proto.security.Principal) DatasetId(co.cask.cdap.proto.id.DatasetId)

Example 24 with Principal

use of co.cask.cdap.proto.security.Principal in project cdap by caskdata.

the class DatasetInstanceService method executeAdmin.

/**
 * Executes an admin operation on a dataset instance.
 *
 * @param instance the instance to execute the admin operation on
 * @param method the type of admin operation to execute
 * @return the {@link DatasetAdminOpResponse} from the HTTP handler
 * @throws NamespaceNotFoundException if the requested namespace was not found
 * @throws IOException if there was a problem in checking if the namespace exists over HTTP
 * @throws UnauthorizedException if perimeter security and authorization are enabled, and the current user does not
 *  have -
 *  <ol>
 *    <li>{@link Action#ADMIN} privileges on the #instance (for "drop" or "truncate") </li>
 *    <li>any privileges on the #instance (for "exists")</li>
 *  <ol>
 */
DatasetAdminOpResponse executeAdmin(DatasetId instance, String method) throws Exception {
    ensureNamespaceExists(instance.getParent());
    Object result = null;
    // NOTE: one cannot directly call create and drop, instead this should be called thru
    // POST/DELETE @ /data/datasets/{instance-id}. Because we must create/drop metadata for these at same time
    Principal principal = authenticationContext.getPrincipal();
    switch(method) {
        case "exists":
            // ensure the user has some privilege on the dataset instance if it is not system dataset
            if (!DatasetsUtil.isSystemDatasetInUserNamespace(instance)) {
                AuthorizationUtil.ensureAccess(instance, authorizationEnforcer, principal);
            }
            result = opExecutorClient.exists(instance);
            break;
        case "truncate":
            if (!DatasetsUtil.isSystemDatasetInUserNamespace(instance)) {
                authorizationEnforcer.enforce(instance, principal, Action.ADMIN);
            }
            if (instanceManager.get(instance) == null) {
                throw new DatasetNotFoundException(instance);
            }
            opExecutorClient.truncate(instance);
            publishAudit(instance, AuditType.TRUNCATE);
            break;
        case "upgrade":
            if (!DatasetsUtil.isSystemDatasetInUserNamespace(instance)) {
                authorizationEnforcer.enforce(instance, principal, Action.ADMIN);
            }
            if (instanceManager.get(instance) == null) {
                throw new DatasetNotFoundException(instance);
            }
            opExecutorClient.upgrade(instance);
            publishAudit(instance, AuditType.UPDATE);
            break;
        default:
            throw new HandlerException(HttpResponseStatus.NOT_FOUND, "Invalid admin operation: " + method);
    }
    return new DatasetAdminOpResponse(result, null);
}
Also used : HandlerException(co.cask.cdap.common.HandlerException) DatasetNotFoundException(co.cask.cdap.common.DatasetNotFoundException) DatasetAdminOpResponse(co.cask.cdap.data2.datafabric.dataset.service.executor.DatasetAdminOpResponse) Principal(co.cask.cdap.proto.security.Principal)

Example 25 with Principal

use of co.cask.cdap.proto.security.Principal in project cdap by caskdata.

the class DefaultNamespaceAdmin method create.

/**
 * Creates a new namespace
 *
 * @param metadata the {@link NamespaceMeta} for the new namespace to be created
 * @throws NamespaceAlreadyExistsException if the specified namespace already exists
 */
@Override
public synchronized void create(final NamespaceMeta metadata) throws Exception {
    // TODO: CDAP-1427 - This should be transactional, but we don't support transactions on files yet
    Preconditions.checkArgument(metadata != null, "Namespace metadata should not be null.");
    NamespaceId namespace = metadata.getNamespaceId();
    if (exists(namespace)) {
        throw new NamespaceAlreadyExistsException(namespace);
    }
    // need to enforce on the principal id if impersonation is involved
    String ownerPrincipal = metadata.getConfig().getPrincipal();
    Principal requestingUser = authenticationContext.getPrincipal();
    if (ownerPrincipal != null) {
        authorizationEnforcer.enforce(new KerberosPrincipalId(ownerPrincipal), requestingUser, Action.ADMIN);
    }
    authorizationEnforcer.enforce(namespace, requestingUser, Action.ADMIN);
    // If this namespace has custom mapping then validate the given custom mapping
    if (hasCustomMapping(metadata)) {
        validateCustomMapping(metadata);
    }
    // check that the user has configured either both of none of the following configuration: principal and keytab URI
    boolean hasValidKerberosConf = false;
    if (metadata.getConfig() != null) {
        String configuredPrincipal = metadata.getConfig().getPrincipal();
        String configuredKeytabURI = metadata.getConfig().getKeytabURI();
        if ((!Strings.isNullOrEmpty(configuredPrincipal) && Strings.isNullOrEmpty(configuredKeytabURI)) || (Strings.isNullOrEmpty(configuredPrincipal) && !Strings.isNullOrEmpty(configuredKeytabURI))) {
            throw new BadRequestException(String.format("Either neither or both of the following two configurations must be configured. " + "Configured principal: %s, Configured keytabURI: %s", configuredPrincipal, configuredKeytabURI));
        }
        hasValidKerberosConf = true;
    }
    // check that if explore as principal is explicitly set to false then user has kerberos configuration
    if (!metadata.getConfig().isExploreAsPrincipal() && !hasValidKerberosConf) {
        throw new BadRequestException(String.format("No kerberos principal or keytab-uri was provided while '%s' was set to true.", NamespaceConfig.EXPLORE_AS_PRINCIPAL));
    }
    // store the meta first in the namespace store because namespacedLocationFactory needs to look up location
    // mapping from namespace config
    nsStore.create(metadata);
    try {
        UserGroupInformation ugi;
        if (NamespaceId.DEFAULT.equals(namespace)) {
            ugi = UserGroupInformation.getCurrentUser();
        } else {
            ugi = impersonator.getUGI(namespace);
        }
        ImpersonationUtils.doAs(ugi, new Callable<Void>() {

            @Override
            public Void call() throws Exception {
                storageProviderNamespaceAdmin.get().create(metadata);
                return null;
            }
        });
    } catch (Throwable t) {
        // failed to create namespace in underlying storage so delete the namespace meta stored in the store earlier
        deleteNamespaceMeta(metadata.getNamespaceId());
        throw new NamespaceCannotBeCreatedException(namespace, t);
    }
    LOG.info("Namespace {} created with meta {}", metadata.getNamespaceId(), metadata);
}
Also used : NamespaceCannotBeCreatedException(co.cask.cdap.common.NamespaceCannotBeCreatedException) 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) BadRequestException(co.cask.cdap.common.BadRequestException) NamespaceId(co.cask.cdap.proto.id.NamespaceId) NamespaceAlreadyExistsException(co.cask.cdap.common.NamespaceAlreadyExistsException) KerberosPrincipalId(co.cask.cdap.proto.id.KerberosPrincipalId) Principal(co.cask.cdap.proto.security.Principal) UserGroupInformation(org.apache.hadoop.security.UserGroupInformation)

Aggregations

Principal (co.cask.cdap.proto.security.Principal)76 EntityId (co.cask.cdap.proto.id.EntityId)22 UnauthorizedException (co.cask.cdap.security.spi.authorization.UnauthorizedException)16 Action (co.cask.cdap.proto.security.Action)13 NamespaceId (co.cask.cdap.proto.id.NamespaceId)12 IOException (java.io.IOException)12 Path (javax.ws.rs.Path)11 Test (org.junit.Test)9 Role (co.cask.cdap.proto.security.Role)8 POST (javax.ws.rs.POST)7 MethodArgument (co.cask.cdap.common.internal.remote.MethodArgument)6 DatasetModuleMeta (co.cask.cdap.proto.DatasetModuleMeta)5 KerberosPrincipalId (co.cask.cdap.proto.id.KerberosPrincipalId)5 Privilege (co.cask.cdap.proto.security.Privilege)5 DatasetManagementException (co.cask.cdap.api.dataset.DatasetManagementException)4 NamespaceNotFoundException (co.cask.cdap.common.NamespaceNotFoundException)4 SecureKeyId (co.cask.cdap.proto.id.SecureKeyId)4 DatasetSpecification (co.cask.cdap.api.dataset.DatasetSpecification)3 DatasetModuleConflictException (co.cask.cdap.data2.datafabric.dataset.type.DatasetModuleConflictException)3 DatasetTypeMeta (co.cask.cdap.proto.DatasetTypeMeta)3