use of com.netflix.spinnaker.fiat.model.resources.ResourceType in project fiat by spinnaker.
the class FiatPermissionEvaluator method permissionContains.
private boolean permissionContains(UserPermission.View permission, String resourceName, ResourceType resourceType, Authorization authorization) {
if (permission == null) {
return false;
}
if (permission.isAdmin()) {
// grant access regardless of whether an explicit permission to the resource exists
return true;
}
Function<Set<? extends Authorizable>, Boolean> containsAuth = resources -> resources.stream().anyMatch(view -> {
Set<Authorization> authorizations = Optional.ofNullable(view.getAuthorizations()).orElse(Collections.emptySet());
return view.getName().equalsIgnoreCase(resourceName) && authorizations.contains(authorization);
});
if (resourceType.equals(ResourceType.ACCOUNT)) {
boolean authorized = containsAuth.apply(permission.getAccounts());
// Todo(jonsie): Debug transitory access denied issue, remove when not necessary
if (!authorized) {
Map<String, Set<Authorization>> accounts = permission.getAccounts().stream().collect(Collectors.toMap(Account.View::getName, Account.View::getAuthorizations));
log.debug("Authorization={} denied to account={} for user permission={}, found={}", authorization.toString(), resourceName, permission.getName(), accounts.toString());
}
return authorized;
} else if (resourceType.equals(ResourceType.APPLICATION)) {
boolean applicationHasPermissions = permission.getApplications().stream().anyMatch(a -> a.getName().equalsIgnoreCase(resourceName));
if (!applicationHasPermissions && permission.isAllowAccessToUnknownApplications()) {
// allow access to any applications w/o explicit permissions
return true;
}
return permission.isLegacyFallback() || containsAuth.apply(permission.getApplications());
} else if (resourceType.equals(ResourceType.SERVICE_ACCOUNT)) {
return permission.getServiceAccounts().stream().anyMatch(view -> view.getName().equalsIgnoreCase(resourceName));
} else if (resourceType.equals(ResourceType.BUILD_SERVICE)) {
return permission.isLegacyFallback() || containsAuth.apply(permission.getBuildServices());
} else if (permission.getExtensionResources() != null && permission.getExtensionResources().containsKey(resourceType)) {
val extensionResources = permission.getExtensionResources().get(resourceType);
return permission.isLegacyFallback() || containsAuth.apply(extensionResources);
} else {
return false;
}
}
use of com.netflix.spinnaker.fiat.model.resources.ResourceType in project fiat by spinnaker.
the class RedisPermissionsRepository method getFromRedis.
private Optional<UserPermission> getFromRedis(@NonNull String id) {
try {
TimeoutContext timeoutContext = new TimeoutContext(String.format("getPermission for user: %s", id), clock, configProps.getRepository().getGetPermissionTimeout());
boolean userExists = UNRESTRICTED.equals(id) || redisRead(timeoutContext, c -> c.sismember(allUsersKey, SafeEncoder.encode(id)));
if (!userExists) {
log.debug("request for user {} not found in redis", id);
return Optional.empty();
}
UserPermission userPermission = new UserPermission().setId(id);
for (Resource r : resources) {
ResourceType resourceType = r.getResourceType();
Map<String, Resource> resourcePermissions = getUserResourceMapFromRedis(id, resourceType);
if (resourcePermissions != null && !resourcePermissions.isEmpty()) {
userPermission.addResources(resourcePermissions.values());
}
}
if (!UNRESTRICTED.equals(id)) {
userPermission.setAdmin(redisRead(timeoutContext, c -> c.sismember(adminKey, SafeEncoder.encode(id))));
userPermission.merge(getUnrestrictedUserPermission());
}
return Optional.of(userPermission);
} catch (Throwable t) {
String message = String.format("Storage exception reading %s entry.", id);
log.error(message, t);
if (t instanceof SpinnakerException) {
throw (SpinnakerException) t;
}
throw new PermissionReadException(message, t);
}
}
use of com.netflix.spinnaker.fiat.model.resources.ResourceType in project fiat by spinnaker.
the class RedisPermissionsRepository method put.
@Override
public RedisPermissionsRepository put(@NonNull UserPermission permission) {
String userId = permission.getId();
byte[] bUserId = SafeEncoder.encode(userId);
List<ResourceType> resourceTypes = resources.stream().map(Resource::getResourceType).collect(Collectors.toList());
Map<ResourceType, Map<String, Resource>> resourceTypeToRedisValue = new HashMap<>(resourceTypes.size());
permission.getAllResources().forEach(resource -> {
resourceTypeToRedisValue.computeIfAbsent(resource.getResourceType(), key -> new HashMap<>()).put(resource.getName(), resource);
});
try {
Set<Role> existingRoles = new HashSet<>(getUserRoleMapFromRedis(userId).values());
// These updates are pre-prepared to reduce work done during the multi-key pipeline
List<PutUpdateData> updateData = new ArrayList<>();
for (ResourceType rt : resourceTypes) {
Map<String, Resource> redisValue = resourceTypeToRedisValue.get(rt);
byte[] userResourceKey = userKey(userId, rt);
PutUpdateData pud = new PutUpdateData();
pud.userResourceKey = userResourceKey;
if (redisValue == null || redisValue.size() == 0) {
pud.compressedData = null;
} else {
pud.compressedData = lz4Compressor.compress(objectMapper.writeValueAsBytes(redisValue));
}
updateData.add(pud);
}
AtomicReference<Response<List<String>>> serverTime = new AtomicReference<>();
redisClientDelegate.withMultiKeyPipeline(pipeline -> {
if (permission.isAdmin()) {
pipeline.sadd(adminKey, bUserId);
} else {
pipeline.srem(adminKey, bUserId);
}
permission.getRoles().forEach(role -> pipeline.sadd(roleKey(role), bUserId));
existingRoles.stream().filter(it -> !permission.getRoles().contains(it)).forEach(role -> pipeline.srem(roleKey(role), bUserId));
for (PutUpdateData pud : updateData) {
if (pud.compressedData == null) {
pipeline.del(pud.userResourceKey);
} else {
byte[] tempKey = SafeEncoder.encode(UUID.randomUUID().toString());
pipeline.set(tempKey, pud.compressedData);
pipeline.rename(tempKey, pud.userResourceKey);
}
}
serverTime.set(pipeline.time());
pipeline.sadd(allUsersKey, bUserId);
pipeline.sync();
});
if (UNRESTRICTED.equals(userId)) {
String lastModified = serverTime.get().get().get(0);
redisClientDelegate.withCommandsClient(c -> {
log.debug("set last modified for user {} to {}", UNRESTRICTED, lastModified);
c.set(unrestrictedLastModifiedKey(), lastModified);
});
}
} catch (Exception e) {
log.error("Storage exception writing {} entry.", userId, e);
}
return this;
}
use of com.netflix.spinnaker.fiat.model.resources.ResourceType in project fiat by spinnaker.
the class FiatPermissionEvaluator method hasPermission.
public boolean hasPermission(String username, Serializable resourceName, String resourceType, Object authorization) {
if (!fiatStatus.isEnabled()) {
return true;
}
if (resourceName == null || resourceType == null || authorization == null) {
log.warn("Permission denied because at least one of the required arguments was null. resourceName={}, resourceType={}, " + "authorization={}", resourceName, resourceType, authorization);
return false;
}
ResourceType r = ResourceType.parse(resourceType);
Authorization a = null;
// Service accounts don't have read/write authorizations.
if (!r.equals(ResourceType.SERVICE_ACCOUNT)) {
a = Authorization.valueOf(authorization.toString());
}
if (a == Authorization.CREATE) {
throw new IllegalArgumentException("This method should not be called for `CREATE`. Please call the other implementation");
}
if (r.equals(ResourceType.APPLICATION) && StringUtils.isNotEmpty(resourceName.toString())) {
resourceName = resourceName.toString();
}
UserPermission.View permission = getPermission(username);
boolean hasPermission = permissionContains(permission, resourceName.toString(), r, a);
authorizationFailure.set(hasPermission ? null : new AuthorizationFailure(a, r, resourceName.toString()));
if (permission != null && permission.isLegacyFallback() && hasPermission) {
// log any access that was granted as part of a legacy fallback.
if (a == Authorization.READ) {
// purposely logging at 'debug' as 'READ' will be sufficiently more verbose
log.debug("Legacy fallback granted {} access (type: {}, resource: {})", a, r, resourceName);
} else {
log.warn("Legacy fallback granted {} access (type: {}, resource: {})", a, r, resourceName);
}
}
return hasPermission;
}
Aggregations