mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-04-19 19:21:18 +00:00
auditTest
This commit is contained in:
parent
4d6f951604
commit
8e363f503e
@ -92,4 +92,4 @@ EXPOSE 8080/tcp
|
||||
|
||||
# Set user and run command
|
||||
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
|
||||
CMD ["sh", "-c", "java -Dfile.encoding=UTF-8 -jar /app.jar & /opt/venv/bin/unoserver --port 2003 --interface 0.0.0.0"]
|
||||
CMD ["sh", "-c", "java -Dfile.encoding=UTF-8 -jar /app.jar & /opt/venv/bin/unoserver --port 2003 --interface 127.0.0.1"]
|
@ -43,7 +43,12 @@ ENV DOCKER_ENABLE_SECURITY=false \
|
||||
PYTHONPATH=/usr/lib/libreoffice/program:/opt/venv/lib/python3.12/site-packages \
|
||||
UNO_PATH=/usr/lib/libreoffice/program \
|
||||
URE_BOOTSTRAP=file:///usr/lib/libreoffice/program/fundamentalrc \
|
||||
PATH=$PATH:/opt/venv/bin
|
||||
PATH=$PATH:/opt/venv/bin \
|
||||
LIBREOFFICE_HOME=/usr/lib/libreoffice \
|
||||
SAL_USE_VCLPLUGIN=svp \
|
||||
OOO_FORCE_DESKTOP=headless \
|
||||
DISPLAY=:99 \
|
||||
LD_LIBRARY_PATH=/usr/lib/libreoffice/program
|
||||
|
||||
|
||||
# JDK for app
|
||||
@ -53,6 +58,11 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a
|
||||
apk upgrade --no-cache -a && \
|
||||
apk add --no-cache \
|
||||
ca-certificates \
|
||||
libxcb libx11 libxtst libxi \
|
||||
xvfb-run \
|
||||
dbus \
|
||||
cairo \
|
||||
mesa-dri-gallium \
|
||||
tzdata \
|
||||
tini \
|
||||
bash \
|
||||
@ -101,4 +111,4 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a
|
||||
EXPOSE 8080/tcp
|
||||
# Set user and run command
|
||||
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
|
||||
CMD ["sh", "-c", "java -Dfile.encoding=UTF-8 -jar /app.jar & /opt/venv/bin/unoserver --port 2003 --interface 0.0.0.0"]
|
||||
CMD ["sh", "-c", "java -Dfile.encoding=UTF-8 -jar /app.jar & /opt/venv/bin/unoserver --port 2003 --interface 127.0.0.1"]
|
||||
|
@ -429,6 +429,7 @@ dependencies {
|
||||
|
||||
// Exclude Tomcat and include Jetty
|
||||
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
|
||||
implementation("org.springframework.boot:spring-boot-starter-aop:$springBootVersion")
|
||||
implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
|
||||
|
||||
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
|
||||
|
@ -0,0 +1,10 @@
|
||||
package stirling.software.SPDF.config.security;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
@Configuration
|
||||
@EnableAspectJAutoProxy
|
||||
public class AopConfig {
|
||||
// No body needed; annotation-driven
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package stirling.software.SPDF.config.security;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class AuditAspect {
|
||||
|
||||
@Autowired
|
||||
private AuditService auditService;
|
||||
|
||||
@Before(
|
||||
"@annotation(RequestMapping) || @annotation(GetMapping) || @annotation(PostMapping) || " +
|
||||
"@annotation(PutMapping) || @annotation(DeleteMapping) || @annotation(PatchMapping)"
|
||||
)
|
||||
public void logApiCall(JoinPoint joinPoint) {
|
||||
try {
|
||||
// Grab the current request
|
||||
HttpServletRequest request =
|
||||
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
|
||||
// Basic info
|
||||
String method = request.getMethod();
|
||||
String endpoint = request.getRequestURI();
|
||||
Map<String, String[]> requestParams = request.getParameterMap();
|
||||
String userAgent = request.getHeader("User-Agent");
|
||||
String ipAddress = getClientIp(request);
|
||||
String username = getCurrentUsername();
|
||||
|
||||
// Extract file metadata if multipart
|
||||
MultipartFile[] files = extractFiles(request);
|
||||
|
||||
// Pass to the audit service
|
||||
auditService.logRequest(
|
||||
method,
|
||||
endpoint,
|
||||
requestParams,
|
||||
userAgent,
|
||||
ipAddress,
|
||||
username,
|
||||
files
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
// Log and continue
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private String getClientIp(HttpServletRequest request) {
|
||||
// Some networks use X-Forwarded-For to pass client IP
|
||||
String xForwardedFor = request.getHeader("X-Forwarded-For");
|
||||
if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
|
||||
return xForwardedFor.split(",")[0];
|
||||
}
|
||||
return request.getRemoteAddr();
|
||||
}
|
||||
|
||||
private String getCurrentUsername() {
|
||||
// If using Spring Security
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (auth != null && auth.isAuthenticated()) {
|
||||
return auth.getName();
|
||||
}
|
||||
return "anonymous";
|
||||
}
|
||||
|
||||
private MultipartFile[] extractFiles(HttpServletRequest request) {
|
||||
if (request instanceof MultipartHttpServletRequest multipartRequest) {
|
||||
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
|
||||
if (!fileMap.isEmpty()) {
|
||||
return fileMap.values().toArray(new MultipartFile[0]);
|
||||
}
|
||||
}
|
||||
return new MultipartFile[0];
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package stirling.software.SPDF.config.security;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import stirling.software.SPDF.model.api.security.AuditLog;
|
||||
import stirling.software.SPDF.repository.AuditLogRepository;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AuditService {
|
||||
|
||||
@Autowired
|
||||
private AuditLogRepository auditLogRepository;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
public void logRequest(
|
||||
String method,
|
||||
String endpoint,
|
||||
Map<String, String[]> requestParams,
|
||||
String userAgent,
|
||||
String ipAddress,
|
||||
String username,
|
||||
MultipartFile[] files
|
||||
) {
|
||||
try {
|
||||
// Build the AuditLog entity
|
||||
AuditLog auditLog = new AuditLog();
|
||||
auditLog.setMethod(method);
|
||||
auditLog.setEndpoint(endpoint);
|
||||
|
||||
// Convert all text form fields (key -> array of values) to JSON for readability
|
||||
String paramsJson = requestParams != null && !requestParams.isEmpty()
|
||||
? objectMapper.writeValueAsString(requestParams)
|
||||
: null;
|
||||
auditLog.setRequestParams(paramsJson);
|
||||
|
||||
auditLog.setUserAgent(userAgent);
|
||||
auditLog.setIpAddress(ipAddress);
|
||||
auditLog.setUsername(username);
|
||||
auditLog.setTimestamp(LocalDateTime.now());
|
||||
|
||||
// Only log metadata for files
|
||||
if (files != null && files.length > 0) {
|
||||
String fileNamesStr = Arrays.stream(files)
|
||||
.map(file -> String.format(
|
||||
"[name=%s, size=%d, type=%s]",
|
||||
file.getOriginalFilename(),
|
||||
file.getSize(),
|
||||
file.getContentType()
|
||||
))
|
||||
.collect(Collectors.joining("; "));
|
||||
auditLog.setFileNames(fileNamesStr);
|
||||
}
|
||||
log.info(auditLog.toString());
|
||||
// Persist
|
||||
auditLogRepository.save(auditLog);
|
||||
|
||||
} catch (Exception e) {
|
||||
// Log error but do not disrupt the main request flow
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package stirling.software.SPDF.model.api.security;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "audit_logs")
|
||||
@Data
|
||||
public class AuditLog {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String method;
|
||||
private String endpoint;
|
||||
|
||||
@Lob
|
||||
private String requestParams; // text form params in JSON
|
||||
private String userAgent;
|
||||
private String ipAddress;
|
||||
private String username;
|
||||
private LocalDateTime timestamp;
|
||||
|
||||
// Store file metadata (comma or semicolon-separated)
|
||||
@Lob
|
||||
private String fileNames;
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package stirling.software.SPDF.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import stirling.software.SPDF.model.api.security.AuditLog;
|
||||
|
||||
@Repository
|
||||
public interface AuditLogRepository extends JpaRepository<AuditLog, Long> {
|
||||
// Additional custom queries, if needed
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user