From a20ee0542b2df7a33fc86c561617170fc9547457 Mon Sep 17 00:00:00 2001 From: Khanh Du Date: Mon, 21 Oct 2024 17:25:59 +0700 Subject: [PATCH] add security and swagger in inventory --- .env.sample | 9 +++- .../matcha/theme/matcha/login/login.ftl | 6 +-- inventory/pom.xml | 4 ++ .../com/fjb/inventory/config/CorsConfig.java | 25 +++++++++++ .../fjb/inventory/config/SecurityConfig.java | 44 +++++++++++++++++++ .../fjb/inventory/config/SwaggerConfig.java | 32 ++++++++++++++ .../src/main/resources/application.properties | 1 - inventory/src/main/resources/application.yml | 43 ++++++++++++++++++ sell-bff/src/main/resources/application.yaml | 7 +++ 9 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 inventory/src/main/java/com/fjb/inventory/config/CorsConfig.java create mode 100644 inventory/src/main/java/com/fjb/inventory/config/SecurityConfig.java create mode 100644 inventory/src/main/java/com/fjb/inventory/config/SwaggerConfig.java delete mode 100644 inventory/src/main/resources/application.properties create mode 100644 inventory/src/main/resources/application.yml diff --git a/.env.sample b/.env.sample index f23c6fa..9f2c74b 100644 --- a/.env.sample +++ b/.env.sample @@ -7,7 +7,7 @@ POSTGRES_PORT= SERVER_PORT= # Swagger UI -URLS= +URLS=[{ url: 'http://localhost:8081/product/v3/api-docs', name: 'Product' }, { url: 'http://localhost:8082/inventory/v3/api-docs', name: 'Inventory' }] # Start all service when run docker compose up COMPOSE_FILE=docker-compose.yml @@ -18,4 +18,9 @@ COMPOSE_FILE=docker-compose.yml # Product PRODUCT_DATASOURCE_URL= PRODUCT_DATA_USERNAME= -PRODUCT_DATA_PASSWORD= \ No newline at end of file +PRODUCT_DATA_PASSWORD= + +# Inventory +INVENTORY_DATASOURCE_URL= +INVENTORY_DATA_USERNAME= +INVENTORY_DATA_PASSWORD= \ No newline at end of file diff --git a/identity/themes/matcha/theme/matcha/login/login.ftl b/identity/themes/matcha/theme/matcha/login/login.ftl index 6e10ab0..bc22b64 100644 --- a/identity/themes/matcha/theme/matcha/login/login.ftl +++ b/identity/themes/matcha/theme/matcha/login/login.ftl @@ -19,11 +19,11 @@ } } + <#elseif section = "form"> -

Welcome to Matcha Store

diff --git a/inventory/pom.xml b/inventory/pom.xml index 5a14be0..e875079 100644 --- a/inventory/pom.xml +++ b/inventory/pom.xml @@ -38,6 +38,10 @@ org.springframework.boot spring-boot-starter-data-jpa + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + org.springframework.boot spring-boot-starter-validation diff --git a/inventory/src/main/java/com/fjb/inventory/config/CorsConfig.java b/inventory/src/main/java/com/fjb/inventory/config/CorsConfig.java new file mode 100644 index 0000000..779eda3 --- /dev/null +++ b/inventory/src/main/java/com/fjb/inventory/config/CorsConfig.java @@ -0,0 +1,25 @@ +package com.fjb.inventory.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class CorsConfig { + + @Value("${cors.allowed}") + private String corsAllowed; + + @Bean + public WebMvcConfigurer corsConfigure() { + return new WebMvcConfigurer() { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**").allowedMethods(corsAllowed) + .allowedOrigins(corsAllowed).allowedHeaders(corsAllowed); + } + }; + } +} diff --git a/inventory/src/main/java/com/fjb/inventory/config/SecurityConfig.java b/inventory/src/main/java/com/fjb/inventory/config/SecurityConfig.java new file mode 100644 index 0000000..c8ad432 --- /dev/null +++ b/inventory/src/main/java/com/fjb/inventory/config/SecurityConfig.java @@ -0,0 +1,44 @@ +package com.fjb.inventory.config; + +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +public class SecurityConfig { + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + + return http + .authorizeHttpRequests(auth -> auth + .anyRequest().permitAll()) + .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())) + .build(); + } + + @Bean + public JwtAuthenticationConverter jwtAuthenticationConverterForKeycloak() { + Converter> jwtGrantedAuthoritiesConverter = jwt -> { + Map> realmAccess = jwt.getClaim("realm_access"); + Collection roles = realmAccess.get("roles"); + return roles.stream() + .map(role -> new SimpleGrantedAuthority("ROLE_" + role)) + .collect(Collectors.toList()); + }; + + var jwtAuthenticationConverter = new JwtAuthenticationConverter(); + jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter); + + return jwtAuthenticationConverter; + } +} diff --git a/inventory/src/main/java/com/fjb/inventory/config/SwaggerConfig.java b/inventory/src/main/java/com/fjb/inventory/config/SwaggerConfig.java new file mode 100644 index 0000000..6eee7f7 --- /dev/null +++ b/inventory/src/main/java/com/fjb/inventory/config/SwaggerConfig.java @@ -0,0 +1,32 @@ +package com.fjb.inventory.config; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.security.OAuthFlow; +import io.swagger.v3.oas.annotations.security.OAuthFlows; +import io.swagger.v3.oas.annotations.security.OAuthScope; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import io.swagger.v3.oas.annotations.servers.Server; + +@OpenAPIDefinition( + info = @Info( + title = "Inventory Service API", + description = "Inventory API documentation", + version = "1.0" + ), + security = @SecurityRequirement(name = "oauth2_bearer"), + servers = { + @Server(url = "${server.servlet.context-path}", + description = "Default Server URL") + }) +@SecurityScheme(name = "oauth2_bearer", type = SecuritySchemeType.OAUTH2, + flows = @OAuthFlows( + authorizationCode = @OAuthFlow( + authorizationUrl = "${springdoc.oauthflow.authorization-url}", + tokenUrl = "${springdoc.oauthflow.token-url}", + scopes = {@OAuthScope(name = "openid", description = "openid") + }))) +public class SwaggerConfig { +} diff --git a/inventory/src/main/resources/application.properties b/inventory/src/main/resources/application.properties deleted file mode 100644 index 1cb2d06..0000000 --- a/inventory/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=inventory diff --git a/inventory/src/main/resources/application.yml b/inventory/src/main/resources/application.yml new file mode 100644 index 0000000..cd18d28 --- /dev/null +++ b/inventory/src/main/resources/application.yml @@ -0,0 +1,43 @@ +spring: + application: + name: inventory + datasource: + url: ${INVENTORY_DATASOURCE_URL} + username: ${INVENTORY_DATA_USERNAME} + password: ${INVENTORY_DATA_PASSWORD} + driver-class-name: org.postgresql.Driver + + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: false + database: postgresql + database-platform: org.hibernate.dialect.PostgreSQLDialect + open-in-view: false + + security: + oauth2: + resourceserver: + jwt: + issuer-uri: http://localhost:8080/realms/Matcha +springdoc: + oauthflow: + authorization-url: http://localhost:8080/realms/Matcha/protocol/openid-connect/auth + token-url: http://localhost:8080/realms/Matcha/protocol/openid-connect/token + swagger-ui: + oauth: + client-id: swagger + use-pkce-with-authorization-code-grant: true + packagesToScan: com.fjb.inventory + path: /swagger-ui + +server: + port: 8082 + servlet: + context-path: /inventory +cors: + allowed: "*" + diff --git a/sell-bff/src/main/resources/application.yaml b/sell-bff/src/main/resources/application.yaml index cb4e30a..574342b 100644 --- a/sell-bff/src/main/resources/application.yaml +++ b/sell-bff/src/main/resources/application.yaml @@ -52,6 +52,13 @@ spring: filters: - RewritePath=/api/(?.*), /$\{segment} - TokenRelay= + - id: inventory + uri: http://localhost:8082 + predicates: + - Path=/api/inventory/** + filters: + - RewritePath=/api/(?.*), /$\{segment} + - TokenRelay= - id: localhost uri: http://localhost:80 predicates: