Skip to content

Commit 06ec9d0

Browse files
committed
feat(security): add RBAC secure context, audit, bootstrap, and secure repositories
1 parent 0a20f8d commit 06ec9d0

34 files changed

+2782
-5
lines changed

spring-boot-starter-data-falkordb/pom.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@
6666
<artifactId>spring-boot-starter</artifactId>
6767
</dependency>
6868

69+
<!-- Optional: validation annotations used by configuration properties -->
70+
<dependency>
71+
<groupId>jakarta.validation</groupId>
72+
<artifactId>jakarta.validation-api</artifactId>
73+
<optional>true</optional>
74+
</dependency>
75+
6976
<!-- Spring Data FalkorDB -->
7077
<dependency>
7178
<groupId>com.falkordb</groupId>
@@ -87,6 +94,24 @@
8794
<optional>true</optional>
8895
</dependency>
8996

97+
<!-- Spring Security Core for RBAC integration -->
98+
<dependency>
99+
<groupId>org.springframework.security</groupId>
100+
<artifactId>spring-security-core</artifactId>
101+
</dependency>
102+
103+
<!-- Optional: only needed if using FalkorDBSecurityContextFilter (servlet integration) -->
104+
<dependency>
105+
<groupId>org.springframework</groupId>
106+
<artifactId>spring-web</artifactId>
107+
<optional>true</optional>
108+
</dependency>
109+
<dependency>
110+
<groupId>jakarta.servlet</groupId>
111+
<artifactId>jakarta.servlet-api</artifactId>
112+
<optional>true</optional>
113+
</dependency>
114+
90115
<!-- Test Dependencies -->
91116
<dependency>
92117
<groupId>org.springframework.boot</groupId>

spring-boot-starter-data-falkordb/src/main/java/org/springframework/boot/autoconfigure/data/falkordb/FalkorDBProperties.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,3 @@ public void setDatabase(String database) {
4242
this.database = database;
4343
}
4444
}
45-
public void setDatabase(String database) {
46-
this.database = database;
47-
}
48-
}

spring-boot-starter-data-falkordb/src/main/java/org/springframework/boot/autoconfigure/data/falkordb/FalkorDBRepositoriesAutoConfiguration.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@
88
import org.springframework.context.annotation.Import;
99
import org.springframework.data.falkordb.core.FalkorDBTemplate;
1010
import org.springframework.data.falkordb.repository.FalkorDBRepository;
11-
import org.springframework.data.falkordb.repository.config.EnableFalkorDBRepositories;
1211
import org.springframework.data.falkordb.repository.config.FalkorDBRepositoryConfigurationExtension;
1312
import org.springframework.data.falkordb.repository.support.FalkorDBRepositoryFactoryBean;
1413

1514
/**
1615
* Auto-configuration for Spring Data FalkorDB Repositories.
1716
* Only activates if FalkorDBTemplate bean is available.
1817
*
18+
* This configuration is used when RBAC security is disabled
19+
* (or not explicitly enabled).
20+
*
1921
* @author Shahar Biron
2022
* @since 1.0
2123
*/
@@ -26,6 +28,8 @@
2628
FalkorDBRepositoryConfigurationExtension.class})
2729
@ConditionalOnProperty(prefix = "spring.data.falkordb.repositories", name = "enabled",
2830
havingValue = "true", matchIfMissing = true)
31+
@ConditionalOnProperty(prefix = "spring.data.falkordb.security", name = "enabled",
32+
havingValue = "false", matchIfMissing = true)
2933
@Import(FalkorDBRepositoriesRegistrar.class)
3034
public class FalkorDBRepositoriesAutoConfiguration {
3135
// Configuration handled by the registrar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package org.springframework.boot.autoconfigure.data.falkordb;
2+
3+
import org.springframework.boot.autoconfigure.AutoConfiguration;
4+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
5+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
6+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
7+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
8+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
9+
import org.springframework.context.annotation.Bean;
10+
import org.springframework.data.falkordb.core.FalkorDBTemplate;
11+
import org.springframework.data.falkordb.security.audit.AuditLogger;
12+
import org.springframework.data.falkordb.security.bootstrap.FalkorDBSecurityBootstrapRunner;
13+
import org.springframework.data.falkordb.security.integration.AuthenticationFalkorSecurityContextAdapter;
14+
import org.springframework.data.falkordb.security.integration.FalkorDBSecurityContextFilter;
15+
import org.springframework.data.falkordb.security.integration.PrivilegeService;
16+
import org.springframework.data.falkordb.security.manager.RBACManager;
17+
import org.springframework.security.core.Authentication;
18+
import org.springframework.security.core.context.SecurityContextHolder;
19+
import org.springframework.web.filter.OncePerRequestFilter;
20+
21+
/**
22+
* Auto-configuration for FalkorDB RBAC/Security integration with Spring Security.
23+
*
24+
* Provides beans to bridge Spring Security's {@link Authentication} to
25+
* {@link org.springframework.data.falkordb.security.context.FalkorSecurityContext}
26+
* and a {@link OncePerRequestFilter} that populates the Falkor context per request.
27+
*
28+
* Note: the filter is provided as a bean but is not automatically wired into the
29+
* Spring Security filter chain. Applications should register it explicitly in
30+
* their {@code SecurityFilterChain} configuration.
31+
*/
32+
@AutoConfiguration(after = FalkorDBAutoConfiguration.class)
33+
@ConditionalOnClass({ SecurityContextHolder.class, Authentication.class, OncePerRequestFilter.class })
34+
@ConditionalOnBean(FalkorDBTemplate.class)
35+
@ConditionalOnProperty(prefix = "spring.data.falkordb.security", name = "enabled", havingValue = "true")
36+
@EnableConfigurationProperties(FalkorDBSecurityProperties.class)
37+
public class FalkorDBSecurityConfiguration {
38+
39+
@Bean
40+
@ConditionalOnMissingBean
41+
public PrivilegeService falkorDBPrivilegeService(FalkorDBTemplate template, FalkorDBSecurityProperties properties) {
42+
return new PrivilegeService(template, properties.getPrivilegeCacheTtl());
43+
}
44+
45+
@Bean
46+
@ConditionalOnMissingBean
47+
public AuthenticationFalkorSecurityContextAdapter falkorDBAuthenticationAdapter(FalkorDBTemplate template,
48+
PrivilegeService privilegeService) {
49+
return new AuthenticationFalkorSecurityContextAdapter(template, privilegeService);
50+
}
51+
52+
@Bean
53+
@ConditionalOnMissingBean
54+
public AuditLogger falkorDBAuditLogger(FalkorDBTemplate template, FalkorDBSecurityProperties properties) {
55+
return new AuditLogger(template, properties.isAuditEnabled());
56+
}
57+
58+
@Bean
59+
@ConditionalOnMissingBean
60+
public RBACManager falkorDBRbacManager(FalkorDBTemplate template, FalkorDBSecurityProperties properties) {
61+
return new RBACManager(template, properties.getAdminRole());
62+
}
63+
64+
@Bean
65+
@ConditionalOnMissingBean
66+
public FalkorDBSecurityContextFilter falkorDBSecurityContextFilter(
67+
AuthenticationFalkorSecurityContextAdapter adapter) {
68+
return new FalkorDBSecurityContextFilter(adapter);
69+
}
70+
71+
@Bean
72+
@ConditionalOnMissingBean
73+
@ConditionalOnProperty(prefix = "spring.data.falkordb.security.bootstrap", name = "enabled", havingValue = "true")
74+
public FalkorDBSecurityBootstrapRunner falkorDBSecurityBootstrapRunner(FalkorDBTemplate template,
75+
FalkorDBSecurityProperties properties) {
76+
return new FalkorDBSecurityBootstrapRunner(template, properties);
77+
}
78+
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package org.springframework.boot.autoconfigure.data.falkordb;
2+
3+
import java.time.Duration;
4+
5+
import org.springframework.boot.context.properties.ConfigurationProperties;
6+
7+
/**
8+
* Configuration properties for FalkorDB RBAC / security integration.
9+
*/
10+
@ConfigurationProperties(prefix = "spring.data.falkordb.security")
11+
public class FalkorDBSecurityProperties {
12+
13+
/**
14+
* Whether RBAC security is enabled.
15+
*/
16+
private boolean enabled = false;
17+
18+
/**
19+
* Name of the administrative role.
20+
*/
21+
private String adminRole = "admin";
22+
23+
/**
24+
* Whether audit logging is enabled.
25+
*/
26+
private boolean auditEnabled = true;
27+
28+
/**
29+
* Time-to-live for cached privileges per user.
30+
*/
31+
private Duration privilegeCacheTtl = Duration.ofMinutes(1);
32+
33+
/**
34+
* Bootstrap settings for creating initial admin role/user.
35+
*/
36+
private final Bootstrap bootstrap = new Bootstrap();
37+
38+
public Bootstrap getBootstrap() {
39+
return this.bootstrap;
40+
}
41+
42+
public boolean isEnabled() {
43+
return this.enabled;
44+
}
45+
46+
public void setEnabled(boolean enabled) {
47+
this.enabled = enabled;
48+
}
49+
50+
public String getAdminRole() {
51+
return this.adminRole;
52+
}
53+
54+
public void setAdminRole(String adminRole) {
55+
this.adminRole = adminRole;
56+
}
57+
58+
public boolean isAuditEnabled() {
59+
return this.auditEnabled;
60+
}
61+
62+
public void setAuditEnabled(boolean auditEnabled) {
63+
this.auditEnabled = auditEnabled;
64+
}
65+
66+
public Duration getPrivilegeCacheTtl() {
67+
return this.privilegeCacheTtl;
68+
}
69+
70+
public void setPrivilegeCacheTtl(Duration privilegeCacheTtl) {
71+
this.privilegeCacheTtl = privilegeCacheTtl;
72+
}
73+
74+
public static class Bootstrap {
75+
76+
/**
77+
* Enable bootstrap logic.
78+
*/
79+
private boolean enabled = false;
80+
81+
/**
82+
* Create (or ensure) an admin user at startup.
83+
*/
84+
private String adminUsername;
85+
86+
/**
87+
* Optional email for the bootstrapped admin user.
88+
*/
89+
private String adminEmail;
90+
91+
public boolean isEnabled() {
92+
return this.enabled;
93+
}
94+
95+
public void setEnabled(boolean enabled) {
96+
this.enabled = enabled;
97+
}
98+
99+
public String getAdminUsername() {
100+
return this.adminUsername;
101+
}
102+
103+
public void setAdminUsername(String adminUsername) {
104+
this.adminUsername = adminUsername;
105+
}
106+
107+
public String getAdminEmail() {
108+
return this.adminEmail;
109+
}
110+
111+
public void setAdminEmail(String adminEmail) {
112+
this.adminEmail = adminEmail;
113+
}
114+
}
115+
116+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.springframework.boot.autoconfigure.data.falkordb;
2+
3+
import org.springframework.boot.autoconfigure.AutoConfiguration;
4+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
5+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
6+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
7+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
8+
import org.springframework.context.annotation.Import;
9+
import org.springframework.data.falkordb.core.FalkorDBTemplate;
10+
import org.springframework.data.falkordb.repository.FalkorDBRepository;
11+
import org.springframework.data.falkordb.repository.config.FalkorDBRepositoryConfigurationExtension;
12+
import org.springframework.data.falkordb.security.repository.FalkorDBSecurityRepositoryFactoryBean;
13+
14+
/**
15+
* Auto-configuration for security-aware Spring Data FalkorDB repositories.
16+
* Uses {@link FalkorDBSecurityRepositoryFactoryBean} to create
17+
* {@link org.springframework.data.falkordb.security.repository.SecureFalkorDBRepository}
18+
* instances when RBAC security is enabled.
19+
*/
20+
@AutoConfiguration(after = FalkorDBAutoConfiguration.class)
21+
@ConditionalOnClass({ FalkorDBTemplate.class, FalkorDBRepository.class })
22+
@ConditionalOnBean(FalkorDBTemplate.class)
23+
@ConditionalOnMissingBean({ FalkorDBSecurityRepositoryFactoryBean.class,
24+
FalkorDBRepositoryConfigurationExtension.class })
25+
@ConditionalOnProperty(prefix = "spring.data.falkordb.repositories", name = "enabled",
26+
havingValue = "true", matchIfMissing = true)
27+
@ConditionalOnProperty(prefix = "spring.data.falkordb.security", name = "enabled",
28+
havingValue = "true")
29+
@Import(FalkorDBSecurityRepositoriesRegistrar.class)
30+
public class FalkorDBSecurityRepositoriesAutoConfiguration {
31+
// Configuration handled by the security registrar
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.springframework.boot.autoconfigure.data.falkordb;
2+
3+
import java.lang.annotation.Annotation;
4+
5+
import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport;
6+
import org.springframework.context.annotation.Configuration;
7+
import org.springframework.data.falkordb.repository.config.EnableFalkorDBRepositories;
8+
import org.springframework.data.falkordb.repository.config.FalkorDBRepositoryConfigurationExtension;
9+
import org.springframework.data.falkordb.security.repository.FalkorDBSecurityRepositoryFactoryBean;
10+
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
11+
12+
/**
13+
* Registrar variant that enables FalkorDB repositories using the
14+
* security-aware {@link FalkorDBSecurityRepositoryFactoryBean}.
15+
*/
16+
class FalkorDBSecurityRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupport {
17+
18+
@Override
19+
protected Class<? extends Annotation> getAnnotation() {
20+
return EnableFalkorDBRepositories.class;
21+
}
22+
23+
@Override
24+
protected Class<?> getConfiguration() {
25+
return EnableFalkorDBSecurityRepositoriesConfiguration.class;
26+
}
27+
28+
@Override
29+
protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
30+
return new FalkorDBRepositoryConfigurationExtension();
31+
}
32+
33+
@Configuration(proxyBeanMethods = false)
34+
@EnableFalkorDBRepositories(repositoryFactoryBeanClass = FalkorDBSecurityRepositoryFactoryBean.class)
35+
static class EnableFalkorDBSecurityRepositoriesConfiguration {
36+
}
37+
38+
}

0 commit comments

Comments
 (0)