
Spring Boot Actuator
Wire Spring Boot Actuator audit events and a production-ready AuditEventRepository for authentication and access-denied logging.
Overview
Spring Boot Actuator Auditing is an agent skill for the Operate phase that configures Spring Boot Actuator audit event publishing and AuditEventRepository choices for secured APIs.
Install
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill spring-boot-actuatorWhat is this skill?
- Documents default Actuator audit events: authentication success, failure, and access denied
- InMemoryAuditEventRepository bean pattern for local development only
- PersistentAuditEvent JPA entity sketch for a database-backed AuditEventRepository in production
- Ties audit publishing to Spring Security being enabled on the app
- Recommends custom AuditEventRepository implementations outside dev environments
- Default audit events include authentication success, failure, and access denied
Adoption & trust: 1.2k installs on skills.sh; 271 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your secured Spring Boot app runs in production but you have no structured record of auth successes, failures, or access-denied events for reporting or lock-out policies.
Who is it for?
Indie builders running Spring Boot + Spring Security who need lightweight compliance-style auth logging before adopting a full SIEM.
Skip if: Greenfield prototypes with no security layer yet, or teams that already standardized on centralized logging that replaces Actuator audit entirely.
When should I use this skill?
Configuring Spring Boot Actuator audit publishing after Spring Security is enabled on an API you operate in production.
What do I get? / Deliverables
You get a clear dev vs production audit repository setup and a persistent event schema direction so Actuator publishes auditable security events you can store and query.
- AuditConfiguration bean with AuditEventRepository
- Optional PersistentAuditEvent entity and production repository approach
Recommended Skills
Journey fit
Audit trails matter once the API is in production and you need observable security behavior, not during initial UI prototyping. Monitoring subphase covers security audit streams and lock-out policies driven by authentication failure events.
How it compares
Use for Spring-native audit hooks on Actuator instead of only dumping unstructured logs to a file.
Common Questions / FAQ
Who is spring-boot-actuator for?
Solo and small-team builders shipping Spring Boot backends who want Actuator-driven security audit events with an explicit repository strategy for dev and production.
When should I use spring-boot-actuator?
During Operate when hardening monitoring on a live API, and during Ship when reviewing security controls before launch—once Spring Security is enabled and you need authentication audit trails.
Is spring-boot-actuator safe to install?
Treat it as configuration guidance for audit storage that may hold principals and event types; review the Security Audits panel on this page and scope production repositories to your data-retention policy.
SKILL.md
READMESKILL.md - Spring Boot Actuator
# Auditing with Spring Boot Actuator Once Spring Security is in play, Spring Boot Actuator has a flexible audit framework that publishes events (by default, "authentication success", "failure" and "access denied" exceptions). This feature can be very useful for reporting and for implementing a lock-out policy based on authentication failures. You can enable auditing by providing a bean of type `AuditEventRepository` in your application's configuration. For convenience, Spring Boot offers an `InMemoryAuditEventRepository`. `InMemoryAuditEventRepository` has limited capabilities, and we recommend using it only for development environments. For production environments, consider creating your own alternative `AuditEventRepository` implementation. ## Basic Audit Configuration ### In-Memory Audit Repository (Development) ```java @Configuration public class AuditConfiguration { @Bean public AuditEventRepository auditEventRepository() { return new InMemoryAuditEventRepository(); } } ``` ### Database Audit Repository (Production) ```java @Entity @Table(name = "audit_events") public class PersistentAuditEvent { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "principal", nullable = false) private String principal; @Column(name = "audit_event_type", nullable = false) private String auditEventType; @Column(name = "audit_event_date", nullable = false) private Instant auditEventDate; @ElementCollection @MapKeyColumn(name = "name") @Column(name = "value") @CollectionTable(name = "audit_event_data", joinColumns = @JoinColumn(name = "event_id")) private Map<String, String> data = new HashMap<>(); // Constructors, getters, setters } @Repository public class CustomAuditEventRepository implements AuditEventRepository { private final PersistentAuditEventRepository repository; public CustomAuditEventRepository(PersistentAuditEventRepository repository) { this.repository = repository; } @Override public void add(AuditEvent event) { PersistentAuditEvent persistentEvent = new PersistentAuditEvent(); persistentEvent.setPrincipal(event.getPrincipal()); persistentEvent.setAuditEventType(event.getType()); persistentEvent.setAuditEventDate(event.getTimestamp()); persistentEvent.setData(event.getData()); repository.save(persistentEvent); } @Override public List<AuditEvent> find(String principal, Instant after, String type) { List<PersistentAuditEvent> events = repository.findByPrincipalAndAuditEventDateAfterAndAuditEventType( principal, after, type); return events.stream() .map(this::convertToAuditEvent) .collect(Collectors.toList()); } private AuditEvent convertToAuditEvent(PersistentAuditEvent persistentEvent) { return new AuditEvent(persistentEvent.getAuditEventDate(), persistentEvent.getPrincipal(), persistentEvent.getAuditEventType(), persistentEvent.getData()); } } ``` ## Custom Auditing ### Custom Audit Events You can publish custom audit events using `AuditEventRepository`: ```java @Service public class UserService { private final AuditEventRepository auditEventRepository; private final UserRepository userRepository; public UserService(AuditEventRepository auditEventRepository, UserRepository userRepository) { this.auditEventRepository = auditEventRepository; this.userRepository = userRepository; } public User createUser(CreateUserRequest request) { User user = userRepository.save(request.toUser()); // Publish audit event Map<String, String> data = new HashMap<>(); data.put("userId", user.getId().toString());