diff --git a/gate-core/src/main/groovy/com/netflix/spinnaker/gate/services/OesAuthorizationService.groovy b/gate-core/src/main/groovy/com/netflix/spinnaker/gate/services/OesAuthorizationService.groovy index 07faf0f175..759d592191 100644 --- a/gate-core/src/main/groovy/com/netflix/spinnaker/gate/services/OesAuthorizationService.groovy +++ b/gate-core/src/main/groovy/com/netflix/spinnaker/gate/services/OesAuthorizationService.groovy @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RequestHeader import org.springframework.web.bind.annotation.RequestParam -@FeignClient(name = "OES", url = '${services.platform.baseUrl}') +@FeignClient(name = "OES", url = '${services.platform.baseUrl}', dismiss404 = true) interface OesAuthorizationService { @PutMapping(value = "/platformservice/v2/usergroups/importAndCache", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) diff --git a/gate-web/src/main/java/com/opsmx/spinnaker/gate/rbac/ApplicationFeatureRbac.java b/gate-web/src/main/java/com/opsmx/spinnaker/gate/rbac/ApplicationFeatureRbac.java index 4598cfbe30..3046c549a0 100644 --- a/gate-web/src/main/java/com/opsmx/spinnaker/gate/rbac/ApplicationFeatureRbac.java +++ b/gate-web/src/main/java/com/opsmx/spinnaker/gate/rbac/ApplicationFeatureRbac.java @@ -18,6 +18,8 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; +import com.netflix.spinnaker.fiat.model.Authorization; +import com.netflix.spinnaker.fiat.shared.FiatPermissionEvaluator; import com.netflix.spinnaker.gate.model.PermissionModel; import com.netflix.spinnaker.gate.services.OesAuthorizationService; import com.netflix.spinnaker.gate.services.PermissionService; @@ -27,14 +29,13 @@ import com.opsmx.spinnaker.gate.exception.InvalidResourceIdException; import com.opsmx.spinnaker.gate.exception.XSpinnakerUserHeaderMissingException; import jakarta.servlet.http.HttpServletRequest; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; +import java.util.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; @Slf4j @@ -46,6 +47,8 @@ public class ApplicationFeatureRbac { @Autowired private PermissionService permissionService; + @Autowired private FiatPermissionEvaluator permissionEvaluator; + public static final List runtime_access = new ArrayList<>(); public static final List applicationFeatureRbacEndpoints = new ArrayList<>(); public static final List endpointsWithApplicationId = new ArrayList<>(); @@ -77,19 +80,24 @@ public void authorizeUserForFeatureVisibility(String userName) { log.debug("Start of the authorizeUserForFeatureVisibility"); log.debug("validating the user for FeatureVisibility"); if (permissionService.isAdmin(userName)) { - log.info("{} is admin, Hence not validating with ISD", userName); + log.info("{} user is admin, Hence not validating with ISD", userName); return; } - isFeatureVisibility = - Boolean.parseBoolean( - oesAuthorizationService - .isFeatureVisibility(userName, RbacFeatureType.APP.name(), userName) - .getBody() - .get("isEnabled")); - log.info("is feature visibility enabled : {}", isFeatureVisibility); - if (!isFeatureVisibility) { + + ResponseEntity> response = + oesAuthorizationService.isFeatureVisibility(userName, RbacFeatureType.APP.name(), userName); + int statusCode = response.getStatusCodeValue(); + isFeatureVisibility = Boolean.parseBoolean(response.getBody().get("isEnabled")); + + if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) { + log.info("Feature visibility check ended with status code: {}", statusCode); + } else if (statusCode == HttpStatus.FORBIDDEN.value() || !isFeatureVisibility) { + log.warn( + "Access forbidden for user {} on feature type {}", + userName, + RbacFeatureType.APP.description); throw new AccessForbiddenException( - "You do not have permission for the feature type : " + RbacFeatureType.APP.description); + "You do not have permission for the feature type: " + RbacFeatureType.APP.description); } log.debug("End of the authorizeUserForFeatureVisibility"); } @@ -99,7 +107,7 @@ public void authorizeUserForApplicationId( log.debug("Start of the authorizeUserForApplicationId"); log.debug("validating the user for ApplicationId"); if (permissionService.isAdmin(username)) { - log.info("{} is admin, Hence not validating with ISD", username); + log.info("{} user is admin,Hence not validating with ISD", username); return; } HttpMethod method = HttpMethod.valueOf(httpMethod); @@ -110,13 +118,23 @@ public void authorizeUserForApplicationId( switch (method.name()) { case "GET": - permission = - oesAuthorizationService - .fetchPermissions(username, RbacFeatureType.APP.name(), applicationId, username) - .getBody(); - log.info("permissions for the GET API : {}", permission); - if (permission == null - || !permission.getPermissions().contains(PermissionEnum.view.name())) { + ResponseEntity response = + oesAuthorizationService.fetchPermissions( + username, RbacFeatureType.APP.name(), applicationId, username); + int statusCode = response.getStatusCodeValue(); + permission = response.getBody(); + + if ((statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) + && permissionEvaluator.hasPermission( + username, applicationId, RbacFeatureType.APP.name(), Authorization.EXECUTE)) { + log.info( + "Authorized user for Application ID with status code :{}, {}", + applicationId, + statusCode); + log.info("permissions for the GET API : {}", permission); + } else if (permission == null + || !permission.getPermissions().contains(PermissionEnum.view.name()) + || statusCode == HttpStatus.FORBIDDEN.value()) { throw new AccessForbiddenException( YOU_DO_NOT_HAVE + PermissionEnum.view.name() @@ -205,24 +223,29 @@ public void authorizeUserForServiceId(String username, String endpointUrl, Strin switch (method.name()) { case "GET": - isAuthorized = - Boolean.parseBoolean( - oesAuthorizationService - .isAuthorizedUser( - username, - PermissionEnum.view.name(), - serviceId, - null, - null, - null, - null, - null, - null, - username) - .getBody() - .get("isEnabled")); - log.info("is authorized for the service Id GET API: {}, {}", serviceId, isAuthorized); - if (isAuthorized == null || !isAuthorized) { + ResponseEntity> response = + oesAuthorizationService.isAuthorizedUser( + username, + PermissionEnum.view.name(), + serviceId, + null, + null, + null, + null, + null, + null, + username); + isAuthorized = Boolean.parseBoolean(response.getBody().get("isEnabled")); + int statusCode = response.getStatusCodeValue(); + + if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) { + log.info( + "Authorized user for the service Id GET API with status code: {}, {}", + serviceId, + statusCode); + } else if (isAuthorized == null + || !isAuthorized + || statusCode == HttpStatus.FORBIDDEN.value()) { throw new AccessForbiddenException( YOU_DO_NOT_HAVE + PermissionEnum.view.name() @@ -298,24 +321,29 @@ public void authorizeUserForPipelineId(String username, String endpointUrl, Stri switch (method.name()) { case "GET": - isAuthorized = - Boolean.parseBoolean( - oesAuthorizationService - .isAuthorizedUser( - username, - PermissionEnum.view.name(), - null, - pipelineId, - null, - null, - null, - null, - null, - username) - .getBody() - .get("isEnabled")); - log.info("is authorized for the pipeline Id GET API: {}, {}", pipelineId, isAuthorized); - if (isAuthorized == null || !isAuthorized) { + ResponseEntity> response = + oesAuthorizationService.isAuthorizedUser( + username, + PermissionEnum.view.name(), + null, + pipelineId, + null, + null, + null, + null, + null, + username); + isAuthorized = Boolean.parseBoolean(response.getBody().get("isEnabled")); + int statusCode = response.getStatusCodeValue(); + + if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) { + log.info( + "authorized user for the pipeline Id GET API with status code: {}, {}", + pipelineId, + statusCode); + } else if (isAuthorized == null + || !isAuthorized + || statusCode == HttpStatus.FORBIDDEN.value()) { throw new AccessForbiddenException( YOU_DO_NOT_HAVE + PermissionEnum.view.name() @@ -393,24 +421,29 @@ public void authorizeUserForGateId(String username, String endpointUrl, String h switch (method.name()) { case "GET": - isAuthorized = - Boolean.parseBoolean( - oesAuthorizationService - .isAuthorizedUser( - username, - PermissionEnum.view.name(), - null, - null, - gateId, - null, - null, - null, - null, - username) - .getBody() - .get("isEnabled")); - log.info("is authorized for the gate Id GET API: {}, {}", gateId, isAuthorized); - if (isAuthorized == null || !isAuthorized) { + ResponseEntity> response = + oesAuthorizationService.isAuthorizedUser( + username, + PermissionEnum.view.name(), + null, + null, + gateId, + null, + null, + null, + null, + username); + isAuthorized = Boolean.parseBoolean(response.getBody().get("isEnabled")); + int statusCode = response.getStatusCodeValue(); + + if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) { + log.info( + "authorized user for the gate Id GET API with staus code: {}, {}", + gateId, + statusCode); + } else if (isAuthorized == null + || !isAuthorized + || statusCode == HttpStatus.FORBIDDEN.value()) { throw new AccessForbiddenException( YOU_DO_NOT_HAVE + PermissionEnum.view.name() @@ -492,25 +525,29 @@ public void authorizeUserForApprovalGateId( switch (method.name()) { case "GET": - isAuthorized = - Boolean.parseBoolean( - oesAuthorizationService - .isAuthorizedUser( - username, - PermissionEnum.view.name(), - null, - null, - null, - approvalGateId, - null, - null, - null, - username) - .getBody() - .get("isEnabled")); - log.info( - "is authorized for the approval gate Id GET API: {}, {}", approvalGateId, isAuthorized); - if (isAuthorized == null || !isAuthorized) { + ResponseEntity> response = + oesAuthorizationService.isAuthorizedUser( + username, + PermissionEnum.view.name(), + null, + null, + null, + approvalGateId, + null, + null, + null, + username); + isAuthorized = Boolean.parseBoolean(response.getBody().get("isEnabled")); + int statusCode = response.getStatusCodeValue(); + + if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) { + log.info( + "authorized user for the approval gate Id GET API: {}, {}", + approvalGateId, + statusCode); + } else if (isAuthorized == null + || !isAuthorized + || statusCode == HttpStatus.FORBIDDEN.value()) { throw new AccessForbiddenException( YOU_DO_NOT_HAVE + PermissionEnum.view.name() @@ -586,27 +623,29 @@ public void authorizeUserForApprovalGateInstanceId( switch (method.name()) { case "GET": - isAuthorized = - Boolean.parseBoolean( - oesAuthorizationService - .isAuthorizedUser( - username, - PermissionEnum.view.name(), - null, - null, - null, - null, - approvalGateInstanceId, - null, - null, - username) - .getBody() - .get("isEnabled")); - log.info( - "is authorized for the approval gate instance Id GET API: {}, {}", - approvalGateInstanceId, - isAuthorized); - if (isAuthorized == null || !isAuthorized) { + ResponseEntity> response = + oesAuthorizationService.isAuthorizedUser( + username, + PermissionEnum.view.name(), + null, + null, + null, + null, + approvalGateInstanceId, + null, + null, + username); + isAuthorized = Boolean.parseBoolean(response.getBody().get("isEnabled")); + int statusCode = response.getStatusCodeValue(); + + if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) { + log.info( + "authorized user for the approval gate instance Id GET API: {}, {}", + approvalGateInstanceId, + statusCode); + } else if (isAuthorized == null + || !isAuthorized + || statusCode == HttpStatus.FORBIDDEN.value()) { throw new AccessForbiddenException( YOU_DO_NOT_HAVE + PermissionEnum.view.name() @@ -682,27 +721,29 @@ public void authorizeUserForApprovalPolicyId( switch (method.name()) { case "GET": - isAuthorized = - Boolean.parseBoolean( - oesAuthorizationService - .isAuthorizedUser( - username, - PermissionEnum.view.name(), - null, - null, - null, - null, - null, - approvalPolicyId, - null, - username) - .getBody() - .get("isEnabled")); - log.info( - "is authorized for the approval policy Id GET API: {}, {}", - approvalPolicyId, - isAuthorized); - if (isAuthorized == null || !isAuthorized) { + ResponseEntity> response = + oesAuthorizationService.isAuthorizedUser( + username, + PermissionEnum.view.name(), + null, + null, + null, + null, + null, + approvalPolicyId, + null, + username); + isAuthorized = Boolean.parseBoolean(response.getBody().get("isEnabled")); + int statusCode = response.getStatusCodeValue(); + + if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) { + log.info( + "authorized user for the approval policy Id GET API with staus code: {}, {}", + approvalPolicyId, + statusCode); + } else if (isAuthorized == null + || !isAuthorized + || statusCode == HttpStatus.FORBIDDEN.value()) { throw new AccessForbiddenException( YOU_DO_NOT_HAVE + PermissionEnum.view.name() @@ -791,24 +832,29 @@ public void authorizeUserForApprovalGateTrigger(HttpServletRequest request) { log.info("authorizing the endpoint : {}", endpointUrl); - isAuthorized = - Boolean.parseBoolean( - oesAuthorizationService - .isAuthorizedUser( - username, - PermissionEnum.runtime_access.name(), - null, - null, - null, - approvalGateId, - null, - null, - null, - username) - .getBody() - .get("isEnabled")); - - if (isAuthorized == null || !isAuthorized) { + ResponseEntity> response = + oesAuthorizationService.isAuthorizedUser( + username, + PermissionEnum.runtime_access.name(), + null, + null, + null, + approvalGateId, + null, + null, + null, + username); + isAuthorized = Boolean.parseBoolean(response.getBody().get("isEnabled")); + int statusCode = response.getStatusCodeValue(); + + if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) { + log.info( + "authorized user for the approval custom gate trigger Id GET API with status code: {}, {}", + approvalGateId, + statusCode); + } else if (isAuthorized == null + || !isAuthorized + || statusCode == HttpStatus.FORBIDDEN.value()) { throw new AccessForbiddenException( YOU_DO_NOT_HAVE + PermissionEnum.runtime_access.name() @@ -846,24 +892,29 @@ public void authorizeUserForPolicyGateTrigger(HttpServletRequest request, Object log.info("authorizing the endpoint : {}", endpointUrl); - isAuthorized = - Boolean.parseBoolean( - oesAuthorizationService - .isAuthorizedUser( - username, - PermissionEnum.runtime_access.name(), - null, - null, - null, - null, - null, - null, - appName, - username) - .getBody() - .get("isEnabled")); - - if (isAuthorized == null || !isAuthorized) { + ResponseEntity> response = + oesAuthorizationService.isAuthorizedUser( + username, + PermissionEnum.runtime_access.name(), + null, + null, + null, + null, + null, + null, + appName, + username); + isAuthorized = Boolean.parseBoolean(response.getBody().get("isEnabled")); + int statusCode = response.getStatusCodeValue(); + + if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) { + log.info( + "authorized user for the policy gate Id GET API with status code: {}, {}", + isAuthorized, + statusCode); + } else if (isAuthorized == null + || !isAuthorized + || statusCode == HttpStatus.FORBIDDEN.value()) { throw new AccessForbiddenException( YOU_DO_NOT_HAVE + PermissionEnum.runtime_access.name() @@ -898,24 +949,29 @@ public void authorizeUserForVerificationAndTestVerificationGateTrigger( log.info("authorizing the endpoint : {}", endpointUrl); - isAuthorized = - Boolean.parseBoolean( - oesAuthorizationService - .isAuthorizedUser( - username, - PermissionEnum.runtime_access.name(), - null, - null, - null, - null, - null, - null, - appName, - username) - .getBody() - .get("isEnabled")); - - if (isAuthorized == null || !isAuthorized) { + ResponseEntity> response = + oesAuthorizationService.isAuthorizedUser( + username, + PermissionEnum.runtime_access.name(), + null, + null, + null, + null, + null, + null, + appName, + username); + isAuthorized = Boolean.parseBoolean(response.getBody().get("isEnabled")); + int statusCode = response.getStatusCodeValue(); + + if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.OK.value()) { + log.info( + "is authorized for the verification gate Id GET API with status code: {}, {}", + isAuthorized, + statusCode); + } else if (isAuthorized == null + || !isAuthorized + || statusCode == HttpStatus.FORBIDDEN.value()) { throw new AccessForbiddenException( YOU_DO_NOT_HAVE + PermissionEnum.runtime_access.name()