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