use of org.graylog.security.Capability in project graylog2-server by Graylog2.
the class RolesToGrantsMigration method migrateRoleToGrant.
private Set<String> migrateRoleToGrant(MigratableRole migratableRole) {
final Set<String> migratedRolePermissions = new HashSet<>();
final Collection<User> allRoleUsers = userService.loadAllForRole(migratableRole.role);
migratableRole.migratableEntities.forEach((entityID, permissions) -> {
final GrantsMetaMigration.GRNTypeCapability grnTypeCapability = MIGRATION_MAP.get(permissions);
// Permissions are mappable to a grant
if (grnTypeCapability != null) {
final Capability capability = grnTypeCapability.capability;
final GRNType grnType = grnTypeCapability.grnType;
allRoleUsers.forEach(user -> {
dbGrantService.ensure(grnRegistry.ofUser(user), capability, grnType.toGRN(entityID), rootUsername);
LOG.info("Migrating entity <{}> permissions <{}> to <{}> grant for user <{}>", grnType.toGRN(entityID), permissions, capability, user.getName());
});
migratedRolePermissions.addAll(permissions.stream().map(p -> p + ":" + entityID).collect(Collectors.toSet()));
} else {
LOG.info("Skipping non-migratable entity <{}>. Permissions <{}> cannot be converted to a grant capability", entityID, permissions);
}
});
return migratedRolePermissions;
}
use of org.graylog.security.Capability in project graylog2-server by Graylog2.
the class EntitySharesService method updateEntityShares.
/**
* Share / unshare an entity with one or more grantees.
* The grants in the request are created or, if they already exist, updated.
*
* @param ownedEntity the target entity for the updated grants
* @param request the request containing grantees and their capabilities
* @param sharingUser the user executing the request
*/
public EntityShareResponse updateEntityShares(GRN ownedEntity, EntityShareRequest request, User sharingUser) {
requireNonNull(ownedEntity, "ownedEntity cannot be null");
requireNonNull(request, "request cannot be null");
requireNonNull(sharingUser, "sharingUser cannot be null");
final ImmutableMap<GRN, Capability> selectedGranteeCapabilities = request.selectedGranteeCapabilities().orElse(ImmutableMap.of());
final String userName = sharingUser.getName();
final GRN sharingUserGRN = grnRegistry.ofUser(sharingUser);
final Set<Grantee> availableGrantees = granteeService.getAvailableGrantees(sharingUser);
final Set<GRN> availableGranteeGRNs = availableGrantees.stream().map(Grantee::grn).collect(Collectors.toSet());
final List<GrantDTO> existingGrants = grantService.getForTargetExcludingGrantee(ownedEntity, sharingUserGRN);
existingGrants.removeIf(grant -> !availableGranteeGRNs.contains(grant.grantee()));
final EntityShareResponse.Builder responseBuilder = EntityShareResponse.builder().entity(ownedEntity.toString()).sharingUser(sharingUserGRN).availableGrantees(availableGrantees).availableCapabilities(getAvailableCapabilities()).missingPermissionsOnDependencies(checkMissingPermissionsOnDependencies(ownedEntity, sharingUserGRN, ImmutableSet.of(), request));
final EntitySharesUpdateEvent.Builder updateEventBuilder = EntitySharesUpdateEvent.builder().user(sharingUser).entity(ownedEntity);
// Abort if validation fails, but try to return a complete EntityShareResponse
final ValidationResult validationResult = validateRequest(ownedEntity, request, sharingUser, availableGranteeGRNs);
if (validationResult.failed()) {
final ImmutableSet<ActiveShare> activeShares = getActiveShares(ownedEntity, sharingUser, availableGranteeGRNs);
return responseBuilder.activeShares(activeShares).selectedGranteeCapabilities(getSelectedGranteeCapabilities(activeShares, request)).validationResult(validationResult).build();
}
// Update capabilities of existing grants (for a grantee)
existingGrants.stream().filter(grantDTO -> request.grantees().contains(grantDTO.grantee())).forEach((g -> {
final Capability newCapability = selectedGranteeCapabilities.get(g.grantee());
if (!g.capability().equals(newCapability)) {
grantService.save(g.toBuilder().capability(newCapability).updatedBy(userName).updatedAt(ZonedDateTime.now(ZoneOffset.UTC)).build());
updateEventBuilder.addUpdates(g.grantee(), newCapability, g.capability());
}
}));
// Create newly added grants
// TODO Create multiple entries with one db query
selectedGranteeCapabilities.forEach((grantee, capability) -> {
if (existingGrants.stream().noneMatch(eg -> eg.grantee().equals(grantee))) {
grantService.create(GrantDTO.builder().grantee(grantee).capability(capability).target(ownedEntity).build(), sharingUser);
updateEventBuilder.addCreates(grantee, capability);
}
});
// remove grants that are not present anymore
// TODO delete multiple entries with one db query
existingGrants.forEach((g) -> {
if (!selectedGranteeCapabilities.containsKey(g.grantee())) {
grantService.delete(g.id());
updateEventBuilder.addDeletes(g.grantee(), g.capability());
}
});
postUpdateEvent(updateEventBuilder.build());
final ImmutableSet<ActiveShare> activeShares = getActiveShares(ownedEntity, sharingUser, availableGranteeGRNs);
return responseBuilder.activeShares(activeShares).selectedGranteeCapabilities(getSelectedGranteeCapabilities(activeShares, request)).build();
}
use of org.graylog.security.Capability in project graylog2-server by Graylog2.
the class EntitySharesService method validateRequest.
private ValidationResult validateRequest(GRN ownedEntity, EntityShareRequest request, User sharingUser, Set<GRN> availableGranteeGRNs) {
final ValidationResult validationResult = new ValidationResult();
final List<GrantDTO> allEntityGrants = grantService.getForTarget(ownedEntity);
final List<GrantDTO> existingGrants = grantService.getForTargetExcludingGrantee(ownedEntity, grnRegistry.ofUser(sharingUser));
// The initial request doesn't submit a grantee selection. Just return.
if (!request.selectedGranteeCapabilities().isPresent()) {
return validationResult;
}
final ImmutableMap<GRN, Capability> selectedGranteeCapabilities = request.selectedGranteeCapabilities().get();
// If there is still an owner in the selection, everything is fine
if (selectedGranteeCapabilities.containsValue(Capability.OWN)) {
return validationResult;
}
// If this entity is already ownerless, things can't get any worse. Let this request pass.
if (allEntityGrants.stream().noneMatch(g -> g.capability().equals(Capability.OWN))) {
return validationResult;
}
// Iterate over all existing owner grants and find modifications
ArrayList<GRN> removedOwners = new ArrayList<>();
existingGrants.stream().filter(g -> g.capability().equals(Capability.OWN)).forEach((g) -> {
// owner got removed
if (!selectedGranteeCapabilities.containsKey(g.grantee())) {
// Ignore owners that were invisible to the requesting user
if (availableGranteeGRNs.contains(g.grantee())) {
removedOwners.add(g.grantee());
}
// owner capability got changed
} else if (!selectedGranteeCapabilities.get(g.grantee()).equals(Capability.OWN)) {
removedOwners.add(g.grantee());
}
});
// If all removedOwners are applied, is there still at least one owner left?
if (allEntityGrants.stream().filter(g -> g.capability().equals(Capability.OWN)).map(GrantDTO::grantee).anyMatch(grantee -> !removedOwners.contains(grantee))) {
return validationResult;
}
validationResult.addError(EntityShareRequest.SELECTED_GRANTEE_CAPABILITIES, String.format(Locale.US, "Removing the following owners <%s> will leave the entity ownerless.", removedOwners));
// Also return the grantees as list to be used by the frontend
validationResult.addContext(EntityShareRequest.SELECTED_GRANTEE_CAPABILITIES, removedOwners.stream().map(Objects::toString).collect(Collectors.toSet()));
return validationResult;
}
use of org.graylog.security.Capability in project graylog2-server by Graylog2.
the class UserPermissionsToGrantsMigration method migrateUserPermissions.
private void migrateUserPermissions(User user, Map<String, Set<String>> migratableEntities) {
migratableEntities.forEach((entityID, permissions) -> {
final GRNTypeCapability grnTypeCapability = GrantsMetaMigration.MIGRATION_MAP.get(permissions);
// Permissions are mappable to a grant
if (grnTypeCapability != null) {
final Capability capability = grnTypeCapability.capability;
GRN targetGRN;
if (permissions.stream().anyMatch(p -> p.contains(VIEW_READ))) {
// For views we need to load the database object to be able to determine if it's a
// search or a dashboard.
targetGRN = getViewGRNType(entityID).map(grnType -> grnType.toGRN(entityID)).orElse(null);
} else {
targetGRN = requireNonNull(grnTypeCapability.grnType, "grnType cannot be null - this is a bug").toGRN(entityID);
}
if (targetGRN != null) {
dbGrantService.ensure(grnRegistry.ofUser(user), capability, targetGRN, rootUsername);
}
final List<String> updatedPermissions = user.getPermissions();
updatedPermissions.removeAll(permissions.stream().map(p -> p + ":" + entityID).collect(Collectors.toSet()));
user.setPermissions(updatedPermissions);
try {
userService.save(user);
} catch (ValidationException e) {
LOG.error("Failed to update permssions on user <{}>", user.getName(), e);
}
LOG.info("Migrating entity <{}> permissions <{}> to <{}> grant for user <{}>", targetGRN, permissions, capability, user.getName());
} else {
LOG.info("Skipping non-migratable entity <{}>. Permissions <{}> cannot be converted to a grant capability", entityID, permissions);
}
});
}
Aggregations