Skip to content

Commit 07cd01f

Browse files
authored
feat(observability): implement correlated logs and AOP-based auditing (#12)
* chore(deps): add logstash-logback-encoder dependency * feat(logging): implement structured, correlated JSON logging * feat(observability): add Loki and Alloy for centralized log collection * feat(otel): route distributed traces via grafana alloy * feat(observability): implement trace-to-log correlation * feat(security): implement AOP-based audit logging module * feat(security): apply AOP-based auditing to services * docs(readme): update main README for phase 5 completion
1 parent 895e4cf commit 07cd01f

File tree

31 files changed

+1202
-94
lines changed

31 files changed

+1202
-94
lines changed

.dockerignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Ignore Maven build output directories
2+
**/target
3+
4+
# Ignore IDE-specific files
5+
.idea/
6+
*.iml
7+
8+
# Ignore build log files
9+
build.log
10+
11+
# Ignore git repository files
12+
.git/
13+
.gitignore
14+
15+
# Ignore local environment files (the real one should never be in the image)
16+
.env

README.md

Lines changed: 153 additions & 21 deletions
Large diffs are not rendered by default.

config/alloy/alloy-config.river

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// ===================================================================
2+
// Grafana Alloy Configuration
3+
// ===================================================================
4+
5+
// --- LOGS PIPELINE ---
6+
7+
// Responsible for sending logs to the Loki backend.
8+
loki.write "default" {
9+
endpoint {
10+
url = "http://loki:3100/loki/api/v1/push"
11+
}
12+
}
13+
14+
// Connects to the Docker API and discovers ALL running containers.
15+
discovery.docker "all_containers" {
16+
host = "unix:///var/run/docker.sock"
17+
}
18+
19+
// Processes the list of discovered containers to filter them and
20+
// add a clean 'container_name' label.
21+
discovery.relabel "filtered_containers" {
22+
targets = discovery.docker.all_containers.targets
23+
rule {
24+
source_labels = ["__meta_docker_network_name"]
25+
action = "keep"
26+
regex = "spring-boot-security-observability-lab_lab-net"
27+
}
28+
rule {
29+
source_labels = ["__meta_docker_container_name"]
30+
regex = "/(.*)"
31+
target_label = "container_name"
32+
}
33+
}
34+
35+
// Scrapes raw log lines from the filtered list of containers and
36+
// forwards them directly to the exporter.
37+
loki.source.docker "default" {
38+
host = "unix:///var/run/docker.sock"
39+
targets = discovery.relabel.filtered_containers.output
40+
forward_to = [loki.write.default.receiver]
41+
}
42+
43+
// --- TRACES PIPELINE ---
44+
45+
// Listens for incoming OpenTelemetry traces on the standard gRPC port.
46+
otelcol.receiver.otlp "default" {
47+
grpc {
48+
endpoint = "0.0.0.0:4317"
49+
}
50+
output {
51+
traces = [otelcol.exporter.otlp.tempo.input]
52+
}
53+
}
54+
55+
// Forwards the received traces to the Tempo backend.
56+
otelcol.exporter.otlp "tempo" {
57+
client {
58+
endpoint = "tempo:4317"
59+
tls {
60+
insecure = true // We are on a trusted Docker network.
61+
}
62+
}
63+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
apiVersion: 1
2+
3+
datasources:
4+
- name: Prometheus
5+
uid: prometheus-lab-uid
6+
type: prometheus
7+
url: http://prometheus:9090
8+
# The access mode ("proxy" means the Grafana backend makes the requests)
9+
access: proxy
10+
isDefault: true
11+
editable: true
12+
13+
- name: Tempo
14+
uid: tempo-lab-uid
15+
type: tempo
16+
url: http://tempo:3200
17+
access: proxy
18+
editable: true
19+
# This section links this Tempo data source to our other observability pillars
20+
jsonData:
21+
# Enables the graph
22+
serviceMap:
23+
datasourceUid: 'prometheus-lab-uid'
24+
# Enables one-click navigation from a trace span directly to the logs for that trace
25+
tracesToLogs:
26+
datasourceUid: 'loki-lab-uid'
27+
mappedTags:
28+
- { key: 'service.name', value: 'container_name' }
29+
filterByTraceID: true
30+
31+
- name: Loki
32+
uid: loki-lab-uid
33+
type: loki
34+
url: http://loki:3100
35+
access: proxy
36+
editable: true

config/grafana/provisioning/datasources/prometheus-datasource.yml

Lines changed: 0 additions & 15 deletions
This file was deleted.

config/grafana/provisioning/datasources/tempo-datasource.yml

Lines changed: 0 additions & 15 deletions
This file was deleted.

config/loki/loki-config.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# ===================================================================
2+
# Loki Configuration for Local Development (Loki v3.x Syntax)
3+
# ===================================================================
4+
server:
5+
http_listen_port: 3100 # The port Loki listens on for log ingestion and API queries
6+
grpc_listen_port: 0 # Disables the gRPC port, as we are only using HTTP
7+
8+
common:
9+
# The path prefix for Loki's internal data directories
10+
path_prefix: /loki
11+
# Defines the storage backend for both index and log chunks
12+
storage:
13+
filesystem:
14+
chunks_directory: /loki/chunks
15+
rules_directory: /loki/rules
16+
# For a single-node setup, the replication factor is always 1
17+
replication_factor: 1
18+
# For our single instance, we use a simple in-memory store
19+
ring:
20+
instance_addr: 127.0.0.1
21+
kvstore:
22+
store: inmemory
23+
24+
# Configures how Loki indexes logs, allowing for fast retrieval
25+
schema_config:
26+
configs:
27+
- from: 2020-10-24 # A past date ensures this schema is always active
28+
# tsdb is the recommended index store for single-node deployments
29+
# It writes index files to the local filesystem
30+
store: tsdb
31+
object_store: filesystem
32+
schema: v13
33+
index:
34+
prefix: index_
35+
period: 24h
36+
37+
# While we are not defining alerts in this phase, the block must be present
38+
ruler:
39+
# In a full setup, this would point to our Alertmanager service
40+
alertmanager_url: http://localhost:9093

docker-compose.yml

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ services:
1717
# OpenTelemetry Agent Configuration
1818
- JAVA_TOOL_OPTIONS=-javaagent:/app/opentelemetry-javaagent.jar
1919
- OTEL_SERVICE_NAME=resource-server
20-
- OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4317
20+
- OTEL_EXPORTER_OTLP_ENDPOINT=http://alloy:4317
2121
- OTEL_EXPORTER_OTLP_PROTOCOL=grpc
2222
- OTEL_METRICS_EXPORTER=none
2323
- OTEL_LOGS_EXPORTER=none
@@ -32,6 +32,8 @@ services:
3232
depends_on:
3333
keycloak:
3434
condition: service_healthy
35+
alloy:
36+
condition: service_started
3537
networks:
3638
- lab-net
3739

@@ -51,7 +53,7 @@ services:
5153
# OpenTelemetry Agent Configuration
5254
- JAVA_TOOL_OPTIONS=-javaagent:/app/opentelemetry-javaagent.jar
5355
- OTEL_SERVICE_NAME=web-client
54-
- OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4317
56+
- OTEL_EXPORTER_OTLP_ENDPOINT=http://alloy:4317
5557
- OTEL_EXPORTER_OTLP_PROTOCOL=grpc
5658
- OTEL_METRICS_EXPORTER=none
5759
- OTEL_LOGS_EXPORTER=none
@@ -63,6 +65,8 @@ services:
6365
condition: service_healthy
6466
resource-server:
6567
condition: service_healthy
68+
alloy:
69+
condition: service_started
6670
networks:
6771
- lab-net
6872

@@ -174,6 +178,43 @@ services:
174178
networks:
175179
- lab-net
176180

181+
# --------------------------------------------------------------------------
182+
# Grafana Loki Service: For centralized log aggregation.
183+
# --------------------------------------------------------------------------
184+
loki:
185+
image: grafana/loki:3.5.3
186+
container_name: loki
187+
# The auth flag is the way to run Loki in single-tenant mode
188+
command: "-config.file=/etc/loki/loki-config.yml -auth.enabled=false"
189+
volumes:
190+
- ./config/loki/loki-config.yml:/etc/loki/loki-config.yml:ro
191+
- loki-data:/loki/data
192+
networks:
193+
- lab-net
194+
195+
# --------------------------------------------------------------------------
196+
# Grafana Alloy Service: The unified observability agent.
197+
# --------------------------------------------------------------------------
198+
alloy:
199+
image: grafana/alloy:v1.10.2
200+
container_name: alloy
201+
volumes:
202+
# =============================== SECURITY DISCLAIMER ===============================
203+
# The read-only mount of the Docker socket is a privileged operation.
204+
# For this lab, we accept this risk to enable a portable & simplified experience with automatic
205+
# service discovery. For production environments, a non-socket-based approach like
206+
# using a native Docker logging driver, or sidecar would be a more secure alternative.
207+
# ===================================================================================
208+
- /var/run/docker.sock:/var/run/docker.sock:ro
209+
- ./config/alloy/alloy-config.river:/etc/alloy/config.river:ro
210+
command: "run /etc/alloy/config.river"
211+
depends_on:
212+
- loki
213+
- tempo
214+
networks:
215+
- lab-net
216+
217+
177218
# --------------------------------------------------------------------------
178219
# Grafana Service: For metrics visualization.
179220
# --------------------------------------------------------------------------
@@ -184,14 +225,16 @@ services:
184225
- "3000:3000"
185226
volumes:
186227
- grafana-data:/var/lib/grafana
187-
- ./config/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources
228+
- ./config/grafana/provisioning/datasources/datasources.yml:/etc/grafana/provisioning/datasources/datasources.yml
188229
- ./config/grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards
189230
- ./config/grafana/dashboards:/var/lib/grafana/dashboards
190231
depends_on:
191232
prometheus:
192233
condition: service_started
193234
tempo:
194235
condition: service_started
236+
loki:
237+
condition: service_started
195238
networks:
196239
- lab-net
197240

@@ -204,7 +247,8 @@ secrets:
204247
volumes:
205248
grafana-data:
206249
keycloak-db-data:
207-
tempo-data: # New volume for Tempo's trace data
250+
tempo-data:
251+
loki-data:
208252

209253
networks:
210254
lab-net:

lab-aspects/pom.xml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.apenlor.lab</groupId>
8+
<artifactId>security-observability-lab</artifactId>
9+
<version>1.0.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>lab-aspects</artifactId>
13+
<name>lab-aspects</name>
14+
<description>Shared library for common utilities, aspects, and DTOs.</description>
15+
16+
<dependencies>
17+
<!-- Spring Libraries -->
18+
<dependency>
19+
<groupId>org.springframework.boot</groupId>
20+
<artifactId>spring-boot-starter-aop</artifactId>
21+
</dependency>
22+
<dependency>
23+
<groupId>org.springframework.boot</groupId>
24+
<artifactId>spring-boot-starter-security</artifactId>
25+
</dependency>
26+
<dependency>
27+
<groupId>org.springframework.boot</groupId>
28+
<artifactId>spring-boot-starter-web</artifactId>
29+
</dependency>
30+
31+
<!-- Metrics & Observability -->
32+
<dependency>
33+
<groupId>io.micrometer</groupId>
34+
<artifactId>micrometer-core</artifactId>
35+
</dependency>
36+
37+
<!-- Utils -->
38+
<dependency>
39+
<groupId>org.projectlombok</groupId>
40+
<artifactId>lombok</artifactId>
41+
</dependency>
42+
43+
<!-- Test Dependencies -->
44+
<dependency>
45+
<groupId>org.springframework.boot</groupId>
46+
<artifactId>spring-boot-starter-test</artifactId>
47+
<scope>test</scope>
48+
</dependency>
49+
<dependency>
50+
<groupId>org.springframework.security</groupId>
51+
<artifactId>spring-security-test</artifactId>
52+
<scope>test</scope>
53+
</dependency>
54+
<dependency>
55+
<groupId>net.logstash.logback</groupId>
56+
<artifactId>logstash-logback-encoder</artifactId>
57+
<scope>test</scope>
58+
</dependency>
59+
</dependencies>
60+
61+
<build>
62+
<plugins>
63+
<plugin>
64+
<groupId>org.apache.maven.plugins</groupId>
65+
<artifactId>maven-compiler-plugin</artifactId>
66+
</plugin>
67+
</plugins>
68+
</build>
69+
70+
</project>

0 commit comments

Comments
 (0)