Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS has been phased out. To see alternatives please check here

Skip to content
Snippets Groups Projects
Commit feb2f248 authored by Flavio Ferraioli's avatar Flavio Ferraioli
Browse files

Merge branch 'release' into 'main'

Release

See merge request simpl/simpl-open/development/iaa/simpl-cloud-gateway!51
parents 0f68b12b 3c7aaff4
No related branches found
No related tags found
2 merge requests!52Feature/align,!51Release
Pipeline #230831 canceled
Showing
with 175 additions and 106 deletions
### Description
Description of the MR
### Merge Request Checklists
- [ ] I have already covered the unit testing
- [ ] Deployment documentation has been updated
### Optional Additional notes
# SIMPL Cloud Gateway - Tier 1
Mediates the traffic from the Internet to the tier 1 agent components of a participant agent (Keycloak, Onboarding, Users Roles).
\ No newline at end of file
...@@ -4,18 +4,19 @@ metadata: ...@@ -4,18 +4,19 @@ metadata:
name: {{ .Chart.Name }}-env-configmap name: {{ .Chart.Name }}-env-configmap
data: data:
{{- if eq .Values.global.profile "authority" }} {{- if eq .Values.global.profile "authority" }}
ONBOARDING_URL: "{{ .Values.microservices.onboardingUrl }}" ONBOARDING_URL: "{{ .Values.onboardingUrl }}"
EJBCA_URL: "{{ .Values.microservices.ejbcaUrl }}" EJBCA_URL: "{{ .Values.ejbcaUrl }}"
IDENTITY_PROVIDER_URL: {{ .Values.microservices.identityProviderUrl }} IDENTITY_PROVIDER_URL: "{{ .Values.identityProviderUrl }}"
SAP_URL: "{{ .Values.microservices.securityAttributesProviderUrl }}" SAP_URL: "{{ .Values.securityAttributesProviderUrl }}"
{{- end }} {{- end }}
SPRING_PROFILES_ACTIVE: {{ .Values.global.profile }} SPRING_PROFILES_ACTIVE: "{{ .Values.global.profile }}"
GATEWAY_URL: "{{- include "microservices.backend.url" . }}" GATEWAY_URL: "{{- include "microservices.backend.url" . }}"
USERSROLES_URL: "{{ .Values.microservices.usersRolesUrl }}" USERSROLES_URL: "{{ .Values.usersRolesUrl }}"
KEYCLOAK_URL: "{{ .Values.microservices.keycloakUrl }}" KEYCLOAK_URL: "{{ .Values.keycloakUrl }}"
AUTHENTICATION_PROVIDER_URL: "{{ .Values.authenticationProviderUrl }}"
CORS_ALLOWED_HEADERS: Access-Control-Allow-Headers,Access-Control-Allow-Credentials,Access-Control-Allow-Origin,Access-Control-Allow-Methods,Keep-Alive,User-Agent,Content-Type,Authorization,Tenant,Channel,Platform,Set-Cookie,geolocation,x-mobility-mode,device,Cache-Control,X-Request-With,Accept,Origin CORS_ALLOWED_HEADERS: Access-Control-Allow-Headers,Access-Control-Allow-Credentials,Access-Control-Allow-Origin,Access-Control-Allow-Methods,Keep-Alive,User-Agent,Content-Type,Authorization,Tenant,Channel,Platform,Set-Cookie,geolocation,x-mobility-mode,device,Cache-Control,X-Request-With,Accept,Origin
CORS_ALLOWED_ORIGINS: {{ .Values.global.cors.allowOrigin }} CORS_ALLOWED_ORIGINS: "{{ .Values.global.cors.allowOrigin }}"
...@@ -4,55 +4,4 @@ metadata: ...@@ -4,55 +4,4 @@ metadata:
name: simpl-cloud-gateway-spring-configmap name: simpl-cloud-gateway-spring-configmap
data: data:
application.yaml: | application.yaml: |
{{- with .Values.springRoutes }} {{ .Values.appConfig | toYaml | indent 4 }}
spring: \ No newline at end of file
cloud:
gateway:
routes:
{{ toYaml . | indent 12 }}
{{- end }}
{{- with .Values.swaggerUrls }}
springdoc:
swagger-ui:
urls:
{{ toYaml . | indent 10 }}
{{ end }}
{{- if .Values.routes }}
{{- if or .Values.routes.publicUrls .Values.routes.deniedUrls .Values.routes.rbac }}
routes:
{{- if .Values.routes.publicUrls }}
public-urls:
{{- range .Values.routes.publicUrls }}
- path: {{ .path }}
{{- if .method }}
method: {{ .method }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.routes.deniedUrls }}
denied-urls:
{{- range .Values.routes.deniedUrls }}
- path: {{ .path }}
{{- if .method }}
method: {{ .method }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.routes.rbac }}
rbac:
{{- range .Values.routes.rbac }}
- path: {{ .path }}
{{- if .method }}
method: {{ .method }}
{{- end }}
{{- if .roles }}
roles:
{{- range .roles }}
- {{ . }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
\ No newline at end of file
...@@ -92,13 +92,13 @@ envFrom: ...@@ -92,13 +92,13 @@ envFrom:
- configMapRef: - configMapRef:
name: simpl-cloud-gateway-env-configmap name: simpl-cloud-gateway-env-configmap
microservices:
usersRolesUrl: http://users-roles.{{ .Release.Namespace }}.svc.cluster.local:8080 usersRolesUrl: http://users-roles.{{ .Release.Namespace }}.svc.cluster.local:8080
securityAttributesProviderUrl: http://security-attributes-provider.{{ .Release.Namespace }}.svc.cluster.local:8080 securityAttributesProviderUrl: http://security-attributes-provider.{{ .Release.Namespace }}.svc.cluster.local:8080
keycloakUrl: http://keycloak.{{ .Release.Namespace }}.svc.cluster.local keycloakUrl: http://keycloak.{{ .Release.Namespace }}.svc.cluster.local
onboardingUrl: http://onboarding.{{ .Release.Namespace }}.svc.cluster.local:8080 onboardingUrl: http://onboarding.{{ .Release.Namespace }}.svc.cluster.local:8080
ejbcaUrl: http://ejbca-community-helm.{{ .Release.Namespace }}.svc.cluster.local:30080 ejbcaUrl: http://ejbca-community-helm.{{ .Release.Namespace }}.svc.cluster.local:30080
identityProviderUrl: http://identity-provider.{{ .Release.Namespace }}.svc.cluster.local:8080 identityProviderUrl: http://identity-provider.{{ .Release.Namespace }}.svc.cluster.local:8080
authenticationProviderUrl: http://authentication-provider.{{ .Release.Namespace }}.svc.cluster.local:8080
nodeSelector: {} nodeSelector: {}
......
PROJECT_VERSION_NUMBER="0.6.1" PROJECT_VERSION_NUMBER="0.7.0"
\ No newline at end of file \ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.aruba.simpl</groupId> <groupId>com.aruba.simpl</groupId>
<artifactId>simpl-parent</artifactId> <artifactId>simpl-parent</artifactId>
<version>0.6.0</version> <version>0.7.0</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
......
package com.aruba.simpl.gatewayserver.configurations;
import com.aruba.simpl.common.logging.LoggingFilter;
import java.util.List;
import java.util.Optional;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class LoggingConfig {
@Bean
public LoggingFilter loggingFilterBean(RouteConfig routeConfig) {
return new LoggingFilter(Optional.ofNullable(routeConfig)
.map(RouteConfig::logging)
.map(RouteConfig.Logging::business)
.orElse(List.of()));
}
}
package com.aruba.simpl.gatewayserver.configurations; package com.aruba.simpl.gatewayserver.configurations;
import com.aruba.simpl.common.logging.LoggingRule;
import java.util.List; import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "routes") @ConfigurationProperties(prefix = "routes")
public record RouteConfig(List<Rule> publicUrls, List<Rule> deniedUrls, List<Rule> rbac) {} public record RouteConfig(List<Rule> publicUrls, List<Rule> deniedUrls, List<Rule> rbac, Logging logging) {
public record Logging(List<LoggingRule> business) {}
}
package com.aruba.simpl.gatewayserver.configurations; package com.aruba.simpl.gatewayserver.configurations;
import com.aruba.simpl.gatewayserver.matchers.KeycloakMatcher; import com.aruba.simpl.gatewayserver.matchers.KeycloakMatcher;
import com.aruba.simpl.gatewayserver.matchers.MtlsMatcher;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.function.UnaryOperator;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value; import org.springdoc.core.properties.AbstractSwaggerUiConfigProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
...@@ -30,11 +31,11 @@ public class SecurityConfig { ...@@ -30,11 +31,11 @@ public class SecurityConfig {
private final RouteConfig routeConfig; private final RouteConfig routeConfig;
private final List<ServerWebExchangeMatcher> publicMatchers; private final List<ServerWebExchangeMatcher> publicMatchers;
private final List<ServerWebExchangeMatcher> deniedMatchers; private final List<ServerWebExchangeMatcher> deniedMatchers;
private final String agentType; private final SwaggerConfig swaggerConfig;
public SecurityConfig(RouteConfig routeConfig, @Value("${keycloak.app.realm}") String agentType) { public SecurityConfig(RouteConfig routeConfig, SwaggerConfig swaggerConfig) {
this.routeConfig = routeConfig; this.routeConfig = routeConfig;
this.agentType = agentType; this.swaggerConfig = swaggerConfig;
this.publicMatchers = buildPublicUrls(); this.publicMatchers = buildPublicUrls();
this.deniedMatchers = buildMatchers(routeConfig.deniedUrls()); this.deniedMatchers = buildMatchers(routeConfig.deniedUrls());
} }
...@@ -66,6 +67,8 @@ public class SecurityConfig { ...@@ -66,6 +67,8 @@ public class SecurityConfig {
} }
routeConfig.rbac().forEach(rule -> configureRbacRule(request, rule)); routeConfig.rbac().forEach(rule -> configureRbacRule(request, rule));
request.matchers(new MtlsMatcher()).denyAll();
request.pathMatchers("/private/**") request.pathMatchers("/private/**")
.authenticated() .authenticated()
.anyExchange() .anyExchange()
...@@ -99,20 +102,16 @@ public class SecurityConfig { ...@@ -99,20 +102,16 @@ public class SecurityConfig {
} }
private void addSwaggersPublicUrls(List<ServerWebExchangeMatcher> publicUrl) { private void addSwaggersPublicUrls(List<ServerWebExchangeMatcher> publicUrl) {
if (Objects.equals("authority", agentType)) { UnaryOperator<String> extractBasePath = v3Url -> v3Url.replaceAll("^([^\"]*/)(?=v3)", "$1");
addSwaggerPublicUrl(publicUrl, "sap-api");
addSwaggerPublicUrl(publicUrl, "identity-api");
addSwaggerPublicUrl(publicUrl, "onboarding-api");
}
addSwaggerPublicUrl(publicUrl, "user-api");
}
private void addSwaggerPublicUrl(List<ServerWebExchangeMatcher> publicUrl, String servicePrefix) { swaggerConfig.urls().stream()
publicUrl.add(ServerWebExchangeMatchers.pathMatchers( .map(AbstractSwaggerUiConfigProperties.SwaggerUrl::getUrl)
.map(v3url -> ServerWebExchangeMatchers.pathMatchers(
HttpMethod.GET, HttpMethod.GET,
"public/%s/swagger-ui.html".formatted(servicePrefix), "%s/swagger-ui.html".formatted(extractBasePath.apply(v3url)),
"public/%s/swagger-ui/**".formatted(servicePrefix), "%s/swagger-ui/**".formatted(extractBasePath.apply(v3url)),
"public/%s/v3/api-docs/**".formatted(servicePrefix))); "%s/**".formatted(v3url)))
.forEach(publicUrl::add);
} }
private List<ServerWebExchangeMatcher> buildMatchers(List<Rule> rules) { private List<ServerWebExchangeMatcher> buildMatchers(List<Rule> rules) {
......
package com.aruba.simpl.gatewayserver.configurations;
import java.util.Set;
import org.springdoc.core.properties.AbstractSwaggerUiConfigProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "springdoc.swagger-ui")
public record SwaggerConfig(Set<AbstractSwaggerUiConfigProperties.SwaggerUrl> urls) {}
package com.aruba.simpl.gatewayserver.filters;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@Component
public class LoggingFilter implements WebFilter {
private final com.aruba.simpl.common.logging.LoggingFilter loggingFilter;
public LoggingFilter(com.aruba.simpl.common.logging.LoggingFilter loggingFilter) {
this.loggingFilter = loggingFilter;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange).then(loggingFilter.filter(exchange));
}
}
...@@ -32,6 +32,12 @@ spring: ...@@ -32,6 +32,12 @@ spring:
- Path=/*/identity-api/** - Path=/*/identity-api/**
filters: filters:
- StripPrefix=2 - StripPrefix=2
- id: authentication-provider
uri: ${authentication-provider.url}
predicates:
- Path=/*/auth-api/**
filters:
- StripPrefix=2
- id: ocsp - id: ocsp
uri: ${ejbca.url} uri: ${ejbca.url}
predicates: predicates:
...@@ -62,6 +68,8 @@ springdoc: ...@@ -62,6 +68,8 @@ springdoc:
name: Users & Roles Service name: Users & Roles Service
- url: /public/identity-api/v3/api-docs - url: /public/identity-api/v3/api-docs
name: Identity Provider Service name: Identity Provider Service
- url: /public/auth-api/v3/api-docs
name: Authentication Provider Service
keycloak: keycloak:
app: app:
...@@ -78,18 +86,6 @@ routes: ...@@ -78,18 +86,6 @@ routes:
- method: GET - method: GET
path: "/actuator/**" path: "/actuator/**"
# TODO Protect with NOTARY role
- method: GET
path: "/public/onboarding-api/onboarding-template/*"
- method: PUT
path: "/public/onboarding-api/onboarding-template/*"
- method: POST
path: "/public/onboarding-api/credential-request"
# TODO Protect with APPLICANT and NOTARY roles
- method: GET
path: "/public/onboarding-api/onboarding-request"
- method: POST - method: POST
path: "/ocsp" path: "/ocsp"
- method: GET - method: GET
...@@ -97,7 +93,12 @@ routes: ...@@ -97,7 +93,12 @@ routes:
- method: GET - method: GET
path: "/crl/**" path: "/crl/**"
- method: GET
path: "/public/user-api/credential/public-key"
denied-urls:
- method: GET
path: "*/auth-api/keypair"
rbac: rbac:
### CLI ### CLI
...@@ -105,11 +106,11 @@ routes: ...@@ -105,11 +106,11 @@ routes:
roles: roles:
- NOTARY - NOTARY
- T1UAR_M - T1UAR_M
- path: "private/sap-api/cli*" - path: "private/sap-api/cli/*"
roles: roles:
- NOTARY - NOTARY
- T1UAR_M - T1UAR_M
- path: "private/user-api/cli*" - path: "private/user-api/cli/*"
roles: roles:
- NOTARY - NOTARY
- T1UAR_M - T1UAR_M
...@@ -133,6 +134,45 @@ routes: ...@@ -133,6 +134,45 @@ routes:
- path: "private/onboarding-api/mime-type/*" - path: "private/onboarding-api/mime-type/*"
roles: roles:
- T2IAA_M - T2IAA_M
- path: "/private/onboarding-api/credential-request"
method: POST
roles:
- NOTARY
- T1UAR_M
- path: "/private/onboarding-api/onboarding-request"
method: GET
roles:
- APPLICANT
- NOTARY
- path: "/private/onboarding-api/onboarding-request"
method: POST
roles:
- APPLICANT
- NOTARY
- path: "/private/onboarding-api/onboarding-request"
method: PATCH
roles:
- APPLICANT
- NOTARY
- path: "/private/onboarding-api/onboarding-request/*"
method: GET
roles:
- APPLICANT
- NOTARY
- path: "/private/onboarding-api/onboarding-request/*/id-document"
method: PATCH
roles:
- APPLICANT
- NOTARY
- path: "/private/onboarding-api/onboarding-request/*/document/*"
method: GET
roles:
- APPLICANT
- NOTARY
- path: "/private/onboarding-api/onboarding-request/*/expiration-timeframe"
method: PATCH
roles:
- NOTARY
### ###
- path: "private/identity-api/participant/*" - path: "private/identity-api/participant/*"
method: PUT method: PUT
......
users-roles: users-roles:
url: http://localhost:8081 url: http://localhost:8081
onboarding:
url: http://localhost:8084
sap: sap:
url: http://localhost:8082 url: http://localhost:8082
identity-provider: identity-provider:
url: http://localhost:8083 url: http://localhost:8083
onboarding:
url: http://localhost:8084
authentication-provider:
url: http://localhost:8085
gateway: gateway:
url: http://localhost:${server.port} url: http://localhost:${server.port}
keycloak: keycloak:
......
...@@ -14,13 +14,20 @@ spring: ...@@ -14,13 +14,20 @@ spring:
- Path=/*/user-api/** - Path=/*/user-api/**
filters: filters:
- StripPrefix=2 - StripPrefix=2
- id: authentication-provider
uri: ${authentication-provider.url}
predicates:
- Path=/*/auth-api/**
filters:
- StripPrefix=2
springdoc: springdoc:
swagger-ui: swagger-ui:
urls: urls:
- url: /public/user-api/v3/api-docs - url: /public/user-api/v3/api-docs
name: Users & Roles Service name: Users & Roles Service
- url: /public/auth-api/v3/api-docs
name: Authentication Provider Service
keycloak: keycloak:
app: app:
realm: participant realm: participant
...@@ -36,6 +43,10 @@ routes: ...@@ -36,6 +43,10 @@ routes:
- method: GET - method: GET
path: "/actuator/**" path: "/actuator/**"
denied-urls:
- method: GET
path: "*/auth-api/keypair"
rbac: rbac:
- path: "private/user-api/agent/identity-attributes" - path: "private/user-api/agent/identity-attributes"
method: GET method: GET
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment