Skip to content

Commit 7c28acc

Browse files
committed
Added some security changes
1 parent c6f288b commit 7c28acc

File tree

6 files changed

+102
-80
lines changed

6 files changed

+102
-80
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
## Lightweight RESTful API with Spring Boot, Keycloak, Docker, PostgreSQL, JPA, Lombok, Spotify plugin, OpenAPI, etc.
2+
## Lightweight RESTful API with Spring Boot 3, Keycloak 21, Docker, PostgreSQL, JPA, Lombok, OpenAPI, etc.
33

44
[![Build Status](https://travis-ci.org/OKaluzny/spring-boot-docker-postgres.svg?branch=master)](https://travis-ci.org/OKaluzny/spring-boot-docker-postgres)
55

docker-compose.yml

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,74 @@ version: '3.9'
33
# Define services
44
services:
55
# App backend service
6-
app:
6+
#app:
77
# This service depends on postgres db and keycloak auth. Start that first.
8-
depends_on:
9-
db:
10-
condition: service_healthy
11-
keycloak:
12-
condition: service_started
13-
image: spring-boot-keycloak-docker-postgres:latest
14-
build:
15-
context: ./
16-
dockerfile: "Dockerfile"
8+
# depends_on:
9+
# db:
10+
# condition: service_healthy
11+
#keycloak:
12+
# condition: service_started
13+
#image: spring-boot-keycloak-docker-postgres:latest
14+
#build:
15+
# context: ./
16+
# dockerfile: "Dockerfile"
1717
# Give the container the name web-app. You can change to something else.
18-
container_name: web-app
18+
#container_name: web-app
1919
# Forward the exposed port 8080 on the container to port 8080 on the host machine
20-
ports:
21-
- "8088:8080"
22-
networks:
23-
- backend
20+
#ports:
21+
# - "0.0.0.0:8088:8080/tcp"
22+
# - target: 8080
23+
# host_ip: 0.0.0.0
24+
# published: 8088
25+
#protocol: tcp
26+
#mode: host
27+
#ports:
28+
# - "8080:8080"
29+
#networks:
30+
# - backend
2431
# entrypoint: [ "java", "-Xms512m", "-Xmx1g", "-jar" ]
2532
# Database Service (Postgres)
26-
db:
27-
# Use the Docker Image postgres. This will pull the 14 version.
28-
image: postgres:14-alpine
33+
#db:
2934
# Give the container the name postgres-db. You can change to something else.
30-
container_name: postgres-db
31-
restart: always
35+
# container_name: postgres-db
36+
# Use the Docker Image postgres. This will pull the 14 version.
37+
#image: postgres:14-alpine
38+
#healthcheck:
39+
# test: [ "CMD", "pg_isready", "-q", "-d", "postgres", "-U", "root" ]
40+
#timeout: 45s
41+
#interval: 10s
42+
#retries: 10
43+
#restart: always
3244
# Set a volume some that database is not lost after shutting down the container.
3345
# I used the name postgres-data, but you can change it to something else.
34-
volumes:
35-
- postgres_data_keycloak:/var/lib/postgresql/data
36-
networks:
37-
- backend
46+
#volumes:
47+
# - postgres_data_keycloak:/var/lib/postgresql/data
48+
#networks:
49+
# - backend
50+
#network_mode: host
3851
# Maps port 5432 (localhost) to port 5432 on the container. You can change the ports to fix your needs.
39-
ports:
40-
- "5432:5432"
52+
#ports:
53+
# - "5432:5432"
4154
# Set up the username, password, and database name. You can change these values.
42-
environment:
43-
POSTGRES_USER: postgres
44-
POSTGRES_PASSWORD: postgres
45-
POSTGRES_DB: automobiles
46-
PGDATA: /var/lib/postgresql/data/pgdata
47-
healthcheck:
48-
test: "pg_isready -U postgres"
55+
#environment:
56+
# POSTGRES_USER: postgres
57+
#POSTGRES_PASSWORD: postgres
58+
#POSTGRES_DB: automobiles
59+
#PGDATA: /var/lib/postgresql/data/pgdata
4960
# Auth service
5061
keycloak:
51-
image: quay.io/keycloak/keycloak:22.0.1
5262
container_name: keycloak-auth
63+
image: quay.io/keycloak/keycloak:22.0.1
64+
#build:
65+
# context: .
66+
#args:
67+
# KEYCLOAK_VERSION: 22.0.1
5368
command:
5469
- "start-dev"
5570
ports:
5671
- "8180:8080"
5772
networks:
58-
- backend
73+
- keycloak
5974
environment:
6075
KEYCLOAK_ADMIN: admin
6176
KEYCLOAK_ADMIN_PASSWORD: password
@@ -82,13 +97,19 @@ services:
8297
POSTGRES_USER: keycloak
8398
POSTGRES_PASSWORD: password
8499
networks:
85-
- backend
100+
- keycloak
86101
healthcheck:
87-
test: "pg_isready -U keycloak"
102+
test: [ "CMD", "pg_isready", "-q", "-d", "postgres", "-U", "root" ]
103+
timeout: 45s
104+
interval: 10s
105+
retries: 10
88106

89107
networks:
90-
backend:
91-
name: app
108+
# backend:
109+
# name: app
110+
# driver: bridge
111+
keycloak:
112+
name: keycloak
92113
driver: bridge
93114

94115
volumes:

pom.xml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,7 @@
113113
</compilerArgs>
114114
</configuration>
115115
</plugin>
116-
117-
<plugin>
116+
<!-- <plugin>
118117
<groupId>io.fabric8</groupId>
119118
<artifactId>docker-maven-plugin</artifactId>
120119
<version>0.43.0</version>
@@ -137,7 +136,7 @@
137136
</configuration>
138137
</execution>
139138
</executions>
140-
</plugin>
139+
</plugin>-->
141140

142141
</plugins>
143142
</build>
Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
package com.kaluzny.demo.config;
22

33
import lombok.RequiredArgsConstructor;
4-
import org.springframework.beans.factory.annotation.Value;
54
import org.springframework.context.annotation.Bean;
65
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.http.HttpMethod;
7+
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
78
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
89
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
910
import org.springframework.security.core.authority.SimpleGrantedAuthority;
10-
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
11-
import org.springframework.security.oauth2.jwt.JwtDecoder;
12-
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
1311
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
1412
import org.springframework.security.web.SecurityFilterChain;
1513

@@ -20,38 +18,27 @@
2018
@Configuration
2119
@EnableWebSecurity
2220
//@EnableMethodSecurity
23-
@RequiredArgsConstructor
2421
class SecurityConfig {
2522

26-
@Value("${spring.security.oauth2.resource-server.jwt.jwk-set-uri}")
27-
private String jwkSetUri;
28-
2923
@Bean
3024
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
3125

3226
httpSecurity
3327
.authorizeHttpRequests(registry -> registry
34-
.requestMatchers("/api/**").hasRole("ADMIN")
28+
.requestMatchers(HttpMethod.GET,"/api/**").hasRole("USER")
29+
.requestMatchers(HttpMethod.POST,"/api/**").hasRole("PERSON")
3530
.anyRequest().authenticated()
3631
)
3732
.oauth2ResourceServer(oauth2Configurer -> oauth2Configurer
3833
.jwt(jwtConfigurer -> jwtConfigurer
3934
.jwtAuthenticationConverter(jwt -> {
40-
// Map<String, Collection<String>> realmAccess = jwt.getClaim("realm_access");
41-
Map<String, Collection<String>> realmAccess = jwt.getClaim("resource_access");
35+
Map<String, Collection<String>> realmAccess = jwt.getClaim("realm_access");
4236
Collection<String> roles = realmAccess.get("roles");
4337
var grantedAuthorities = roles.stream()
4438
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
4539
.collect(Collectors.toList());
4640
return new JwtAuthenticationToken(jwt, grantedAuthorities);
47-
}).decoder(jwtDecoder())));
41+
})));
4842
return httpSecurity.build();
4943
}
50-
51-
@Bean
52-
public JwtDecoder jwtDecoder() {
53-
return NimbusJwtDecoder
54-
.withJwkSetUri(jwkSetUri)
55-
.jwsAlgorithm(SignatureAlgorithm.RS256).build();
56-
}
5744
}

src/main/java/com/kaluzny/demo/web/AutomobileRestController.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import io.swagger.v3.oas.annotations.responses.ApiResponses;
1515
import io.swagger.v3.oas.annotations.tags.Tag;
1616
import jakarta.annotation.PostConstruct;
17+
import jakarta.annotation.security.RolesAllowed;
1718
import jakarta.validation.constraints.NotNull;
1819
import lombok.RequiredArgsConstructor;
1920
import lombok.extern.slf4j.Slf4j;
@@ -23,6 +24,7 @@
2324
import org.springframework.data.domain.Sort;
2425
import org.springframework.http.HttpStatus;
2526
import org.springframework.http.MediaType;
27+
import org.springframework.security.access.prepost.PreAuthorize;
2628
import org.springframework.transaction.annotation.Transactional;
2729
import org.springframework.web.bind.annotation.*;
2830

@@ -51,15 +53,15 @@ public void init() {
5153
repository.save(new Automobile(1L, "Ford", "Green", Instant.now(), Instant.now(), true, false));
5254
}
5355

54-
@Operation(summary = "Add a new Automobile", description = "endpoint for creating an entity", tags = {"Automobile"})
56+
/*@Operation(summary = "Add a new Automobile", description = "endpoint for creating an entity", tags = {"Automobile"})
5557
@ApiResponses(value = {
5658
@ApiResponse(responseCode = "201", description = "Automobile created"),
5759
@ApiResponse(responseCode = "400", description = "Invalid input"),
58-
@ApiResponse(responseCode = "409", description = "Automobile already exists")})
60+
@ApiResponse(responseCode = "409", description = "Automobile already exists")})*/
5961
@PostMapping("/automobiles")
6062
@ResponseStatus(HttpStatus.CREATED)
61-
//@PreAuthorize("hasRole('PERSON')")
62-
//@RolesAllowed("PERSON")
63+
@PreAuthorize("hasRole('ADMIN')")
64+
//@RolesAllowed("ADMIN")
6365
public Automobile saveAutomobile(
6466
@Parameter(description = "Automobile", required = true) @NotNull @RequestBody Automobile automobile) {
6567
log.info("saveAutomobile() - start: automobile = {}", automobile);
@@ -74,7 +76,8 @@ public Automobile saveAutomobile(
7476
content = @Content(array = @ArraySchema(schema = @Schema(implementation = Automobile.class))))})
7577
@GetMapping("/automobiles")
7678
@ResponseStatus(HttpStatus.OK)
77-
@Cacheable(value = "automobile")
79+
//@Cacheable(value = "automobile", sync = true)
80+
@PreAuthorize("hasRole('ADMIN')")
7881
public Collection<Automobile> getAllAutomobiles() {
7982
log.info("getAllAutomobiles() - start");
8083
Collection<Automobile> collection = repository.findAll();

src/main/resources/application.yml

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ spring:
44
name: App
55
profiles:
66
active: development
7-
main:
8-
allow-bean-definition-overriding: true
7+
#main:
8+
# allow-bean-definition-overriding: true
99
# Database
1010
datasource:
1111
driver-class-name: org.postgresql.Driver
1212
# For correct works with docker-compose, we need to change "localhost" to a service name, take from docker-compose.yml
13-
url: jdbc:postgresql://db:5432/automobiles
13+
#url: jdbc:postgresql://db:5432/automobiles
14+
url: jdbc:postgresql://localhost:5432/automobiles
1415
username: postgres
1516
password: postgres
1617
# JPA properties
@@ -20,31 +21,42 @@ spring:
2021
show-sql: true
2122
database: postgresql
2223
database-platform: org.hibernate.dialect.PostgreSQLDialect
23-
open-in-view: false
24-
generate-ddl: true
25-
# Keycloak Configuration
24+
#open-in-view: false
25+
#generate-ddl: true
26+
# Keycloak Configuration
2627
security:
2728
oauth2:
2829
resource-server:
2930
jwt:
3031
issuer-uri: http://localhost:8180/realms/automobile-realm
31-
jwk-set-uri: http://localhost:8180/realms/automobile-realm/protocol/openid-connect/certs
32-
32+
# Server configuration
33+
server:
34+
port: 8080 #set your port
35+
servlet:
36+
context-path: /demo
3337
# Logger configuration
3438
logging:
3539
pattern:
3640
console: "%d %-5level %logger : %msg%n"
3741
level:
3842
org.springframework: info
43+
org.springframework.security: debug
44+
org.springframework.security.oauth2: debug
3945
#org.hibernate: debug
40-
# Server configuration
41-
server:
42-
port: 8088 #set your port
43-
#servlet:
44-
# context-path: /demo
4546
# Swagger configuration
4647
springdoc:
4748
swagger-ui:
4849
path: /swagger-ui.html # swagger-ui custom path
4950
api-docs:
5051
path: /v3/api-docs.yaml
52+
# spring actuator
53+
management:
54+
endpoints:
55+
#enabled-by-default: true # If changed to false, you can enable separate functionality as indicated below
56+
#endpoint: # here
57+
# health:
58+
# enabled: true
59+
web:
60+
exposure:
61+
# exclude: "*"
62+
include: "*"

0 commit comments

Comments
 (0)