@Transactional public AccessKey authenticate(@NotNull String key) { Optional<AccessKey> accessKeyOpt = genericDAO .createNamedQuery(AccessKey.class, "AccessKey.getByKey", Optional.of(CacheConfig.get())) .setParameter("someKey", key) .getResultList() .stream() .findFirst(); if (!accessKeyOpt.isPresent()) { return null; } AccessKey accessKey = accessKeyOpt.get(); final Long expirationPeriod = configurationService.getLong(Constants.SESSION_TIMEOUT, Constants.DEFAULT_SESSION_TIMEOUT); if (accessKey.getExpirationDate() != null) { final Long expiresIn = accessKey.getExpirationDate().getTime() - timestampService.getTimestamp().getTime(); if (AccessKeyType.SESSION == accessKey.getType() && expiresIn > 0 && expiresIn < expirationPeriod / 2) { em.refresh(accessKey, LockModeType.PESSIMISTIC_WRITE); accessKey.setExpirationDate( new Date(timestampService.getTimestamp().getTime() + expirationPeriod)); return genericDAO.merge(accessKey); } } return accessKey; }
@AroundInvoke public Object checkPermissions(InvocationContext context) throws Exception { try { logger.trace(Thread.currentThread().getName()); HivePrincipal principal = ThreadLocalVariablesKeeper.getPrincipal(); AccessKey key = principal.getKey(); if (key == null) { return context.proceed(); } if (key.getUser() == null || !key.getUser().getStatus().equals(UserStatus.ACTIVE)) { throw new HiveException(UNAUTHORIZED.getReasonPhrase(), UNAUTHORIZED.getStatusCode()); } Timestamp expirationDate = key.getExpirationDate(); if (expirationDate != null && expirationDate.before(new Timestamp(System.currentTimeMillis()))) { throw new HiveException(UNAUTHORIZED.getReasonPhrase(), UNAUTHORIZED.getStatusCode()); } Method method = context.getMethod(); AllowedKeyAction allowedActionAnnotation = method.getAnnotation(AllowedKeyAction.class); List<AllowedKeyAction.Action> actions = Arrays.asList(allowedActionAnnotation.action()); boolean isAllowed = CheckPermissionsHelper.checkAllPermissions(key, actions); if (!isAllowed) { throw new HiveException(UNAUTHORIZED.getReasonPhrase(), UNAUTHORIZED.getStatusCode()); } return context.proceed(); } finally { ThreadLocalVariablesKeeper.clean(); } }
private void deleteAccessKeyPermissions(AccessKey key) { logger.debug("Deleting all permission of access key {}", key.getId()); int deleted = genericDAO .createNamedQuery( "AccessKeyPermission.deleteByAccessKey", Optional.<CacheConfig>empty()) .setParameter("accessKey", key) .executeUpdate(); logger.info("Deleted {} permissions by access key {}", deleted, key.getId()); }
@Transactional(propagation = Propagation.SUPPORTS) public boolean hasAccessToDevice(AccessKey accessKey, String deviceGuid) { Set<AccessKeyPermission> permissions = accessKey.getPermissions(); Set<String> allowedDevices = new HashSet<>(); Set<Long> allowedNetworks = new HashSet<>(); User accessKeyUser = userService.findUserWithNetworks(accessKey.getUser().getId()); Set<AccessKeyPermission> toRemove = new HashSet<>(); Device device = genericDAO .createNamedQuery(Device.class, "Device.findByUUID", of(CacheConfig.refresh())) .setParameter("guid", deviceGuid) .getSingleResult(); for (AccessKeyPermission currentPermission : permissions) { if (currentPermission.getDeviceGuidsAsSet() == null) { allowedDevices.add(null); } else { if (!currentPermission.getDeviceGuidsAsSet().contains(deviceGuid)) { toRemove.add(currentPermission); } else { allowedDevices.addAll(currentPermission.getDeviceGuidsAsSet()); } } if (currentPermission.getNetworkIdsAsSet() == null) { allowedNetworks.add(null); } else { if (device.getNetwork() != null) { if (!currentPermission.getNetworkIdsAsSet().contains(device.getNetwork().getId())) { toRemove.add(currentPermission); } else { allowedNetworks.addAll(currentPermission.getNetworkIdsAsSet()); } } } } permissions.removeAll(toRemove); boolean hasAccess; hasAccess = allowedDevices.contains(null) ? userService.hasAccessToDevice(accessKeyUser, device.getGuid()) : allowedDevices.contains(device.getGuid()) && userService.hasAccessToDevice(accessKeyUser, device.getGuid()); hasAccess = hasAccess && allowedNetworks.contains(null) ? accessKeyUser.isAdmin() || accessKeyUser.getNetworks().contains(device.getNetwork()) : (accessKeyUser.isAdmin() || accessKeyUser.getNetworks().contains(device.getNetwork())) && allowedNetworks.contains(device.getNetwork().getId()); return hasAccess; }
@Transactional public AccessKey create(@NotNull User user, @NotNull AccessKey accessKey) { if (accessKey.getLabel() == null) { throw new IllegalParametersException(Messages.LABEL_IS_REQUIRED); } Optional<AccessKey> akOpt = genericDAO .createNamedQuery( AccessKey.class, "AccessKey.getByUserAndLabel", Optional.<CacheConfig>empty()) .setParameter("userId", user.getId()) .setParameter("label", accessKey.getLabel()) .getResultList() .stream() .findFirst(); if (akOpt.isPresent()) { logger.error("Access key with label {} already exists", accessKey.getLabel()); throw new ActionNotAllowedException(Messages.DUPLICATE_LABEL_FOUND); } if (accessKey.getId() != null) { logger.error("Access key id shouldn't be present in request parameters"); throw new IllegalParametersException(Messages.INVALID_REQUEST_PARAMETERS); } authenticationUtils.validateActions(accessKey); AccessKeyProcessor keyProcessor = new AccessKeyProcessor(); String key = keyProcessor.generateKey(); accessKey.setKey(key); accessKey.setUser(user); genericDAO.persist(accessKey); for (AccessKeyPermission current : accessKey.getPermissions()) { AccessKeyPermission permission = preparePermission(current); permission.setAccessKey(accessKey); genericDAO.persist(permission); } return genericDAO.find(AccessKey.class, accessKey.getId()); }
@Transactional(propagation = Propagation.REQUIRED) public AccessKey authenticate(@NotNull User user) { userService.refreshUserLoginData(user); AccessKey accessKey = authenticationUtils.prepareAccessKey(user); Set<AccessKeyPermission> permissions = new HashSet<>(); final AccessKeyPermission permission = authenticationUtils.preparePermission(user.getRole()); permissions.add(permission); accessKey.setPermissions(permissions); genericDAO.persist(accessKey); permission.setAccessKey(accessKey); genericDAO.persist(permission); return accessKey; }
@Transactional(propagation = Propagation.SUPPORTS) public boolean hasAccessToNetwork(AccessKey accessKey, Network targetNetwork) { Set<AccessKeyPermission> permissions = accessKey.getPermissions(); User user = accessKey.getUser(); boolean hasNullPermission = permissions.stream().anyMatch(perm -> perm.getNetworkIdsAsSet() == null); if (hasNullPermission) { return userService.hasAccessToNetwork(user, targetNetwork); } else { Set<Long> allowedNetworks = permissions .stream() .map(AccessKeyPermission::getNetworkIdsAsSet) .flatMap(Collection::stream) .collect(Collectors.toSet()); user = userService.findUserWithNetworks(user.getId()); return allowedNetworks.contains(targetNetwork.getId()) && (user.isAdmin() || user.getNetworks().contains(targetNetwork)); } }
@Transactional public AccessKey updateAccessKeyFromOAuthGrant(OAuthGrant grant, User user, Date now) { AccessKey existing = find(grant.getAccessKey().getId(), user.getId()); deleteAccessKeyPermissions(existing); if (grant.getAccessType().equals(AccessType.ONLINE)) { Date expirationDate = new Date(now.getTime() + 600000); // the key is valid for 10 minutes existing.setExpirationDate(expirationDate); } else { existing.setExpirationDate(null); } existing.setLabel( String.format( Messages.OAUTH_GRANT_TOKEN_LABEL, grant.getClient().getName(), System.currentTimeMillis())); Set<AccessKeyPermission> permissions = new HashSet<>(); AccessKeyPermission permission = new AccessKeyPermission(); permission.setDomainArray(grant.getClient().getDomain()); permission.setActionsArray(StringUtils.split(grant.getScope(), ' ')); permission.setSubnetsArray(grant.getClient().getSubnet()); permission.setNetworkIds(grant.getNetworkIds()); permissions.add(permission); existing.setPermissions(permissions); AccessKeyProcessor keyProcessor = new AccessKeyProcessor(); String key = keyProcessor.generateKey(); existing.setKey(key); for (AccessKeyPermission current : permissions) { current.setAccessKey(existing); genericDAO.persist(current); } return existing; }
@Transactional public AccessKey createAccessKeyFromOAuthGrant(OAuthGrant grant, User user, Date now) { AccessKey newKey = new AccessKey(); newKey.setType(AccessKeyType.OAUTH); if (grant.getAccessType().equals(AccessType.ONLINE)) { Date expirationDate = new Date(now.getTime() + 600000); // the key is valid for 10 minutes newKey.setExpirationDate(expirationDate); } newKey.setUser(user); newKey.setLabel( String.format( Messages.OAUTH_GRANT_TOKEN_LABEL, grant.getClient().getName(), System.currentTimeMillis())); Set<AccessKeyPermission> permissions = new HashSet<>(); AccessKeyPermission permission = new AccessKeyPermission(); permission.setDomainArray(grant.getClient().getDomain()); permission.setActionsArray(StringUtils.split(grant.getScope(), ' ')); permission.setSubnetsArray(grant.getClient().getSubnet()); permission.setNetworkIds(grant.getNetworkIds()); permissions.add(permission); newKey.setPermissions(permissions); create(user, newKey); return newKey; }
@Transactional public boolean update(@NotNull Long userId, @NotNull Long keyId, AccessKeyUpdate toUpdate) { AccessKey existing = find(keyId, userId); if (existing == null) { return false; } if (toUpdate == null) { return true; } if (toUpdate.getLabel() != null) { existing.setLabel(toUpdate.getLabel().orElse(null)); } if (toUpdate.getExpirationDate() != null) { existing.setExpirationDate(toUpdate.getExpirationDate().orElse(null)); } if (toUpdate.getType() != null) { existing.setType(toUpdate.getType().map(v -> toUpdate.getTypeEnum()).orElse(null)); } if (toUpdate.getPermissions() != null) { if (!toUpdate.getPermissions().isPresent()) { logger.error("New permissions shouldn't be empty in request parameters"); throw new IllegalParametersException(Messages.INVALID_REQUEST_PARAMETERS); } Set<AccessKeyPermission> permissionsToReplace = toUpdate.getPermissions().get(); AccessKey toValidate = toUpdate.convertTo(); authenticationUtils.validateActions(toValidate); deleteAccessKeyPermissions(existing); for (AccessKeyPermission current : permissionsToReplace) { AccessKeyPermission permission = preparePermission(current); permission.setAccessKey(existing); genericDAO.persist(permission); } } return true; }
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public Network getWithDevicesAndDeviceClasses( @NotNull Long networkId, @NotNull HivePrincipal principal) { if (principal.getUser() != null) { List<Network> found = networkDAO.getNetworkList(principal.getUser(), null, Arrays.asList(networkId)); if (found.isEmpty()) { return null; } List<Device> devices = deviceService.getList(networkId, principal); Network result = found.get(0); result.setDevices(new HashSet<>(devices)); return result; } else { AccessKey key = principal.getKey(); User user = userService.findUserWithNetworks(key.getUser().getId()); List<Network> found = networkDAO.getNetworkList(user, key.getPermissions(), Arrays.asList(networkId)); Network result = found.isEmpty() ? null : found.get(0); if (result == null) { return result; } // to get proper devices 1) get access key with all permissions 2) get devices for required // network key = accessKeyService.find(key.getId(), principal.getKey().getUser().getId()); List<AllowedKeyAction.Action> actions = new ArrayList<>(); actions.add(AllowedKeyAction.Action.GET_DEVICE); if (!CheckPermissionsHelper.checkAllPermissions(key, actions)) { result.setDevices(null); return result; } Set<Device> devices = new HashSet<>(deviceService.getList(result.getId(), principal)); result.setDevices(devices); return result; } }