use of co.cask.cdap.proto.security.Principal 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.proto.security.Principal 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.proto.security.Principal 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);
}
use of co.cask.cdap.proto.security.Principal in project cdap by caskdata.
the class ArtifactRepository method addSystemArtifacts.
/**
* Scan all files in the local system artifact directory, looking for jar files and adding them as system artifacts.
* If the artifact already exists it will not be added again unless it is a snapshot version.
*
* @throws IOException if there was some IO error adding the system artifacts
*/
public void addSystemArtifacts() throws Exception {
// to add system artifacts, users should have write privileges on the system namespace
Principal principal = authenticationContext.getPrincipal();
authorizationEnforcer.enforce(NamespaceId.SYSTEM, principal, Action.WRITE);
// scan the directory for artifact .jar files and config files for those artifacts
List<SystemArtifactInfo> systemArtifacts = new ArrayList<>();
for (File systemArtifactDir : systemArtifactDirs) {
for (File jarFile : DirUtils.listFiles(systemArtifactDir, "jar")) {
// parse id from filename
Id.Artifact artifactId;
try {
artifactId = Id.Artifact.parse(Id.Namespace.SYSTEM, jarFile.getName());
} catch (IllegalArgumentException e) {
LOG.warn(String.format("Skipping system artifact '%s' because the name is invalid: ", e.getMessage()));
continue;
}
// first revoke any orphane privileges
co.cask.cdap.proto.id.ArtifactId artifact = artifactId.toEntityId();
privilegesManager.revoke(artifact);
// then grant all on the artifact
privilegesManager.grant(artifact, principal, EnumSet.allOf(Action.class));
// check for a corresponding .json config file
String artifactFileName = jarFile.getName();
String configFileName = artifactFileName.substring(0, artifactFileName.length() - ".jar".length()) + ".json";
File configFile = new File(systemArtifactDir, configFileName);
try {
// read and parse the config file if it exists. Otherwise use an empty config with the artifact filename
ArtifactConfig artifactConfig = configFile.isFile() ? configReader.read(artifactId.getNamespace(), configFile) : new ArtifactConfig();
validateParentSet(artifactId, artifactConfig.getParents());
validatePluginSet(artifactConfig.getPlugins());
systemArtifacts.add(new SystemArtifactInfo(artifactId, jarFile, artifactConfig));
} catch (InvalidArtifactException e) {
LOG.warn(String.format("Could not add system artifact '%s' because it is invalid.", artifactFileName), e);
// since adding artifact failed, revoke privileges, since they may be orphane now
privilegesManager.revoke(artifact);
}
}
}
// taking advantage of the fact that we only have 1 level of dependencies
// so we can add all the parents first, then we know its safe to add everything else
// add all parents
Set<Id.Artifact> parents = new HashSet<>();
for (SystemArtifactInfo child : systemArtifacts) {
Id.Artifact childId = child.getArtifactId();
for (SystemArtifactInfo potentialParent : systemArtifacts) {
Id.Artifact potentialParentId = potentialParent.getArtifactId();
// skip if we're looking at ourselves
if (childId.equals(potentialParentId)) {
continue;
}
if (child.getConfig().hasParent(potentialParentId)) {
parents.add(potentialParentId);
}
}
}
// add all parents first
for (SystemArtifactInfo systemArtifact : systemArtifacts) {
if (parents.contains(systemArtifact.getArtifactId())) {
addSystemArtifact(systemArtifact);
}
}
// add children next
for (SystemArtifactInfo systemArtifact : systemArtifacts) {
if (!parents.contains(systemArtifact.getArtifactId())) {
addSystemArtifact(systemArtifact);
}
}
}
use of co.cask.cdap.proto.security.Principal in project cdap by caskdata.
the class ArtifactRepository method deleteArtifact.
/**
* Delete the specified artifact. Programs that use the artifact will not be able to start.
*
* @param artifactId the artifact to delete
* @throws IOException if there was some IO error deleting the artifact
* @throws ArtifactNotFoundException if the given artifact does not exist
* @throws UnauthorizedException if the current user is not authorized to delete the artifact. To delete an artifact,
* a user needs {@link Action#ADMIN} permission on the artifact.
*/
public void deleteArtifact(Id.Artifact artifactId) throws Exception {
// for deleting artifacts, users need admin privileges on the artifact being deleted.
Principal principal = authenticationContext.getPrincipal();
authorizationEnforcer.enforce(artifactId.toEntityId(), principal, Action.ADMIN);
// delete the artifact first and then privileges. Not the other way to avoid orphan artifact
// which does not have any privilege if the artifact delete from store fails. see CDAP-6648
artifactStore.delete(artifactId);
metadataStore.removeMetadata(artifactId.toEntityId());
// revoke all privileges on the artifact
privilegesManager.revoke(artifactId.toEntityId());
}
Aggregations