mirror of
https://github.com/mvvasilev/personal-finances.git
synced 2025-04-19 14:19:52 +03:00
Remove api gateway
This commit is contained in:
parent
d7c3cbbc69
commit
c7750e1662
9 changed files with 0 additions and 359 deletions
|
@ -1,21 +0,0 @@
|
||||||
PROFILE= production/development
|
|
||||||
|
|
||||||
AUTHENTIK_CLIENT_ID= authentik oauth2 client id
|
|
||||||
AUTHENTIK_CLIENT_SECRET= authentik oauth2 client secret
|
|
||||||
AUTHENTIK_ISSUER_URL= authentik issuer url ( dev: https://auth.mvvasilev.dev/application/o/personal-finances/ )
|
|
||||||
AUTHENTIK_BACK_CHANNEL_LOGOUT_URL= authentik back channel logout url ( dev: https://auth.mvvasilev.dev/application/o/personal-finances/end-session/ )
|
|
||||||
|
|
||||||
GATEWAY_URI= http://localhost:8080
|
|
||||||
CORE_API_URI= http://localhost:8081
|
|
||||||
STATEMENTS_API_URI= http://localhost:8082
|
|
||||||
WIDGETS_API_URI= http://localhost:8083
|
|
||||||
FRONTEND_URI= http://localhost:5173
|
|
||||||
|
|
||||||
SSL_ENABLED= true if generated an ssl cert ( keytool -genkeypair -alias local -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore local.p12 -validity 3650 )
|
|
||||||
SSL_KEY_STORE_TYPE= type of key store ( PKCS12 )
|
|
||||||
SSL_KEY_STORE= where to find the key store ( classpath:keystore/local.p12 if located in main/resources/keystore/local.p12 )
|
|
||||||
SSL_KEY_STORE_PASSWORD= the password for the key store
|
|
||||||
SSL_KEY_ALIAS= the key store alias
|
|
||||||
|
|
||||||
REDIS_HOST= the address of the redis host
|
|
||||||
REDIS_PORT= the port of redis ( 6379 by default )
|
|
37
pefi-api-gateway/.gitignore
vendored
37
pefi-api-gateway/.gitignore
vendored
|
@ -1,37 +0,0 @@
|
||||||
HELP.md
|
|
||||||
.gradle
|
|
||||||
build/
|
|
||||||
!gradle/wrapper/gradle-wrapper.jar
|
|
||||||
!**/src/main/**/build/
|
|
||||||
!**/src/test/**/build/
|
|
||||||
|
|
||||||
### STS ###
|
|
||||||
.apt_generated
|
|
||||||
.classpath
|
|
||||||
.factorypath
|
|
||||||
.project
|
|
||||||
.settings
|
|
||||||
.springBeans
|
|
||||||
.sts4-cache
|
|
||||||
bin/
|
|
||||||
!**/src/main/**/bin/
|
|
||||||
!**/src/test/**/bin/
|
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
|
||||||
.idea
|
|
||||||
*.iws
|
|
||||||
*.iml
|
|
||||||
*.ipr
|
|
||||||
out/
|
|
||||||
!**/src/main/**/out/
|
|
||||||
!**/src/test/**/out/
|
|
||||||
|
|
||||||
### NetBeans ###
|
|
||||||
/nbproject/private/
|
|
||||||
/nbbuild/
|
|
||||||
/dist/
|
|
||||||
/nbdist/
|
|
||||||
/.nb-gradle/
|
|
||||||
|
|
||||||
### VS Code ###
|
|
||||||
.vscode/
|
|
|
@ -1,7 +0,0 @@
|
||||||
FROM eclipse-temurin:21-jdk-alpine
|
|
||||||
|
|
||||||
COPY ./build/libs/pefi-api-gateway-0.0.1-SNAPSHOT.jar app.jar
|
|
||||||
|
|
||||||
EXPOSE 8081
|
|
||||||
|
|
||||||
ENTRYPOINT exec java $JAVA_OPTS -jar /app.jar $ARGS
|
|
|
@ -1,44 +0,0 @@
|
||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id 'org.springframework.boot' version '3.2.0'
|
|
||||||
id 'io.spring.dependency-management' version '1.1.4'
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'dev.mvvasilev'
|
|
||||||
version = '0.0.1-SNAPSHOT'
|
|
||||||
|
|
||||||
java {
|
|
||||||
sourceCompatibility = '21'
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven { url 'https://repo.spring.io/milestone' }
|
|
||||||
}
|
|
||||||
|
|
||||||
ext {
|
|
||||||
set('springCloudVersion', "2023.0.0")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
|
|
||||||
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
|
|
||||||
implementation 'org.springframework.session:spring-session-core'
|
|
||||||
implementation 'org.springframework.session:spring-session-data-redis'
|
|
||||||
|
|
||||||
implementation 'io.lettuce:lettuce-core'
|
|
||||||
|
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
|
||||||
testImplementation 'org.springframework.security:spring-security-test'
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencyManagement {
|
|
||||||
imports {
|
|
||||||
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named('test') {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
rootProject.name = 'pefi-api-gateway'
|
|
|
@ -1,15 +0,0 @@
|
||||||
package dev.mvvasilev.gateway;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
|
||||||
import org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession;
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
public class ApiGatewayApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(ApiGatewayApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,133 +0,0 @@
|
||||||
package dev.mvvasilev.gateway;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
|
||||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseCookie;
|
|
||||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
|
||||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
|
||||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
|
||||||
import org.springframework.security.jackson2.SecurityJackson2Modules;
|
|
||||||
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
|
|
||||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestCustomizers;
|
|
||||||
import org.springframework.security.oauth2.client.web.server.DefaultServerOAuth2AuthorizationRequestResolver;
|
|
||||||
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizationRequestResolver;
|
|
||||||
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
|
|
||||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
|
||||||
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
|
|
||||||
import org.springframework.security.web.server.authentication.HttpStatusServerEntryPoint;
|
|
||||||
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationEntryPoint;
|
|
||||||
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
|
|
||||||
import org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession;
|
|
||||||
import org.springframework.web.server.WebSession;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebFluxSecurity
|
|
||||||
@EnableRedisWebSession
|
|
||||||
public class SecurityConfiguration implements BeanClassLoaderAware {
|
|
||||||
|
|
||||||
public static final String IS_LOGGED_IN_COOKIE = "isLoggedIn";
|
|
||||||
|
|
||||||
@Value("${spring.security.oauth2.client.provider.authentik.back-channel-logout-url}")
|
|
||||||
private String backChannelLogoutUrl;
|
|
||||||
|
|
||||||
@Value("${server.reactive.session.cookie.max-age}")
|
|
||||||
private Duration springSessionDuration;
|
|
||||||
|
|
||||||
@Value("${server.reactive.session.cookie.path}")
|
|
||||||
private String springSessionPath;
|
|
||||||
|
|
||||||
private ClassLoader loader;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http, ServerOAuth2AuthorizationRequestResolver resolver) {
|
|
||||||
http
|
|
||||||
.httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
|
|
||||||
.csrf(ServerHttpSecurity.CsrfSpec::disable)
|
|
||||||
.authorizeExchange(c -> {
|
|
||||||
c.pathMatchers("/**").permitAll();
|
|
||||||
c.pathMatchers("/api/**").authenticated();
|
|
||||||
})
|
|
||||||
.oauth2Login(c -> {
|
|
||||||
c.authenticationSuccessHandler((exchange, auth) -> {
|
|
||||||
ServerHttpResponse response = exchange.getExchange().getResponse();
|
|
||||||
|
|
||||||
response.getCookies().set(
|
|
||||||
IS_LOGGED_IN_COOKIE,
|
|
||||||
ResponseCookie.from(IS_LOGGED_IN_COOKIE)
|
|
||||||
.value("true")
|
|
||||||
.path(springSessionPath)
|
|
||||||
.maxAge(springSessionDuration)
|
|
||||||
.httpOnly(false)
|
|
||||||
.secure(false)
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
|
|
||||||
return new RedirectServerAuthenticationSuccessHandler("/").onAuthenticationSuccess(exchange, auth);
|
|
||||||
});
|
|
||||||
|
|
||||||
c.authorizationRequestResolver(resolver);
|
|
||||||
})
|
|
||||||
.logout(c -> {
|
|
||||||
c.logoutSuccessHandler((ex, a) -> {
|
|
||||||
ServerHttpResponse response = ex.getExchange().getResponse();
|
|
||||||
|
|
||||||
response.setStatusCode(HttpStatus.SEE_OTHER);
|
|
||||||
response.getHeaders().set("Location", backChannelLogoutUrl);
|
|
||||||
response.getCookies().remove("JSESSIONID");
|
|
||||||
response.getCookies().remove("SESSION");
|
|
||||||
response.getCookies().set(
|
|
||||||
IS_LOGGED_IN_COOKIE,
|
|
||||||
ResponseCookie.from(IS_LOGGED_IN_COOKIE)
|
|
||||||
.value("false")
|
|
||||||
.path(springSessionPath)
|
|
||||||
.maxAge(springSessionDuration)
|
|
||||||
.httpOnly(false)
|
|
||||||
.secure(false)
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
|
|
||||||
return ex.getExchange().getSession().flatMap(WebSession::invalidate);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.exceptionHandling(e -> e.authenticationEntryPoint(new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED)));
|
|
||||||
|
|
||||||
return http.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ServerOAuth2AuthorizationRequestResolver pkceResolver(ReactiveClientRegistrationRepository repo) {
|
|
||||||
var resolver = new DefaultServerOAuth2AuthorizationRequestResolver(repo);
|
|
||||||
resolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce());
|
|
||||||
return resolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ServerAuthenticationEntryPoint authenticationEntryPoint() {
|
|
||||||
return new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
|
|
||||||
return new GenericJackson2JsonRedisSerializer(objectMapper());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObjectMapper objectMapper() {
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
|
||||||
mapper.registerModules(SecurityJackson2Modules.getModules(this.loader));
|
|
||||||
return mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
|
||||||
this.loader = classLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
spring:
|
|
||||||
cloud:
|
|
||||||
gateway:
|
|
||||||
routes:
|
|
||||||
- id: statements-api
|
|
||||||
uri: ${STATEMENTS_API_URI}
|
|
||||||
order: 1
|
|
||||||
predicates:
|
|
||||||
- Path=/api/statements/**
|
|
||||||
filters:
|
|
||||||
- RewritePath=/api/(?<segment>.*), /$\{segment}
|
|
||||||
- TokenRelay=
|
|
||||||
- id: widgets-api
|
|
||||||
uri: ${WIDGETS_API_URI}
|
|
||||||
order: 2
|
|
||||||
predicates:
|
|
||||||
- Path=/api/widgets/**
|
|
||||||
filters:
|
|
||||||
- RewritePath=/api/(?<segment>.*), /$\{segment}
|
|
||||||
- TokenRelay=
|
|
||||||
- id: core-api
|
|
||||||
uri: ${CORE_API_URI}
|
|
||||||
order: 3
|
|
||||||
predicates:
|
|
||||||
- Path=/api/**
|
|
||||||
filters:
|
|
||||||
- RewritePath=/api/(?<segment>.*), /$\{segment}
|
|
||||||
- TokenRelay=
|
|
||||||
- id: spa
|
|
||||||
order: 4
|
|
||||||
uri: ${FRONTEND_URI}
|
|
||||||
predicates:
|
|
||||||
- Path=/**
|
|
|
@ -1,68 +0,0 @@
|
||||||
logging:
|
|
||||||
level:
|
|
||||||
web: trace
|
|
||||||
core: trace
|
|
||||||
spring:
|
|
||||||
profiles:
|
|
||||||
active: ${PROFILE}
|
|
||||||
data:
|
|
||||||
redis:
|
|
||||||
host: ${REDIS_HOST}
|
|
||||||
port: ${REDIS_PORT}
|
|
||||||
security:
|
|
||||||
oauth2:
|
|
||||||
client:
|
|
||||||
registration:
|
|
||||||
authentik:
|
|
||||||
client-id: ${AUTHENTIK_CLIENT_ID}
|
|
||||||
client-secret: ${AUTHENTIK_CLIENT_SECRET}
|
|
||||||
redirect-uri: "{baseUrl}/login/oauth2/code/authentik"
|
|
||||||
provider:
|
|
||||||
authentik:
|
|
||||||
back-channel-logout-url: ${AUTHENTIK_BACK_CHANNEL_LOGOUT_URL} # spring doesn't support back-channel logouts by default
|
|
||||||
issuer-uri: ${AUTHENTIK_ISSUER_URL}
|
|
||||||
cloud:
|
|
||||||
gateway:
|
|
||||||
set-status:
|
|
||||||
original-status-header-name: Original-Status
|
|
||||||
routes:
|
|
||||||
- id: statements-api
|
|
||||||
uri: ${STATEMENTS_API_URI}
|
|
||||||
order: 1
|
|
||||||
predicates:
|
|
||||||
- Path=/api/statements/**
|
|
||||||
filters:
|
|
||||||
- RewritePath=/api/(?<segment>.*), /$\{segment}
|
|
||||||
- TokenRelay=
|
|
||||||
- id: widgets-api
|
|
||||||
uri: ${WIDGETS_API_URI}
|
|
||||||
order: 2
|
|
||||||
predicates:
|
|
||||||
- Path=/api/widgets/**
|
|
||||||
filters:
|
|
||||||
- RewritePath=/api/(?<segment>.*), /$\{segment}
|
|
||||||
- TokenRelay=
|
|
||||||
- id: core-api
|
|
||||||
uri: ${CORE_API_URI}
|
|
||||||
order: 3
|
|
||||||
predicates:
|
|
||||||
- Path=/api/**
|
|
||||||
filters:
|
|
||||||
- RewritePath=/api/(?<segment>.*), /$\{segment}
|
|
||||||
- TokenRelay=
|
|
||||||
|
|
||||||
server:
|
|
||||||
ssl:
|
|
||||||
enabled: ${SSL_ENABLED}
|
|
||||||
key-store-type: ${SSL_KEY_STORE_TYPE}
|
|
||||||
key-store: ${SSL_KEY_STORE}
|
|
||||||
key-store-password: ${SSL_KEY_STORE_PASSWORD}
|
|
||||||
key-alias: ${SSL_KEY_ALIAS}
|
|
||||||
reactive:
|
|
||||||
session:
|
|
||||||
cookie:
|
|
||||||
http-only: true
|
|
||||||
secure: true
|
|
||||||
same-site: lax
|
|
||||||
max-age: 30m
|
|
||||||
path: "/"
|
|
Loading…
Add table
Reference in a new issue