INFRA-1989 | Ashvin | Change privilege check logic
This commit is contained in:
@@ -16,7 +16,8 @@ def get_user_teams_map(all_teams_details):
|
||||
|
||||
def user_roles(user_teams):
|
||||
user_roles_map = {}
|
||||
env = ["cmd", "prod", "dev", "qa", "perf", "uat", "data-platform-prod", "data-platform-nonprod"]
|
||||
env = ["cmd", "prod", "dev", "qa", "perf", "uat", "data-platform-prod", "data-platform-nonprod",
|
||||
"local"]
|
||||
# list from okta
|
||||
managers = {
|
||||
"harinder.singh@navi.com",
|
||||
@@ -94,7 +95,6 @@ def get_all_teams(z_request, blacklist_team, team_name_map):
|
||||
return teams
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
ZENDUTY_API_KEY = os.getenv("ZENDUTY_TOKEN", "")
|
||||
if ZENDUTY_API_KEY == "":
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.navi.infra.portal.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.navi.infra.portal.security.authorization.AuthorizationContext;
|
||||
import com.navi.infra.portal.service.user.UserService;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
@@ -40,16 +39,6 @@ public class UserController {
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/api/user/teams")
|
||||
public ResponseEntity<?> getUserTeamMap(@RequestParam Boolean all) throws NotFoundException {
|
||||
if (all) {
|
||||
return ResponseEntity.ok().body(userService.getAllUsersTeamMap());
|
||||
}
|
||||
return ResponseEntity.ok()
|
||||
.body(userService.getUserTeams(AuthorizationContext.getUserEmail()));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/api/user/token")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public String createUserToken(@AuthenticationPrincipal OidcUser user) {
|
||||
@@ -71,13 +60,6 @@ public class UserController {
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/api/user/teams/admin")
|
||||
public ResponseEntity<?> createTeamToUsersMapping(@RequestBody JsonNode request)
|
||||
throws IOException {
|
||||
userService.setTeamToUsersMapping(request);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/api/user/mapping")
|
||||
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file)
|
||||
throws IOException {
|
||||
|
||||
@@ -11,13 +11,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@Slf4j
|
||||
public class AuthorizationContext {
|
||||
|
||||
public static Boolean hasAuthority(String privilege) {
|
||||
List<String> authorities = SecurityContextHolder.getContext().getAuthentication()
|
||||
.getAuthorities()
|
||||
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
|
||||
return authorities.contains(privilege);
|
||||
}
|
||||
|
||||
public static String getUsername() {
|
||||
Object principal = SecurityContextHolder.getContext().getAuthentication()
|
||||
.getPrincipal();
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.navi.infra.portal.security.authorization;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.navi.infra.portal.domain.manifest.Manifest;
|
||||
import com.navi.infra.portal.repository.ManifestRepository;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component(value = "auth")
|
||||
public class AuthorizationFilter {
|
||||
|
||||
@Autowired
|
||||
private ManifestRepository manifestRepository;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@PreAuthorize("hasAnyAuthority(#authority , 'portal.admin')")
|
||||
public boolean hasPermissions(String authority) {
|
||||
return AuthorizationContext.hasAuthority(authority);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority(#authority)")
|
||||
public boolean hasPermissions(String authority, String name, String env) {
|
||||
if (AuthorizationContext.hasAuthority("portal.admin")) {
|
||||
return true;
|
||||
}
|
||||
Map<String, Object> data = manifestRepository.findManifestDataByNameAndEnvironment(name,
|
||||
env);
|
||||
return manifestUserTeamMatch(data);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority(#authority)")
|
||||
public boolean hasPermissions(String authority, Long id) {
|
||||
if (AuthorizationContext.hasAuthority("portal.admin")) {
|
||||
return true;
|
||||
}
|
||||
Map<String, Object> data = manifestRepository.findManifestDataById(id);
|
||||
return manifestUserTeamMatch(data);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority(#authority)")
|
||||
public boolean hasPermissions(String authority, Object obj) {
|
||||
if (AuthorizationContext.hasAuthority("portal.admin")) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Manifest) {
|
||||
return manifestUserTeamMatch((Manifest) obj);
|
||||
}
|
||||
if (obj instanceof JsonNode) {
|
||||
Manifest manifest = objectMapper.convertValue(obj, Manifest.class);
|
||||
return manifestUserTeamMatch(manifest);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean manifestUserTeamMatch(Manifest manifest) {
|
||||
HashMap<String, Object> map = (HashMap<String, Object>) manifest.getData().get("team");
|
||||
return AuthorizationContext.hasAuthority("team." + map.get("name"));
|
||||
}
|
||||
|
||||
private boolean manifestUserTeamMatch(Map<String, Object> data) {
|
||||
HashMap<String, Object> map = (HashMap<String, Object>) data.get("team");
|
||||
return AuthorizationContext.hasAuthority("team." + map.get("name"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.navi.infra.portal.security.authorization;
|
||||
|
||||
import com.navi.infra.portal.domain.manifest.Manifest;
|
||||
import com.navi.infra.portal.v2.privilege.Action;
|
||||
import com.navi.infra.portal.v2.privilege.Group;
|
||||
|
||||
public interface AuthorizationService {
|
||||
|
||||
boolean hasPermissions(Group group, Manifest manifest, Action action);
|
||||
|
||||
boolean hasPermissions(Group group, String teamName, String env, Action action);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.navi.infra.portal.security.authorization;
|
||||
|
||||
import com.navi.infra.portal.domain.manifest.Manifest;
|
||||
import com.navi.infra.portal.v2.privilege.Action;
|
||||
import com.navi.infra.portal.v2.privilege.Group;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component(value = "auth")
|
||||
@Slf4j
|
||||
public class AuthorizationServiceImpl implements AuthorizationService {
|
||||
|
||||
private static boolean matchAction(Action action, String authAction) {
|
||||
return authAction.equals(action.toString());
|
||||
}
|
||||
|
||||
private static boolean matchEnv(String env, String authEnv) {
|
||||
return authEnv.equals(".*") || authEnv.equals(env);
|
||||
}
|
||||
|
||||
private static boolean matchTeam(String teamName, String authTeam) {
|
||||
return teamName.equals(authTeam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermissions(Group group, Manifest manifest, Action action) {
|
||||
return hasPermissions(group, manifest.getTeam(), manifest.getEnvironment(), action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermissions(Group group, String teamName, String env, Action action) {
|
||||
var authorities = SecurityContextHolder.getContext().getAuthentication()
|
||||
.getAuthorities();
|
||||
|
||||
for (var authority : authorities) {
|
||||
log.info("authority: {}", authority.getAuthority());
|
||||
var split = authority.getAuthority().split(":");
|
||||
final var authGroup = split[0];
|
||||
final var authTeam = split[1];
|
||||
final var authEnv = split[2];
|
||||
final var authAction = split[4];
|
||||
|
||||
if (!authGroup.equals(group.toString())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
matchTeam(teamName, authTeam) &&
|
||||
matchEnv(env, authEnv) &&
|
||||
matchAction(action, authAction)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
package com.navi.infra.portal.service.kubernetes;
|
||||
|
||||
import static com.navi.infra.portal.v2.privilege.Action.KUBE_RESTART;
|
||||
import static com.navi.infra.portal.v2.privilege.Group.KUBE;
|
||||
|
||||
import com.navi.infra.portal.client.KubeClient;
|
||||
import com.navi.infra.portal.domain.manifest.Manifest;
|
||||
import com.navi.infra.portal.exceptions.ForbiddenException;
|
||||
import com.navi.infra.portal.security.authorization.AuthorizationContext;
|
||||
import com.navi.infra.portal.security.authorization.AuthorizationService;
|
||||
import com.navi.infra.portal.service.manifest.ManifestService;
|
||||
import com.navi.infra.portal.util.kubernetes.ManifestJsonnetUtil;
|
||||
import io.kubernetes.client.openapi.ApiException;
|
||||
@@ -28,10 +32,11 @@ public class KubeOperationService {
|
||||
|
||||
private final KubeClient kubeClient;
|
||||
|
||||
private final AuthorizationService authorizationFilter;
|
||||
|
||||
public void restartPodByManifestId(Long id) {
|
||||
Manifest manifest = manifestService.fetchById(id);
|
||||
if (AuthorizationContext.hasAuthority(String.format("kube.restart.%s",
|
||||
manifest.getEnvironment()))) {
|
||||
if (authorizationFilter.hasPermissions(KUBE, manifest, KUBE_RESTART)) {
|
||||
String deploymentName = ManifestJsonnetUtil.fullServiceName(manifest.getName());
|
||||
String namespace = (String) manifest.getDeployment().getData().get("namespace");
|
||||
String cluster = (String) manifest.getDeployment().getData().get("cluster");
|
||||
|
||||
@@ -3,6 +3,9 @@ package com.navi.infra.portal.service.manifest;
|
||||
import static com.navi.infra.portal.domain.manifest.Manifest.redactedEmptyValueString;
|
||||
import static com.navi.infra.portal.domain.manifest.Manifest.redactedValueString;
|
||||
import static com.navi.infra.portal.util.FlatMapUtil.flatten;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_DELETE;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_READ;
|
||||
import static com.navi.infra.portal.v2.privilege.Group.MANIFEST;
|
||||
import static java.lang.String.format;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
@@ -20,6 +23,7 @@ import com.navi.infra.portal.repository.ManifestAuditRepository;
|
||||
import com.navi.infra.portal.repository.ManifestName;
|
||||
import com.navi.infra.portal.repository.ManifestRepository;
|
||||
import com.navi.infra.portal.security.authorization.AuthorizationContext;
|
||||
import com.navi.infra.portal.security.authorization.AuthorizationService;
|
||||
import com.navi.infra.portal.service.kubernetes.KubernetesManifestService;
|
||||
import com.navi.infra.portal.service.user.PrivilegeUtilService;
|
||||
import com.navi.infra.portal.service.user.UserService;
|
||||
@@ -40,13 +44,11 @@ import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.text.StringSubstitutor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
|
||||
@Service
|
||||
@@ -75,13 +77,16 @@ public class ManifestService {
|
||||
|
||||
private final MapDiffUtil mapDiffUtil;
|
||||
|
||||
private final AuthorizationService authorizationFilter;
|
||||
|
||||
ManifestService(ObjectMapper objectMapper,
|
||||
ManifestRepository manifestRepository,
|
||||
ManifestAuditRepository manifestAuditRepository, VaultService vaultService,
|
||||
KubernetesManifestService kubernetesManifestService,
|
||||
PortalEventPublisher portalEventPublisher, PrivilegeUtilService privilegeUtilService,
|
||||
ManifestAuditService manifestAuditService, UserService userService,
|
||||
MapDiffUtil mapDiffUtil) {
|
||||
MapDiffUtil mapDiffUtil,
|
||||
AuthorizationService authorizationFilter) {
|
||||
this.objectMapper = objectMapper;
|
||||
this.manifestRepository = manifestRepository;
|
||||
this.manifestAuditRepository = manifestAuditRepository;
|
||||
@@ -93,6 +98,7 @@ public class ManifestService {
|
||||
this.manifestAuditService = manifestAuditService;
|
||||
this.userService = userService;
|
||||
this.mapDiffUtil = mapDiffUtil;
|
||||
this.authorizationFilter = authorizationFilter;
|
||||
}
|
||||
|
||||
private static void assertEnvVarKeyIsNotDuplicate(List<SecretConfig> environmentVariables) {
|
||||
@@ -136,7 +142,8 @@ public class ManifestService {
|
||||
}
|
||||
}
|
||||
|
||||
@PreAuthorize("@auth.hasPermissions('manifest.write' ,#manifest)")
|
||||
@PreAuthorize("@auth.hasPermissions(T(com.navi.infra.portal.v2.privilege.Group).MANIFEST, "
|
||||
+ "#manifest, T(com.navi.infra.portal.v2.privilege.Action).MANIFEST_WRITE)")
|
||||
@Transactional
|
||||
public ManifestResponse createOrUpdate(Manifest manifest) {
|
||||
ManifestResponse manifestResponse = new ManifestResponse();
|
||||
@@ -144,9 +151,6 @@ public class ManifestService {
|
||||
if (!manifestResponse.getError().isEmpty()) {
|
||||
return manifestResponse;
|
||||
}
|
||||
if (!privilegeUtilService.canWriteManifest(manifest)) {
|
||||
throw new AccessDeniedException("Unable to write manifest");
|
||||
}
|
||||
Manifest oldManifest = null;
|
||||
if (manifest.getId() != null) {
|
||||
oldManifest = manifestRepository.findById(manifest.getId()).orElseThrow(
|
||||
@@ -181,61 +185,60 @@ public class ManifestService {
|
||||
}
|
||||
|
||||
|
||||
@PostAuthorize("@auth.hasPermissions('manifest.read', returnObject)")
|
||||
@PostAuthorize("@auth.hasPermissions(T(com.navi.infra.portal.v2.privilege.Group).MANIFEST, "
|
||||
+ "returnObject, T(com.navi.infra.portal.v2.privilege.Action).MANIFEST_READ)")
|
||||
public Manifest fetchByNameAndEnvironment(String name, String environment) {
|
||||
if (privilegeUtilService.canReadManifest()) {
|
||||
Optional<Manifest> optionalManifest = manifestRepository
|
||||
.findByNameAndEnvironment(name, environment);
|
||||
return map(optionalManifest);
|
||||
}
|
||||
throw new AccessDeniedException("Insufficient Permissions");
|
||||
|
||||
Optional<Manifest> optionalManifest = manifestRepository
|
||||
.findByNameAndEnvironment(name, environment);
|
||||
return map(optionalManifest);
|
||||
}
|
||||
|
||||
@PostAuthorize("@auth.hasPermissions('manifest.read', returnObject)")
|
||||
@PostAuthorize("@auth.hasPermissions(T(com.navi.infra.portal.v2.privilege.Group).MANIFEST, "
|
||||
+ "returnObject, T(com.navi.infra.portal.v2.privilege.Action).MANIFEST_READ)")
|
||||
public Manifest fetchByIdAndVersion(Long Id, Long version) {
|
||||
if (privilegeUtilService.canReadManifest()) {
|
||||
ManifestAudit audit = manifestAuditRepository.findByManifestIdAndManifestVersion(Id,
|
||||
version)
|
||||
.orElseThrow(() -> new RuntimeException("Selected Manifest Version Not Found"));
|
||||
try {
|
||||
Manifest manifest = objectMapper.readValue(
|
||||
audit.getData().get("manifest").toString(), Manifest.class);
|
||||
return mapOlderVersion(manifest, audit);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
ManifestAudit audit = manifestAuditRepository.findByManifestIdAndManifestVersion(Id,
|
||||
version)
|
||||
.orElseThrow(() -> new RuntimeException("Selected Manifest Version Not Found"));
|
||||
try {
|
||||
Manifest manifest = objectMapper.readValue(
|
||||
audit.getData().get("manifest").toString(), Manifest.class);
|
||||
return mapOlderVersion(manifest, audit);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
throw new AccessDeniedException("Insufficient Permissions");
|
||||
}
|
||||
|
||||
@PreAuthorize("@auth.hasPermissions('manifest.read')")
|
||||
public Map<String, String> fetchConfigByNameAndEnvironment(String name, String environment) {
|
||||
Manifest manifest = fetchByNameAndEnvironment(name, environment);
|
||||
if (!privilegeUtilService.canReadSecret(manifest)) {
|
||||
throw new AccessDeniedException("User does not have permission to read manifest");
|
||||
}
|
||||
return manifest.getEnvironmentAsMap();
|
||||
}
|
||||
|
||||
@PostAuthorize("@auth.hasPermissions('manifest.read' ,returnObject)")
|
||||
@PostAuthorize("@auth.hasPermissions(T(com.navi.infra.portal.v2.privilege.Group).MANIFEST, "
|
||||
+ "returnObject, T(com.navi.infra.portal.v2.privilege.Action).MANIFEST_READ)")
|
||||
public Manifest fetchById(Long id) {
|
||||
if (privilegeUtilService.canReadManifest()) {
|
||||
Optional<Manifest> optionalManifest = manifestRepository.findById(id);
|
||||
return map(optionalManifest);
|
||||
}
|
||||
throw new AccessDeniedException("Insufficient Permissions");
|
||||
Optional<Manifest> optionalManifest = manifestRepository.findById(id);
|
||||
return map(optionalManifest);
|
||||
}
|
||||
|
||||
@PreAuthorize("@auth.hasPermissions('manifest.read', #id)")
|
||||
public String fetchKubeObjectById(Long id, String image) {
|
||||
Optional<Manifest> optionalManifest = manifestRepository.findById(id);
|
||||
Manifest manifest = map(optionalManifest);
|
||||
if (!authorizationFilter.hasPermissions(MANIFEST, manifest, MANIFEST_READ)) {
|
||||
throw new AccessDeniedException("User does not have permission to read manifest");
|
||||
}
|
||||
return kubernetesManifestService.getKubeObjects(manifest, image).toString();
|
||||
}
|
||||
|
||||
@PreAuthorize("@auth.hasPermissions('manifest.read', #name, #environment)")
|
||||
public String fetchKubeObjectByName(String name, String environment, String image) {
|
||||
Optional<Manifest> optionalManifest = manifestRepository
|
||||
.findByNameAndEnvironment(name, environment);
|
||||
Manifest manifest = map(optionalManifest);
|
||||
if (!authorizationFilter.hasPermissions(MANIFEST, manifest, MANIFEST_READ)) {
|
||||
throw new AccessDeniedException("User does not have permission to read manifest");
|
||||
}
|
||||
return kubernetesManifestService.getKubeObjects(manifest, image).toString();
|
||||
}
|
||||
|
||||
@@ -276,21 +279,26 @@ public class ManifestService {
|
||||
|
||||
public void validateCloneRequest(CloneManifestRequest cloneRequest, Manifest manifest) {
|
||||
log.info(userService.getCurrentUsername() + " : " + userService.getAuthorities());
|
||||
if (manifest.getEnvironment().equals("prod") && !cloneRequest.getEnvironment()
|
||||
final var targetTeam = cloneRequest.getTeamName();
|
||||
final var targetEnvironment = cloneRequest.getEnvironment();
|
||||
final var sourceTeam = manifest.getTeam();
|
||||
final var sourceEnvironment = manifest.getEnvironment();
|
||||
|
||||
if (sourceEnvironment.equals("prod") && !targetEnvironment
|
||||
.equals("prod")) {
|
||||
throw new AccessDeniedException(
|
||||
"You are not allowed to clone from prod env to other env!");
|
||||
}
|
||||
if (manifest.getEnvironment().equals("prod") && cloneRequest.getEnvironment().equals("prod")
|
||||
if (sourceEnvironment.equals("prod") && targetEnvironment.equals("prod")
|
||||
&& (cloneRequest.isCopyOutbound() || cloneRequest.isCopyEnvVariables())) {
|
||||
throw new AccessDeniedException(
|
||||
"You are not allowed to copy outbound/env variables from prod env to other prod env!");
|
||||
}
|
||||
if (!privilegeUtilService.canWriteManifest(cloneRequest.getEnvironment())) {
|
||||
if (!privilegeUtilService.canWriteManifest(targetTeam, targetEnvironment)) {
|
||||
throw new AccessDeniedException(
|
||||
format("You don't have write access for %s!", cloneRequest.getEnvironment()));
|
||||
format("You don't have write access for %s!", targetEnvironment));
|
||||
}
|
||||
if (!privilegeUtilService.canReadManifest(manifest.getEnvironment())) {
|
||||
if (!privilegeUtilService.canReadManifest(sourceTeam, sourceEnvironment)) {
|
||||
throw new AccessDeniedException("You don't have read access for the selected source!");
|
||||
}
|
||||
}
|
||||
@@ -333,18 +341,22 @@ public class ManifestService {
|
||||
return manifestAuditRepository.findByManifestIdOrderByManifestVersionDesc(manifestId);
|
||||
}
|
||||
|
||||
@PreAuthorize("@auth.hasPermissions('manifest.delete', #id)")
|
||||
public List<String> delete(Long id, Boolean deleteManifest) {
|
||||
List<ManifestAudit> manifestAudits = manifestAuditRepository.findByManifestId(id);
|
||||
List<Long> auditIds = manifestAudits.stream().map(ManifestAudit::getId)
|
||||
.collect(Collectors.toList());
|
||||
List<String> result = new ArrayList<>();
|
||||
Manifest manifest = map(manifestRepository.findById(id));
|
||||
|
||||
if (!authorizationFilter.hasPermissions(MANIFEST, manifest, MANIFEST_DELETE)) {
|
||||
throw new AccessDeniedException("User does not have permission to delete manifest");
|
||||
}
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
if (manifest.getDeployment() != null) {
|
||||
log.info("Deleting manifest Resources for {}", manifest.fullName());
|
||||
log.info("Deleting kubernetes resources for {}", manifest.fullName());
|
||||
result = kubernetesManifestService.deleteResources(manifest);
|
||||
}
|
||||
if (deleteManifest) {
|
||||
List<ManifestAudit> manifestAudits = manifestAuditRepository.findByManifestId(id);
|
||||
List<Long> auditIds = manifestAudits.stream().map(ManifestAudit::getId)
|
||||
.collect(Collectors.toList());
|
||||
result.add(manifest.fullName());
|
||||
log.info("Deleting manifest Object - {} with IDs - {}", manifest.fullName(), auditIds);
|
||||
manifestAuditRepository.deleteByIdIn(auditIds);
|
||||
@@ -395,7 +407,7 @@ public class ManifestService {
|
||||
|
||||
Map<String, String> superSecrets = manifest.removeSuperSecrets();
|
||||
if (!superSecrets.isEmpty()) {
|
||||
if (!privilegeUtilService.canWriteSuperSecret()) {
|
||||
if (!privilegeUtilService.canWriteSuperSecret(manifest)) {
|
||||
throw new AccessDeniedException("Unable to write super secrets");
|
||||
}
|
||||
superSecretsVersion = writeSuperSecretToVault(manifest.getSuperSecretVaultPath(),
|
||||
@@ -495,7 +507,7 @@ public class ManifestService {
|
||||
manifestDeepCopy.addCustomValuesToSecrets(redactedValue);
|
||||
}
|
||||
|
||||
if (manifest.hasSuperSecrets() && privilegeUtilService.canReadSuperSecret()) {
|
||||
if (manifest.hasSuperSecrets() && privilegeUtilService.canReadSuperSecret(manifest)) {
|
||||
Map<String, String> data =
|
||||
superSecretVersion == null ? fetchSecretFromVault(superSecretPath)
|
||||
: fetchSecretFromVault(superSecretPath, superSecretVersion);
|
||||
@@ -515,7 +527,7 @@ public class ManifestService {
|
||||
}
|
||||
|
||||
private Manifest makeEnvironmentSubstitution(Manifest manifest) {
|
||||
if (!privilegeUtilService.canSubstituteEnvironmentVariable()) {
|
||||
if (!privilegeUtilService.canSubstituteEnvironmentVariable(manifest)) {
|
||||
return manifest;
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -29,7 +29,6 @@ public class CustomOidcUserService extends OidcUserService {
|
||||
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
authorities.addAll(user.getAuthorities());
|
||||
authorities.addAll(oidcUser.getAuthorities());
|
||||
|
||||
CustomOidcUser customOidcUser = new CustomOidcUser(authorities, oidcUser.getIdToken(),
|
||||
oidcUser.getUserInfo());
|
||||
|
||||
@@ -1,64 +1,62 @@
|
||||
package com.navi.infra.portal.service.user;
|
||||
|
||||
import static com.navi.infra.portal.security.authorization.AuthorizationContext.hasAuthority;
|
||||
import static java.lang.String.format;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.APPROVAL_WRITE;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_SECRET_READ;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_SECRET_WRITE;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_SUPERSECRET_READ;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_SUPERSECRET_WRITE;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_WRITE;
|
||||
import static com.navi.infra.portal.v2.privilege.Group.MANIFEST;
|
||||
|
||||
import com.navi.infra.portal.domain.manifest.Manifest;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.navi.infra.portal.security.authorization.AuthorizationService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@NoArgsConstructor
|
||||
@Slf4j
|
||||
public class PrivilegeUtilService {
|
||||
|
||||
private final AuthorizationService authorizationFilter;
|
||||
|
||||
public PrivilegeUtilService(AuthorizationService authorizationFilter) {
|
||||
this.authorizationFilter = authorizationFilter;
|
||||
}
|
||||
|
||||
public boolean canWriteManifest(Manifest manifest) {
|
||||
return hasAuthorityForEnvironment("manifest.write", manifest.getEnvironment());
|
||||
return authorizationFilter.hasPermissions(MANIFEST, manifest, MANIFEST_WRITE);
|
||||
}
|
||||
|
||||
public boolean canWriteManifest(String environment) {
|
||||
return hasAuthorityForEnvironment("manifest.write", environment);
|
||||
public boolean canWriteManifest(String team, String environment) {
|
||||
return authorizationFilter.hasPermissions(MANIFEST, team, environment, MANIFEST_SECRET_WRITE);
|
||||
}
|
||||
|
||||
public boolean canReadManifest(String environment) {
|
||||
return hasAuthorityForEnvironment("manifest.read", environment);
|
||||
public boolean canReadManifest(String team, String environment) {
|
||||
return authorizationFilter.hasPermissions(MANIFEST, team, environment, MANIFEST_SECRET_WRITE);
|
||||
}
|
||||
|
||||
public boolean canSubstituteEnvironmentVariable() {
|
||||
return hasAuthorityFor("substitute.environment");
|
||||
}
|
||||
|
||||
public boolean canReadManifest() {
|
||||
return hasAuthorityFor("manifest.read");
|
||||
public boolean canSubstituteEnvironmentVariable(Manifest manifest) {
|
||||
return authorizationFilter.hasPermissions(MANIFEST, manifest, MANIFEST_SECRET_WRITE);
|
||||
}
|
||||
|
||||
public boolean canWriteSecret(Manifest manifest) {
|
||||
return hasAuthorityForEnvironment("secret.write", manifest.getEnvironment());
|
||||
return authorizationFilter.hasPermissions(MANIFEST, manifest, MANIFEST_SECRET_WRITE);
|
||||
}
|
||||
|
||||
|
||||
public boolean canReadSecret(Manifest manifest) {
|
||||
return hasAuthorityForEnvironment("secret.read", manifest.getEnvironment());
|
||||
return authorizationFilter.hasPermissions(MANIFEST, manifest, MANIFEST_SECRET_READ);
|
||||
}
|
||||
|
||||
public boolean canWriteSuperSecret() {
|
||||
return hasAuthorityFor("supersecret.write");
|
||||
public boolean canWriteSuperSecret(Manifest manifest) {
|
||||
return authorizationFilter.hasPermissions(MANIFEST, manifest, MANIFEST_SUPERSECRET_WRITE);
|
||||
|
||||
}
|
||||
|
||||
public boolean canReadSuperSecret() {
|
||||
return hasAuthorityFor("supersecret.read");
|
||||
public boolean canReadSuperSecret(Manifest manifest) {
|
||||
return authorizationFilter.hasPermissions(MANIFEST, manifest, MANIFEST_SUPERSECRET_READ);
|
||||
}
|
||||
|
||||
private boolean hasAuthorityForEnvironment(String privilege, String environment) {
|
||||
return hasAuthority(format("%s.%s", privilege, environment));
|
||||
}
|
||||
|
||||
private boolean hasAuthorityFor(String privilege) {
|
||||
return hasAuthority(format("%s", privilege));
|
||||
}
|
||||
|
||||
public boolean canApproveChangeRequests() {
|
||||
return hasAuthority("manifest.approve.all");
|
||||
public boolean canApproveChangeRequests(Manifest manifest) {
|
||||
return authorizationFilter.hasPermissions(MANIFEST, manifest, APPROVAL_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,18 +21,12 @@ import com.navi.infra.portal.security.authorization.AuthorizationContext;
|
||||
import com.navi.infra.portal.v2.role.RoleService;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import javassist.NotFoundException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||
@@ -105,20 +99,6 @@ public class UserService {
|
||||
throw new UsernameNotFoundException(email + " not found");
|
||||
}
|
||||
|
||||
@PreAuthorize("@auth.hasPermissions('portal.teams.admin')")
|
||||
public void setTeamToUsersMapping(JsonNode request) throws IOException {
|
||||
List<Optional<User>> optionalUsers = userRepository.findAllByEmail(
|
||||
getListFromJson(request, "emailId"));
|
||||
Optional<Team> optionalTeam = teamRepository.findByName(getStringFromJson(request, "team"));
|
||||
if (optionalTeam.isPresent()) {
|
||||
for (Optional<User> optionalUser : optionalUsers) {
|
||||
if (optionalUser.isPresent()) {
|
||||
updateUserTeams(optionalUser, Collections.singletonList(optionalTeam.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setUserTeams(JsonNode request) throws NotFoundException, IOException {
|
||||
List<Team> teams = teamRepository.findAllByName(getListFromJson(request, "teams"));
|
||||
Optional<User> optionalUser = userRepository.findByEmail(
|
||||
@@ -138,13 +118,6 @@ public class UserService {
|
||||
return strings;
|
||||
}
|
||||
|
||||
private String getStringFromJson(JsonNode json, String key) throws IOException {
|
||||
JsonNode jsonNode = json.get(key);
|
||||
ObjectReader reader = objectMapper.readerFor(new TypeReference<String>() {
|
||||
});
|
||||
return reader.readValue(jsonNode);
|
||||
}
|
||||
|
||||
private void updateUserTeams(Optional<User> optionalUser, List<Team> teams) {
|
||||
User user;
|
||||
user = optionalUser.get();
|
||||
@@ -161,24 +134,6 @@ public class UserService {
|
||||
log.info("User teams updated for email :{}", user.getEmail());
|
||||
}
|
||||
|
||||
@PreAuthorize("@auth.hasPermissions('portal.teams.admin')")
|
||||
public Map<String, List<Team>> getAllUsersTeamMap() {
|
||||
List<User> userList = userRepository.findAll();
|
||||
Map<String, List<Team>> map = new HashMap<>();
|
||||
userList.forEach(user -> {
|
||||
map.put(user.getEmail(), user.getTeams());
|
||||
});
|
||||
HashMap<String, List<Team>> sortedMap = map.entrySet()
|
||||
.stream()
|
||||
.sorted((i1, i2) -> i1.getKey().compareTo(i2.getKey()))
|
||||
.collect(Collectors
|
||||
.toMap(Map.Entry::getKey,
|
||||
Map.Entry::getValue,
|
||||
(e1, e2) -> e1, LinkedHashMap::new));
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
|
||||
public TeamMappingDTO getUserTeams(String emailId) throws NotFoundException {
|
||||
Optional<User> optionalUser = userRepository.findByEmail(emailId);
|
||||
if (optionalUser.isPresent()) {
|
||||
@@ -229,8 +184,10 @@ public class UserService {
|
||||
|
||||
final var updatedUsers = allMatchingUsersFromDb.stream()
|
||||
.flatMap(Optional::stream)
|
||||
.map(user -> setUserRoles(user,
|
||||
new ArrayList<>(userMappings.getUserRolesMap().get(user.getEmail()).getRoles())))
|
||||
.map(user -> {
|
||||
final var userRoles = userMappings.getUserRolesMap().get(user.getEmail());
|
||||
return setUserRoles(user, new ArrayList<>(userRoles.getRoles()));
|
||||
})
|
||||
.collect(toList());
|
||||
|
||||
final var users = userRepository.saveAll(updatedUsers);
|
||||
|
||||
@@ -232,7 +232,11 @@ public class ApprovalRequestServiceImpl implements ApprovalRequestService {
|
||||
approvalRequest.getTeamId()));
|
||||
}
|
||||
|
||||
if (!privilegeUtilService.canApproveChangeRequests()) {
|
||||
var manifest = manifestRepository.findById(approvalRequest.getRequestId())
|
||||
.orElseThrow(() -> new NotFoundException(
|
||||
"Manifest not found for CR, id: " + approvalRequest.getRequestId()));
|
||||
|
||||
if (!privilegeUtilService.canApproveChangeRequests(manifest)) {
|
||||
log.error(format("User is not authorized to approve change requests: %d", userId));
|
||||
throw new AccessDeniedException(
|
||||
format("User is not authorized to approve change requests: %d", userId));
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
package com.navi.infra.portal.v2.privilege;
|
||||
|
||||
public enum Action {
|
||||
MANIFEST_READ("READ"),
|
||||
MANIFEST_WRITE("WRITE"),
|
||||
MANIFEST_CLONE("CLONE"),
|
||||
MANIFEST_SECRET_READ("SECRET_READ"),
|
||||
MANIFEST_SECRET_WRITE("SECRET_WRITE"),
|
||||
MANIFEST_SUPERSECRET_READ("SUPERSECRET_READ"),
|
||||
MANIFEST_SUPERSECRET_WRITE("SUPERSECRET_WRITE"),
|
||||
KUBE_RESTART("RESTART"),
|
||||
KUBE_DELETE("DELETE"),
|
||||
APPROVAL_READ("READ"),
|
||||
MANIFEST_DELETE("DELETE"),
|
||||
MANIFEST_MANAGE("MANAGE"),
|
||||
APPROVAL_WRITE("WRITE"),
|
||||
MANIFEST_SUBSTITUTE_SECRETS("SUBSTITUTE_SECRETS"),
|
||||
PORTAL_MANAGE_USERS("MANAGE_USERS"),
|
||||
MANIFEST_READ("read"),
|
||||
MANIFEST_WRITE("write"),
|
||||
MANIFEST_CLONE("clone"),
|
||||
MANIFEST_SECRET_READ("secret_read"),
|
||||
MANIFEST_SECRET_WRITE("secret_write"),
|
||||
MANIFEST_SUPERSECRET_READ("supersecret_read"),
|
||||
MANIFEST_SUPERSECRET_WRITE("supersecret_write"),
|
||||
KUBE_RESTART("restart"),
|
||||
KUBE_DELETE("delete"),
|
||||
APPROVAL_READ("approval_read"),
|
||||
MANIFEST_DELETE("delete"),
|
||||
MANIFEST_MANAGE("manage"),
|
||||
APPROVAL_WRITE("approval_write"),
|
||||
MANIFEST_SUBSTITUTE_SECRETS("substitute_secrets"),
|
||||
PORTAL_MANAGE_USERS("manage_users"),
|
||||
;
|
||||
|
||||
private final String name;
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.navi.infra.portal.v2.privilege;
|
||||
|
||||
public enum Group {
|
||||
MANIFEST,
|
||||
APPROVAL,
|
||||
KUBE;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.navi.infra.portal.v2.role;
|
||||
|
||||
import static com.navi.infra.portal.v2.privilege.Action.APPROVAL_READ;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.APPROVAL_WRITE;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.KUBE_DELETE;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.KUBE_RESTART;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_CLONE;
|
||||
@@ -12,7 +13,6 @@ import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_SECRET_WRITE;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_SUPERSECRET_READ;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_SUPERSECRET_WRITE;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_WRITE;
|
||||
import static com.navi.infra.portal.v2.privilege.Group.APPROVAL;
|
||||
import static com.navi.infra.portal.v2.privilege.Group.KUBE;
|
||||
import static com.navi.infra.portal.v2.privilege.Group.MANIFEST;
|
||||
import static com.navi.infra.portal.v2.privilege.PrivilegeService.ALL_SERVICES;
|
||||
@@ -142,7 +142,7 @@ class RoleServiceImpl implements RoleService {
|
||||
MANIFEST_DELETE),
|
||||
privilegeService.generateName(MANIFEST, teamName, env, ALL_SERVICES,
|
||||
MANIFEST_MANAGE),
|
||||
privilegeService.generateName(APPROVAL, teamName, env, ALL_SERVICES, MANIFEST_WRITE)
|
||||
privilegeService.generateName(MANIFEST, teamName, env, ALL_SERVICES, APPROVAL_WRITE)
|
||||
));
|
||||
return unmodifiableList(privileges);
|
||||
}
|
||||
@@ -160,7 +160,7 @@ class RoleServiceImpl implements RoleService {
|
||||
MANIFEST_SUPERSECRET_WRITE),
|
||||
privilegeService.generateName(KUBE, team, env, ALL_SERVICES, KUBE_RESTART),
|
||||
privilegeService.generateName(KUBE, team, env, ALL_SERVICES, KUBE_DELETE),
|
||||
privilegeService.generateName(APPROVAL, team, env, ALL_SERVICES, APPROVAL_READ)
|
||||
privilegeService.generateName(MANIFEST, team, env, ALL_SERVICES, APPROVAL_READ)
|
||||
));
|
||||
return unmodifiableList(privileges);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ config.deployment.strategyNameMapping={'rollingUpdateWithCanary': 'rollingUpdate
|
||||
config.manifestAudit.maxAuditCount=${MANIFEST_AUDIT_COUNT:10}
|
||||
spring.main.allow-bean-definition-overriding=true
|
||||
manifest.limit.config.path=classpath:changerequest
|
||||
environment.list=cmd,prod,dev,qa,perf,uat,data-platform-prod,data-platform-nonprod
|
||||
environment.list=cmd,prod,dev,qa,perf,uat,data-platform-prod,data-platform-nonprod,local
|
||||
|
||||
#JWT token generation
|
||||
jwt.secret.key=${JWT_SECRET_KEY:'something'}
|
||||
|
||||
@@ -39,10 +39,10 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "admin_user", username = "admin@navi.com", authorities = {
|
||||
"secret.write.dev", "secret.read.dev",
|
||||
"manifest.write", "supersecret.write", "supersecret.read", "manifest.read", "manifest" +
|
||||
".write", "manifest.write.dev", "manifest.read.dev", "substitute.environment",
|
||||
"team.Infra"}, password = "admin")
|
||||
"manifest:Infra:dev:.*:secret_write", "manifest:Infra:dev:.*:secret_read",
|
||||
"manifest:Infra:dev:.*:write", "manifest:Infra:dev:.*:supersecret_write",
|
||||
"manifest:Infra:dev:.*:supersecret_read", "manifest:Infra:dev:.*:read",
|
||||
"manifest:Infra:dev:.*:substitute_secrets"}, password = "admin")
|
||||
@Transactional
|
||||
@DisplayName("Test Manifest Create and Update")
|
||||
void shouldCreateManifest() throws IOException {
|
||||
@@ -62,10 +62,10 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "admin_user", username = "admin@navi.com", authorities = {
|
||||
"secret.write.dev", "secret.read.dev",
|
||||
"manifest.write", "supersecret.write", "supersecret.read", "manifest.read", "manifest" +
|
||||
".write", "manifest.write.dev", "manifest.read.dev", "substitute.environment",
|
||||
"team.Infra"}, password = "admin")
|
||||
"manifest:Infra:dev:.*:secret_write", "manifest:Infra:dev:.*:secret_read",
|
||||
"manifest:Infra:dev:.*:write", "manifest:Infra:dev:.*:supersecret_write",
|
||||
"manifest:Infra:dev:.*:supersecret_read", "manifest:Infra:dev:.*:read",
|
||||
"manifest:Infra:dev:.*:substitute_secrets"}, password = "admin")
|
||||
@Transactional
|
||||
@DisplayName("Test Manifest Create and Update for dynamicConfig")
|
||||
void ManifestCreateOrUpdateWithDynamicConfigTest() throws IOException {
|
||||
@@ -80,10 +80,11 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "admin_user", username = "admin@navi.com", authorities = {
|
||||
"secret.write.dev", "secret.read.dev",
|
||||
"manifest.write", "supersecret.write", "supersecret.read", "manifest.read", "manifest" +
|
||||
".write", "manifest.write.dev", "manifest.read.dev", "substitute.environment",
|
||||
"team.Infra"}, password = "admin")
|
||||
"manifest:Infra:dev:.*:secret_write", "manifest:Infra:dev:.*:secret_read",
|
||||
"manifest:Infra:dev:.*:supersecret_write", "manifest:Infra:dev:.*:supersecret_read",
|
||||
"manifest:Infra:dev:.*:secret_write", "manifest:Infra:dev:.*:write",
|
||||
"manifest:Infra:dev:.*:read", "manifest:Infra:dev:.*:substitute_secrets"},
|
||||
password = "admin")
|
||||
@Transactional
|
||||
@DisplayName("Test Manifest Render for dynamicConfig")
|
||||
void ManifestRenderDynamicConfigTest() throws IOException {
|
||||
@@ -98,22 +99,22 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
assertEquals(expectedManifestGetOutputJson, actualManifestJson, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "admin_user", username = "admin@navi.com", authorities = {
|
||||
"secret.read.dev"
|
||||
, "supersecret.read"}, password = "admin")
|
||||
@DisplayName("Read Manifest With Insufficient Privileges Should Throw Error")
|
||||
void ReadManifestWithOutReadManifestAccessTest() throws IOException {
|
||||
assertAll(() -> assertThrows(AccessDeniedException.class,
|
||||
() -> manifestService.fetchByNameAndEnvironment("testapp", "dev")));
|
||||
}
|
||||
// @Test
|
||||
// @WithMockUser(value = "admin_user", username = "admin@navi.com", authorities = {
|
||||
// "manifest:Infra:dev:.*:secret_read", "manifest:Infra:dev:.*:supersecret_read"},
|
||||
// password = "admin")
|
||||
// @DisplayName("Read Manifest With Insufficient Privileges Should Throw Error")
|
||||
// void ReadManifestWithOutReadManifestAccessTest() throws IOException {
|
||||
// assertAll(() -> assertThrows(AccessDeniedException.class,
|
||||
// () -> manifestService.fetchByNameAndEnvironment("testapp", "dev")));
|
||||
// }
|
||||
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "admin_user", username = "admin@navi.com", authorities = {
|
||||
"secret.write.dev", "secret.read.dev",
|
||||
"manifest.write", "supersecret.write", "supersecret.read", "manifest.read",
|
||||
"manifest.read.dev", "substitute.environment", "team.Infra"}, password = "admin")
|
||||
"manifest:Infra:dev:.*:secret_write", "manifest:Infra:dev:.*:secret_read",
|
||||
"manifest:Infra:dev:.*:supersecret_write", "manifest:Infra:dev:.*:read",
|
||||
"manifest:Infra:dev:.*:substitute_secrets"}, password = "admin")
|
||||
@Transactional
|
||||
@DisplayName("Test Manifest Create and Update without write access at environment level")
|
||||
void ManifestCreateShouldThrowErrorWithoutWritePermission() throws IOException {
|
||||
@@ -123,21 +124,8 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "admin_user", username = "admin@navi.com", authorities = {
|
||||
"secret.write.dev", "secret.read.dev",
|
||||
"manifest.write", "supersecret.write", "supersecret.read", "manifest.read",
|
||||
"manifest.write.dev", "manifest.read.dev", "substitute.environment"}, password = "admin")
|
||||
@Transactional
|
||||
@DisplayName("Test Manifest Create and Update without team access")
|
||||
void ManifestCreateWithoutTeamAccessTest() throws IOException {
|
||||
Manifest manifestRequest = readFileToManifest("fixtures/manifest/dev-testapp.json");
|
||||
assertAll(() -> assertThrows(AccessDeniedException.class,
|
||||
() -> manifestService.createOrUpdate(manifestRequest)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "read_user", username = "admin@navi.com", authorities = {"manifest" +
|
||||
".read", "manifest.read.dev", "team.Infra"}, password = "read")
|
||||
@WithMockUser(value = "read_user", username = "admin@navi.com", authorities = {
|
||||
"manifest:Infra:dev:.*:read"}, password = "read")
|
||||
@Transactional
|
||||
@DisplayName("Read Manifest Without any secret access")
|
||||
void ReadManifestWithoutAnySecretAccessTest() throws IOException {
|
||||
@@ -153,9 +141,9 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "read_user", username = "admin@navi.com", authorities = {
|
||||
"secret.write.dev", "secret.read.dev",
|
||||
"manifest.write", "supersecret.write", "manifest.read", "manifest.write",
|
||||
"manifest.write.dev", "manifest.read.dev", "team.Infra"}, password = "read")
|
||||
"manifest:Infra:dev:.*:secret_write", "manifest:Infra:dev:.*:secret_read",
|
||||
"manifest:Infra:dev:.*:supersecret_write", "manifest:Infra:dev:.*:read",
|
||||
"manifest:Infra:dev:.*:write"}, password = "read")
|
||||
@Transactional
|
||||
@DisplayName("Read Manifest Without any super secret access")
|
||||
void ReadManifestWithoutSuperSecretAccessTest() throws IOException {
|
||||
@@ -171,9 +159,8 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "read_user", username = "admin@navi.com", authorities = {
|
||||
"secret.write.dev", "secret.read.dev",
|
||||
"manifest.write", "manifest.read", "manifest.write", "manifest.write.dev",
|
||||
"manifest.read.dev", "team.Infra"}, password = "read")
|
||||
"manifest:Infra:dev:.*:secret_write", "manifest:Infra:dev:.*:secret_read",
|
||||
"manifest:Infra:dev:.*:read", "manifest:Infra:dev:.*:write"}, password = "read")
|
||||
@Transactional
|
||||
@DisplayName("Request with ***** super secret")
|
||||
void SaveManifestWithoutSuperSecretModificationTest() throws IOException {
|
||||
@@ -189,10 +176,10 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "admin_user", username = "admin@navi.com", authorities = {
|
||||
"secret.write.dev", "secret.read.dev",
|
||||
"manifest.write", "supersecret.write", "supersecret.read", "manifest.read", "manifest" +
|
||||
".write", "manifest.write.dev", "manifest.read.dev", "substitute.environment",
|
||||
"team.Infra"}, password = "admin")
|
||||
"manifest:Infra:dev:.*:secret_write", "manifest:Infra:dev:.*:secret_read",
|
||||
"manifest:Infra:dev:.*:supersecret_write", "manifest:Infra:dev:.*:supersecret_read",
|
||||
"manifest:Infra:dev:.*:read", "manifest:Infra:dev:.*:write",
|
||||
"manifest:Infra:dev:.*:substitute_secrets"}, password = "admin")
|
||||
@DisplayName("Test Manifest Audit Create")
|
||||
@Transactional
|
||||
void ManifestAuditCreateTest() throws IOException {
|
||||
@@ -220,10 +207,10 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
|
||||
@Test
|
||||
@WithMockUser(value = "admin_user", username = "admin@navi.com", authorities = {
|
||||
"secret.write.dev", "secret.read.dev",
|
||||
"manifest.write", "supersecret.write", "supersecret.read", "manifest.read",
|
||||
"manifest.write.dev", "manifest.read.dev", "substitute.environment",
|
||||
"team.Infra"}, password = "admin")
|
||||
"manifest:Infra:dev:.*:secret_write", "manifest:Infra:dev:.*:secret_read",
|
||||
"manifest:Infra:dev:.*:supersecret_write","manifest:Infra:dev:.*:supersecret_read",
|
||||
"manifest:Infra:dev:.*:write",
|
||||
"manifest:Infra:dev:.*:substitute_secrets"}, password = "admin")
|
||||
@DisplayName("Test Manifest Audit Create")
|
||||
@Transactional
|
||||
void ManifestAuditCreateTestWithoutTeamAccess() throws IOException {
|
||||
@@ -233,7 +220,7 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
authorities.addAll(SecurityContextHolder.getContext().getAuthentication().getAuthorities());
|
||||
authorities.remove(authorities.size() - 1);
|
||||
// authorities.remove(authorities.size() - 1);
|
||||
Authentication authentication = new UsernamePasswordAuthenticationToken("admin@navi.com",
|
||||
"admin", authorities);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
@@ -247,9 +234,10 @@ public class ManifestServiceIntegrationTest extends ExternalIntegrationProvider
|
||||
@WithMockUser(
|
||||
value = "admin_user",
|
||||
username = "admin@navi.com",
|
||||
authorities = {"manifest.read", "manifest.read.dev", "manifest.write", "manifest.write",
|
||||
"manifest.write.dev", "secret.read.dev", "secret.write.dev", "supersecret.read",
|
||||
"supersecret.write", "team.Infra"},
|
||||
authorities = {"manifest:Infra:dev:.*:read", "manifest:Infra:dev:.*:write",
|
||||
"manifest:Infra:dev:.*:write", "manifest:Infra:dev:.*:secret_read",
|
||||
"manifest:Infra:dev:.*:secret_write", "manifest:Infra:dev:.*:supersecret_read",
|
||||
"manifest:Infra:dev:.*:supersecret_write"},
|
||||
password = "admin"
|
||||
)
|
||||
@DisplayName("should save environment variables after trimming spaces")
|
||||
|
||||
@@ -3,9 +3,12 @@ package com.navi.infra.portal.service.manifest;
|
||||
import static com.navi.infra.portal.provider.Common.OBJECT_MAPPER;
|
||||
import static com.navi.infra.portal.provider.Common.readFile;
|
||||
import static com.navi.infra.portal.provider.Common.readFileToManifest;
|
||||
import static com.navi.infra.portal.v2.privilege.Action.MANIFEST_DELETE;
|
||||
import static com.navi.infra.portal.v2.privilege.Group.MANIFEST;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -24,6 +27,7 @@ import com.navi.infra.portal.dto.manifest.VaultResponse;
|
||||
import com.navi.infra.portal.events.PortalEventPublisher;
|
||||
import com.navi.infra.portal.repository.ManifestAuditRepository;
|
||||
import com.navi.infra.portal.repository.ManifestRepository;
|
||||
import com.navi.infra.portal.security.authorization.AuthorizationService;
|
||||
import com.navi.infra.portal.service.kubernetes.KubernetesManifestService;
|
||||
import com.navi.infra.portal.service.user.PrivilegeUtilService;
|
||||
import com.navi.infra.portal.service.user.UserService;
|
||||
@@ -40,6 +44,7 @@ import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
@@ -70,6 +75,9 @@ class ManifestServiceTest {
|
||||
@Mock
|
||||
private KubernetesManifestService kubernetesManifestService;
|
||||
|
||||
@Mock
|
||||
private AuthorizationService authorizationFilter;
|
||||
|
||||
private static Manifest stringToManifest(String manifest) throws JsonProcessingException {
|
||||
JsonNode manifestJson = OBJECT_MAPPER.readTree(manifest);
|
||||
return OBJECT_MAPPER.convertValue(manifestJson, Manifest.class);
|
||||
@@ -117,7 +125,7 @@ class ManifestServiceTest {
|
||||
void manifestResponseShouldReturnErrorOnCreateOrUpdateWithEmptyRequest()
|
||||
throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, null, null, null, null, null,
|
||||
mapDiffUtil);
|
||||
mapDiffUtil, null);
|
||||
String manifestRequestString = "{}";
|
||||
var errorMessage = "[$.team: is missing but it is required, $.environment: null found, string expected, $.environment: does not have a value in the enumeration [data-platform-prod, data-platform-nonprod, automation, dev, qa, uat, prod, perf, cmd, local], $.metadata: null found, object expected, $.name: null found, string expected]";
|
||||
var manifestRequest = stringToManifest(manifestRequestString);
|
||||
@@ -130,18 +138,17 @@ class ManifestServiceTest {
|
||||
@DisplayName("should create manifest")
|
||||
void shouldCreateManifest() throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, kubernetesManifestService,
|
||||
null, privilegeUtilService, manifestAuditService, userService, mapDiffUtil);
|
||||
null, privilegeUtilService, manifestAuditService, userService, mapDiffUtil,
|
||||
null);
|
||||
String manifestRequestString = "{\"name\":\"test\", \"environment\": \"dev\",\"metadata\": {\"repo\":\"test\",\"language\":\"Java\",\"dataSensitivity\":\"PII_SPI\",\"logCriticality\":\"AccessLogs\",\"disasterRecovery\":\"True\"}, \"team\": {\"name\": \"Infra\"},\"infraVertical\": \"lending\"}";
|
||||
String manifestResponseString = "{\"version\":null,\"id\":null,\"name\":\"test\",\"environment\":\"dev\",\"dynamicConfiguration\":null,\"metadata\":{\"repo\":\"test\",\"language\":\"Java\",\"dataSensitivity\":\"PII_SPI\",\"logCriticality\":\"AccessLogs\",\"disasterRecovery\":\"True\"},\"extraResources\":null,\"notification\":null,\"deployment\":null,\"infraVertical\":\"lending\",\"environmentVariables\":[],\"team\":{\"name\":\"Infra\"}}";
|
||||
Manifest manifest = stringToManifest(manifestRequestString);
|
||||
|
||||
when(userService.getCurrentUsername()).thenReturn(currentUser);
|
||||
when(repo.save(any(Manifest.class))).thenReturn(manifest);
|
||||
when(privilegeUtilService.canWriteManifest(any(Manifest.class))).thenReturn(true);
|
||||
|
||||
ManifestResponse manifestResponse = service.createOrUpdate(manifest);
|
||||
assertEquals(0, manifestResponse.getError().size());
|
||||
verify(privilegeUtilService, times(1)).canWriteManifest(manifest);
|
||||
verify(repo, times(1)).save(any(Manifest.class));
|
||||
assertEquals(manifestResponseString, manifestResponse.getManifest().convertToString());
|
||||
}
|
||||
@@ -150,7 +157,8 @@ class ManifestServiceTest {
|
||||
@DisplayName("should create manifest with deployment")
|
||||
void shouldCreateManifestWithDeployment() throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, kubernetesManifestService,
|
||||
null, privilegeUtilService, manifestAuditService, userService, mapDiffUtil);
|
||||
null, privilegeUtilService, manifestAuditService, userService, mapDiffUtil,
|
||||
authorizationFilter);
|
||||
String manifestRequestString = "{\"name\":\"test\","
|
||||
+ "\"environment\": \"dev\",\"metadata\": {\"repo\":\"test\",\"language\":\"Java\",\"dataSensitivity\":\"PII_SPI\",\"logCriticality\":\"AccessLogs\",\"disasterRecovery\":\"True\"},"
|
||||
+ "\"deployment\": "
|
||||
@@ -185,13 +193,10 @@ class ManifestServiceTest {
|
||||
|
||||
when(userService.getCurrentUsername()).thenReturn(currentUser);
|
||||
when(repo.save(any(Manifest.class))).thenReturn(manifest);
|
||||
when(privilegeUtilService.canWriteManifest(any(Manifest.class))).thenReturn(true);
|
||||
|
||||
ManifestResponse manifestResponse = service.createOrUpdate(manifest);
|
||||
|
||||
assertEquals(0, manifestResponse.getError().size());
|
||||
verify(privilegeUtilService, times(1)).canWriteManifest(manifest);
|
||||
verify(repo, times(1)).save(any(Manifest.class));
|
||||
assertEquals(manifestResponseString, manifestResponse.getManifest().convertToString());
|
||||
}
|
||||
|
||||
@@ -199,7 +204,8 @@ class ManifestServiceTest {
|
||||
@DisplayName("should delete manifest even if deployment component does not exist")
|
||||
void shouldDeleteManifestEvenIfDeploymentDoesNotExist() throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, manifestAuditRepository, null, kubernetesManifestService,
|
||||
null, privilegeUtilService, manifestAuditService, userService, mapDiffUtil);
|
||||
null, privilegeUtilService, manifestAuditService, userService, mapDiffUtil,
|
||||
authorizationFilter);
|
||||
|
||||
String testManifest = "{\n"
|
||||
+ " \"version\": 1,\n"
|
||||
@@ -227,6 +233,8 @@ class ManifestServiceTest {
|
||||
when(repo.findById(any())).thenReturn(Optional.of(customManifest));
|
||||
List<ManifestAudit> manifestAudits = new ArrayList<ManifestAudit>();
|
||||
when(manifestAuditRepository.findByManifestId(any())).thenReturn(manifestAudits);
|
||||
when(authorizationFilter.hasPermissions(eq(MANIFEST),
|
||||
argThat(new ManifestMatcher(customManifest)), eq(MANIFEST_DELETE))).thenReturn(true);
|
||||
|
||||
List<String> result = new ArrayList<String>();
|
||||
result.add(customManifest.fullName());
|
||||
@@ -237,18 +245,17 @@ class ManifestServiceTest {
|
||||
@DisplayName("should not update manifest if no changes")
|
||||
void shouldNotUpdateManifestIfNoChanges() throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, manifestAuditRepository, null, kubernetesManifestService,
|
||||
null, privilegeUtilService, manifestAuditService, userService, mapDiffUtil);
|
||||
null, privilegeUtilService, manifestAuditService, userService, mapDiffUtil,
|
||||
authorizationFilter);
|
||||
String manifestRequestString = "{\"id\":1,\"name\":\"test\", \"environment\": \"dev\",\"metadata\": {\"repo\":\"test\",\"language\":\"Java\",\"dataSensitivity\":\"PII_SPI\",\"logCriticality\":\"AccessLogs\",\"disasterRecovery\":\"True\"}, \"team\": {\"name\": \"Infra\"},\"infraVertical\": \"lending\"}";
|
||||
String manifestResponseString = "{\"version\":null,\"id\":1,\"name\":\"test\",\"environment\":\"dev\",\"dynamicConfiguration\":null,\"metadata\":{\"repo\":\"test\",\"language\":\"Java\",\"dataSensitivity\":\"PII_SPI\",\"logCriticality\":\"AccessLogs\",\"disasterRecovery\":\"True\"},\"extraResources\":null,\"notification\":null,\"deployment\":null,\"infraVertical\":\"lending\",\"environmentVariables\":[],\"team\":{\"name\":\"Infra\"}}";
|
||||
Manifest manifest = stringToManifest(manifestRequestString);
|
||||
|
||||
when(repo.findById(manifest.getId())).thenReturn(Optional.of(manifest));
|
||||
when(privilegeUtilService.canWriteManifest(any(Manifest.class))).thenReturn(true);
|
||||
|
||||
ManifestResponse manifestResponse = service.createOrUpdate(manifest);
|
||||
|
||||
assertEquals(0, manifestResponse.getError().size());
|
||||
verify(privilegeUtilService, times(1)).canWriteManifest(manifest);
|
||||
verify(repo, times(0)).save(any(Manifest.class));
|
||||
verify(repo, times(1)).findById(1L);
|
||||
assertEquals(manifestResponseString, manifestResponse.getManifest().convertToString());
|
||||
@@ -258,7 +265,8 @@ class ManifestServiceTest {
|
||||
@DisplayName("should update manifest")
|
||||
void shouldUpdateManifest() throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, kubernetesManifestService,
|
||||
portalEventPublisher, privilegeUtilService, manifestAuditService, userService, mapDiffUtil);
|
||||
portalEventPublisher, privilegeUtilService, manifestAuditService, userService, mapDiffUtil,
|
||||
authorizationFilter);
|
||||
String manifestRequestString = "{\"id\": 1,\"name\":\"test\", \"environment\": \"dev\",\"metadata\": {\"repo\":\"test\",\"language\":\"Java\",\"dataSensitivity\":\"PII_SPI\",\"logCriticality\":\"AccessLogs\",\"disasterRecovery\":\"True\"}, \"team\": {\"name\": \"Infra\"},\"infraVertical\": \"lending\"}";
|
||||
String manifestResponseString = "{\"version\":null,\"id\":1,\"name\":\"test\",\"environment\":\"dev\",\"dynamicConfiguration\":null,\"metadata\":{\"repo\":\"test\",\"language\":\"Java\",\"dataSensitivity\":\"PII_SPI\",\"logCriticality\":\"AccessLogs\",\"disasterRecovery\":\"True\"},\"extraResources\":null,\"notification\":null,\"deployment\":null,\"infraVertical\":\"lending\",\"environmentVariables\":[],\"team\":{\"name\":\"Infra\"}}";
|
||||
String currentManifestString = "{\"id\":1,\"name\":\"test\",\"environment\":\"dev\",\"infraVertical\":\"lending\",\"team\":{\"name\":\"CBP\"}}";
|
||||
@@ -267,7 +275,6 @@ class ManifestServiceTest {
|
||||
|
||||
when(repo.findById(manifest.getId())).thenReturn(Optional.of(currentManifest));
|
||||
when(repo.save(any(Manifest.class))).thenReturn(manifest);
|
||||
when(privilegeUtilService.canWriteManifest(any(Manifest.class))).thenReturn(true);
|
||||
when(userService.getCurrentUsername()).thenReturn(currentUser);
|
||||
doNothing().when(portalEventPublisher)
|
||||
.publishManifestUpdatedEvent(any(Manifest.class), eq(currentUser),
|
||||
@@ -276,7 +283,6 @@ class ManifestServiceTest {
|
||||
ManifestResponse manifestResponse = service.createOrUpdate(manifest);
|
||||
|
||||
assertEquals(0, manifestResponse.getError().size());
|
||||
verify(privilegeUtilService, times(1)).canWriteManifest(manifest);
|
||||
verify(repo, times(1)).save(any(Manifest.class));
|
||||
verify(repo, times(1)).findById(1L);
|
||||
assertEquals(manifestResponseString, manifestResponse.getManifest().convertToString());
|
||||
@@ -286,7 +292,8 @@ class ManifestServiceTest {
|
||||
@DisplayName("Save Manifest Without Secret - Add Secret")
|
||||
void shouldSaveManifestWithoutSecretWhileProvidingSecret() throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, vaultService, null,
|
||||
portalEventPublisher, privilegeUtilService, manifestAuditService, userService, null);
|
||||
portalEventPublisher, privilegeUtilService, manifestAuditService, userService, null,
|
||||
authorizationFilter);
|
||||
String oldManifestString = "{\"id\":1,\"name\":\"test\",\"environment\":\"dev\",\"infraVertical\":\"lending\",\"team\":{\"name\":\"Infra\"}}";
|
||||
Manifest newManifest = stringToManifest(oldManifestString);
|
||||
Manifest expectedManifest = stringToManifest(oldManifestString);
|
||||
@@ -298,7 +305,7 @@ class ManifestServiceTest {
|
||||
expectedManifest.addRedactedValuesToSecrets();
|
||||
|
||||
when(privilegeUtilService.canWriteSecret(any(Manifest.class))).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteSuperSecret()).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteSuperSecret(newManifest)).thenReturn(true);
|
||||
when(vaultService.writeConfig(eq(newManifest.getSecretVaultPath()),
|
||||
any(Map.class))).thenReturn(getVaultResponse());
|
||||
when(vaultService.updateConfig(eq(newManifest.getSuperSecretVaultPath()), any(Map.class),
|
||||
@@ -321,7 +328,7 @@ class ManifestServiceTest {
|
||||
@DisplayName("Save Manifest without secret - Remove secret")
|
||||
void SaveManifestWithoutSecretShouldRemoveSecret() throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, null, portalEventPublisher,
|
||||
privilegeUtilService, manifestAuditService, userService, null);
|
||||
privilegeUtilService, manifestAuditService, userService, null, authorizationFilter);
|
||||
String manifestString = "{\"id\": 1,\"name\":\"test\", \"environment\": \"dev\", \"team\": {\"name\": \"Infra\"},\"infraVertical\": \"lending\"}";
|
||||
Manifest oldManifest = stringToManifest(manifestString);
|
||||
Manifest newManifest = stringToManifest(manifestString);
|
||||
@@ -341,7 +348,7 @@ class ManifestServiceTest {
|
||||
@Test
|
||||
@DisplayName("throw Runtime Exception when manifest is not found")
|
||||
void throwRuntimeExceptionWhenManifestIsNotFound() {
|
||||
service = new ManifestService(null, repo, null, null, null, null, null, null, null, null);
|
||||
service = new ManifestService(null, repo, null, null, null, null, null, null, null, null, null);
|
||||
|
||||
var appName = "appName";
|
||||
var environment = "environment";
|
||||
@@ -359,7 +366,7 @@ class ManifestServiceTest {
|
||||
@Test
|
||||
@DisplayName("should set deployment status if isDeployed flag is true")
|
||||
void shouldSetDeploymentStatusIfIsDeployedFlagIsTrue() throws IOException {
|
||||
service = new ManifestService(null, repo, null, null, null, null, null, null, null, null);
|
||||
service = new ManifestService(null, repo, null, null, null, null, null, null, null, null, null);
|
||||
var appName = "appName";
|
||||
var environment = "environment";
|
||||
var manifest = getManifest();
|
||||
@@ -378,7 +385,7 @@ class ManifestServiceTest {
|
||||
@Test
|
||||
@DisplayName("should set deployment status if isDeployed flag is false")
|
||||
void shouldSetDeploymentStatusIfIsDeployedFlagIsFalse() {
|
||||
service = new ManifestService(null, repo, null, null, null, null, null, null, null, null);
|
||||
service = new ManifestService(null, repo, null, null, null, null, null, null, null, null, null);
|
||||
|
||||
var appName = "appName";
|
||||
var environment = "environment";
|
||||
@@ -399,17 +406,16 @@ class ManifestServiceTest {
|
||||
@DisplayName("should create manifest with API Gateways containing gateway along with external auth and rate limit")
|
||||
void shouldCreateApiGateways() throws IOException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, kubernetesManifestService,
|
||||
null, privilegeUtilService, manifestAuditService, userService, mapDiffUtil);
|
||||
null, privilegeUtilService, manifestAuditService, userService, mapDiffUtil,
|
||||
null);
|
||||
Manifest manifest = readFileToManifest("fixtures/manifest/dev-testapp-api-gateways-1.json");
|
||||
String expectedApiGatewayResponse = readFile(
|
||||
"fixtures/manifest/expected_output/dev-testapp-api-gateway-1.json");
|
||||
|
||||
when(userService.getCurrentUsername()).thenReturn(currentUser);
|
||||
when(repo.save(any(Manifest.class))).thenReturn(manifest);
|
||||
when(privilegeUtilService.canWriteManifest(any(Manifest.class))).thenReturn(true);
|
||||
|
||||
ManifestResponse manifestResponse = service.createOrUpdate(manifest);
|
||||
verify(privilegeUtilService, times(1)).canWriteManifest(manifest);
|
||||
verify(repo, times(1)).save(any(Manifest.class));
|
||||
String actualResponse = manifestResponse.getManifest().getDeployment().convertToJson().toString();
|
||||
assertEquals(expectedApiGatewayResponse, actualResponse);
|
||||
@@ -434,7 +440,7 @@ class ManifestServiceTest {
|
||||
@DisplayName("Should Copy Manifest")
|
||||
void ShouldReturnManifestOnValidRequest() throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, null, null,
|
||||
privilegeUtilService, null, userService, null);
|
||||
privilegeUtilService, null, userService, null, null);
|
||||
String manifestString = "{\"id\": 1,\"name\":\"test\", \"environment\": \"dev\", \"team\": {\"name\": \"Infra\"},\"infraVertical\": \"lending\"}";
|
||||
String CopyRequestString = "{\"name\": \"test-copy\",\"teamName\":\"CBP\",\"environment\":\"qa\", \"manifestId\": 1}";
|
||||
var expectedManifest = getManifest("test-copy", "qa", "CBP");
|
||||
@@ -443,13 +449,14 @@ class ManifestServiceTest {
|
||||
Manifest manifest = stringToManifest(manifestString);
|
||||
|
||||
when(repo.findById(1L)).thenReturn(Optional.of(manifest));
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable()).thenReturn(true);
|
||||
when(privilegeUtilService.canReadManifest("dev")).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteManifest("qa")).thenReturn(true);
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable(argThat(new ManifestMatcher(manifest)))).thenReturn(true);
|
||||
when(privilegeUtilService.canReadManifest("Infra", "dev")).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteManifest("CBP", "qa")).thenReturn(true);
|
||||
Manifest copyManifest = service.copyManifest(cloneManifestRequest);
|
||||
|
||||
verify(repo, times(1)).findById(1L);
|
||||
verify(privilegeUtilService, times(1)).canSubstituteEnvironmentVariable();
|
||||
verify(privilegeUtilService, times(1)).canSubstituteEnvironmentVariable(
|
||||
argThat(new ManifestMatcher(manifest)));
|
||||
assertEquals(expectedManifest.convertToString(), copyManifest.convertToString());
|
||||
}
|
||||
|
||||
@@ -458,7 +465,7 @@ class ManifestServiceTest {
|
||||
void ShouldReturnManifestOnValidRequestWithCopyEnvironmentVariable()
|
||||
throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, null, null,
|
||||
privilegeUtilService, null, userService, null);
|
||||
privilegeUtilService, null, userService, null, null);
|
||||
String manifestString = "{\"id\": 1,\"name\":\"test\", \"environment\": \"dev\", \"team\": {\"name\": \"Infra\"},\"infraVertical\": \"lending\"}";
|
||||
String CopyRequestString = "{\"name\": \"test-copy\",\"teamName\":\"CBP\",\"environment\":\"qa\", \"manifestId\": 1, \"copyEnvVariables\": true}";
|
||||
var expectedManifest = getManifest("test-copy", "qa", "CBP");
|
||||
@@ -469,13 +476,13 @@ class ManifestServiceTest {
|
||||
expectedManifest.setEnvironmentVariables(getEnvironmentVariableOutputWithSha());
|
||||
|
||||
when(repo.findById(1L)).thenReturn(Optional.of(manifest));
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable()).thenReturn(true);
|
||||
when(privilegeUtilService.canReadManifest("dev")).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteManifest("qa")).thenReturn(true);
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable(argThat(new ManifestMatcher(manifest)))).thenReturn(true);
|
||||
when(privilegeUtilService.canReadManifest("Infra", "dev")).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteManifest("CBP", "qa")).thenReturn(true);
|
||||
Manifest copyManifest = service.copyManifest(cloneManifestRequest);
|
||||
|
||||
verify(repo, times(1)).findById(1L);
|
||||
verify(privilegeUtilService, times(1)).canSubstituteEnvironmentVariable();
|
||||
verify(privilegeUtilService, times(1)).canSubstituteEnvironmentVariable(argThat(new ManifestMatcher(manifest)));
|
||||
assertEquals(expectedManifest.convertToString(), copyManifest.convertToString());
|
||||
}
|
||||
|
||||
@@ -484,7 +491,7 @@ class ManifestServiceTest {
|
||||
void ShouldThrowErrorOnValidRequestWithCopyEnvironmentVariableOnProd()
|
||||
throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, null, null,
|
||||
privilegeUtilService, null, userService, null);
|
||||
privilegeUtilService, null, userService, null, null);
|
||||
String manifestString = "{\"id\": 1,\"name\":\"test\", \"environment\": \"prod\", \"team\": {\"name\": \"Infra\"},\"infraVertical\": \"lending\"}";
|
||||
String CopyRequestString = "{\"name\": \"test-copy\",\"teamName\":\"CBP\",\"environment\":\"qa\", \"manifestId\": 1, \"copyEnvVariables\": true}";
|
||||
CloneManifestRequest cloneManifestRequest = OBJECT_MAPPER.readValue(CopyRequestString,
|
||||
@@ -492,7 +499,7 @@ class ManifestServiceTest {
|
||||
Manifest manifest = stringToManifest(manifestString);
|
||||
|
||||
when(repo.findById(1L)).thenReturn(Optional.of(manifest));
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable()).thenReturn(true);
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable(manifest)).thenReturn(true);
|
||||
assertThrows(RuntimeException.class, () -> service.copyManifest(cloneManifestRequest));
|
||||
}
|
||||
|
||||
@@ -500,7 +507,7 @@ class ManifestServiceTest {
|
||||
@DisplayName("should copy outbound connection")
|
||||
void shouldCopyOutboundConnection() throws JsonProcessingException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, null, null,
|
||||
privilegeUtilService, null, userService, null);
|
||||
privilegeUtilService, null, userService, null, null);
|
||||
String CopyRequestString = "{\"name\": \"test-copy\",\"teamName\":\"CBP\",\"environment\":\"qa\", \"manifestId\": 1, \"copyOutbound\": true}";
|
||||
CloneManifestRequest cloneManifestRequest = OBJECT_MAPPER.readValue(CopyRequestString,
|
||||
CloneManifestRequest.class);
|
||||
@@ -514,22 +521,21 @@ class ManifestServiceTest {
|
||||
expectedManifest.getDeployment().getData().put("isVpaEnabled", false);
|
||||
|
||||
when(repo.findById(1L)).thenReturn(Optional.of(manifest));
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable()).thenReturn(true);
|
||||
when(privilegeUtilService.canReadManifest("dev")).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteManifest("qa")).thenReturn(true);
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable(argThat(new ManifestMatcher(manifest)))).thenReturn(true);
|
||||
when(privilegeUtilService.canReadManifest("Infra", "dev")).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteManifest("CBP", "qa")).thenReturn(true);
|
||||
Manifest copyManifest = service.copyManifest(cloneManifestRequest);
|
||||
|
||||
verify(repo, times(1)).findById(1L);
|
||||
verify(privilegeUtilService, times(1)).canSubstituteEnvironmentVariable();
|
||||
verify(privilegeUtilService, times(1)).canSubstituteEnvironmentVariable(argThat(new ManifestMatcher(manifest)));
|
||||
assertEquals(expectedManifest.convertToString(), copyManifest.convertToString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should replace all expected variables with default values")
|
||||
void shouldReplaceWithDefaultFields() throws IOException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, null, null,
|
||||
privilegeUtilService, null, userService, null);
|
||||
privilegeUtilService, null, userService, null, null);
|
||||
String CopyRequestString = "{\"name\": \"test-copy\",\"teamName\":\"CBP\",\"environment\":\"qa\", \"manifestId\": 1, \"copyOutbound\": true}";
|
||||
CloneManifestRequest cloneManifestRequest = OBJECT_MAPPER.readValue(CopyRequestString,
|
||||
CloneManifestRequest.class);
|
||||
@@ -538,13 +544,13 @@ class ManifestServiceTest {
|
||||
"fixtures/manifest/expected_output/dev-testapp-copy-1.json");
|
||||
|
||||
when(repo.findById(1L)).thenReturn(Optional.of(manifest));
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable()).thenReturn(true);
|
||||
when(privilegeUtilService.canReadManifest("dev")).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteManifest("qa")).thenReturn(true);
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable(argThat(new ManifestMatcher(manifest)))).thenReturn(true);
|
||||
when(privilegeUtilService.canReadManifest("Infra", "dev")).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteManifest("CBP", "qa")).thenReturn(true);
|
||||
Manifest copyManifest = service.copyManifest(cloneManifestRequest);
|
||||
|
||||
verify(repo, times(1)).findById(1L);
|
||||
verify(privilegeUtilService, times(1)).canSubstituteEnvironmentVariable();
|
||||
verify(privilegeUtilService, times(1)).canSubstituteEnvironmentVariable(argThat(new ManifestMatcher(manifest)));
|
||||
assertEquals(expectedManifest.convertToString(), copyManifest.convertToString());
|
||||
}
|
||||
|
||||
@@ -552,7 +558,7 @@ class ManifestServiceTest {
|
||||
@DisplayName("should replace all expected variables with default values for extra resources")
|
||||
void shouldReplaceWithDefaultFieldsForExtraResources() throws IOException {
|
||||
service = new ManifestService(OBJECT_MAPPER, repo, null, null, null, null,
|
||||
privilegeUtilService, null, userService, null);
|
||||
privilegeUtilService, null, userService, null, null);
|
||||
String CopyRequestString = "{\"name\": \"test-copy\",\"teamName\":\"CBP\",\"environment\":\"qa\", \"manifestId\": 1, \"copyOutbound\": true}";
|
||||
CloneManifestRequest cloneManifestRequest = OBJECT_MAPPER.readValue(CopyRequestString,
|
||||
CloneManifestRequest.class);
|
||||
@@ -561,15 +567,33 @@ class ManifestServiceTest {
|
||||
"fixtures/manifest/expected_output/dev-testapp-copy-2.json");
|
||||
|
||||
when(repo.findById(1L)).thenReturn(Optional.of(manifest));
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable()).thenReturn(true);
|
||||
when(privilegeUtilService.canReadManifest("dev")).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteManifest("qa")).thenReturn(true);
|
||||
when(privilegeUtilService.canSubstituteEnvironmentVariable(argThat(new ManifestMatcher(manifest)))).thenReturn(true);
|
||||
when(privilegeUtilService.canReadManifest("Infra", "dev")).thenReturn(true);
|
||||
when(privilegeUtilService.canWriteManifest("CBP", "qa")).thenReturn(true);
|
||||
Manifest copyManifest = service.copyManifest(cloneManifestRequest);
|
||||
|
||||
verify(repo, times(1)).findById(1L);
|
||||
verify(privilegeUtilService, times(1)).canSubstituteEnvironmentVariable();
|
||||
verify(privilegeUtilService, times(1)).canSubstituteEnvironmentVariable(argThat(new ManifestMatcher(manifest)));
|
||||
JSONAssert.assertEquals(expectedManifest.convertToString(),
|
||||
copyManifest.convertToString(), false);
|
||||
}
|
||||
}
|
||||
|
||||
static class ManifestMatcher implements ArgumentMatcher<Manifest> {
|
||||
private final Manifest expectedManifest;
|
||||
|
||||
public ManifestMatcher(Manifest expectedManifest) {
|
||||
this.expectedManifest = expectedManifest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Manifest manifest) {
|
||||
if (expectedManifest == null || manifest == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return expectedManifest.getName().equals(manifest.getName()) &&
|
||||
expectedManifest.getEnvironment().equals(manifest.getEnvironment());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,12 +121,14 @@ public class ApprovalRequestServiceImplTest {
|
||||
when(repo.findPendingByRequestId(requestApproval.getId())).thenReturn(
|
||||
Optional.of(requestApproval));
|
||||
when(teamService.findByUserId(user1.getId())).thenReturn(List.of(team1));
|
||||
when(privilegeUtilService.canApproveChangeRequests()).thenReturn(true);
|
||||
when(privilegeUtilService.canApproveChangeRequests(manifest)).thenReturn(true);
|
||||
when(repo.save(toBeSavedRequestApproval)).thenReturn(toBeSavedRequestApproval);
|
||||
when(repo.findAllPendingByRequestTypeAndRequestId(RequestType.CHANGE_REQUEST.code,
|
||||
requestApproval.getRequestId())).thenReturn(singletonList(new ApprovalRequest()));
|
||||
when(manifestRepository.findById(1L)).thenReturn(Optional.of(manifest));
|
||||
|
||||
service = new ApprovalRequestServiceImpl(repo, teamService, null, null, null, null,
|
||||
|
||||
service = new ApprovalRequestServiceImpl(repo, teamService, manifestRepository, null, null, null,
|
||||
privilegeUtilService, null);
|
||||
|
||||
final var approvedRequest = service.allowApproveRequest(requestApproval.getId(),
|
||||
@@ -135,7 +137,7 @@ public class ApprovalRequestServiceImplTest {
|
||||
|
||||
verify(repo).findPendingByRequestId(requestApproval.getId());
|
||||
verify(teamService).findByUserId(user1.getId());
|
||||
verify(privilegeUtilService).canApproveChangeRequests();
|
||||
verify(privilegeUtilService).canApproveChangeRequests(manifest);
|
||||
verify(repo).save(toBeSavedRequestApproval);
|
||||
verify(repo).findAllPendingByRequestTypeAndRequestId(RequestType.CHANGE_REQUEST.code,
|
||||
requestApproval.getRequestId());
|
||||
|
||||
Reference in New Issue
Block a user