use of co.cask.cdap.common.security.AuthEnforce 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
@AuthEnforce(entities = "instanceId", enforceOn = InstanceId.class, actions = Action.ADMIN)
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);
}
// 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));
}
// Namespace can be created. Grant all the permissions to the user.
Principal principal = authenticationContext.getPrincipal();
privilegesManager.grant(namespace, principal, EnumSet.allOf(Action.class));
// Also grant the user who will execute programs in this namespace all privileges on the namespace
String executionUserName;
if (SecurityUtil.isKerberosEnabled(cConf) && !NamespaceId.SYSTEM.equals(namespace)) {
String namespacePrincipal = metadata.getConfig().getPrincipal();
if (Strings.isNullOrEmpty(namespacePrincipal)) {
executionUserName = new KerberosName(SecurityUtil.getMasterPrincipal(cConf)).getShortName();
} else {
executionUserName = new KerberosName(namespacePrincipal).getShortName();
}
} else {
executionUserName = UserGroupInformation.getCurrentUser().getShortUserName();
}
Principal executionUser = new Principal(executionUserName, Principal.PrincipalType.USER);
privilegesManager.grant(namespace, executionUser, EnumSet.allOf(Action.class));
// 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());
privilegesManager.revoke(namespace);
throw new NamespaceCannotBeCreatedException(namespace, t);
}
LOG.info("Namespace {} created with meta {}", metadata.getNamespaceId(), metadata);
}
use of co.cask.cdap.common.security.AuthEnforce in project cdap by caskdata.
the class DefaultNamespaceAdmin method delete.
/**
* Deletes the specified namespace
*
* @param namespaceId the {@link Id.Namespace} of the specified namespace
* @throws NamespaceCannotBeDeletedException if the specified namespace cannot be deleted
* @throws NamespaceNotFoundException if the specified namespace does not exist
*/
@Override
@AuthEnforce(entities = "namespaceId", enforceOn = NamespaceId.class, actions = Action.ADMIN)
public synchronized void delete(@Name("namespaceId") final NamespaceId namespaceId) throws Exception {
// TODO: CDAP-870, CDAP-1427: Delete should be in a single transaction.
NamespaceMeta namespaceMeta = get(namespaceId);
if (checkProgramsRunning(namespaceId)) {
throw new NamespaceCannotBeDeletedException(namespaceId, String.format("Some programs are currently running in namespace " + "'%s', please stop them before deleting namespace", namespaceId));
}
LOG.info("Deleting namespace '{}'.", namespaceId);
try {
resourceDeleter.get().deleteResources(namespaceMeta);
// namespace in the storage provider (Hive, HBase, etc), since we re-use their default namespace.
if (!NamespaceId.DEFAULT.equals(namespaceId)) {
// Finally delete namespace from MDS and remove from cache
deleteNamespaceMeta(namespaceId);
// revoke privileges as the final step. This is done in the end, because if it is done before actual deletion,
// and deletion fails, we may have a valid (or invalid) namespace in the system, that no one has privileges on,
// so no one can clean up. This may result in orphaned privileges, which will be cleaned up by the create API
// if the same namespace is successfully re-created.
privilegesManager.revoke(namespaceId);
LOG.info("Namespace '{}' deleted", namespaceId);
} else {
LOG.info("Keeping the '{}' namespace after removing all data.", NamespaceId.DEFAULT);
}
} catch (Exception e) {
LOG.warn("Error while deleting namespace {}", namespaceId, e);
throw new NamespaceCannotBeDeletedException(namespaceId, e);
}
}
Aggregations