running with security on/off

This commit is contained in:
Dario Ghunney Ware 2025-05-09 14:16:34 +01:00
parent 2e3a8009b6
commit cab21eb590
35 changed files with 353 additions and 114 deletions

View File

@ -69,6 +69,16 @@ sourceSets {
exclude "stirling/software/SPDF/model/SessionEntity.java" exclude "stirling/software/SPDF/model/SessionEntity.java"
exclude "stirling/software/SPDF/model/User.java" exclude "stirling/software/SPDF/model/User.java"
exclude "stirling/software/SPDF/repository/**" exclude "stirling/software/SPDF/repository/**"
exclude 'stirling/software/enterprise/security/controller/**'
exclude 'stirling/software/enterprise/security/model/ApiKeyAuthenticationToken.java'
exclude 'stirling/software/enterprise/security/model/AttemptCounter.java'
exclude 'stirling/software/enterprise/security/model/Authority.java'
exclude 'stirling/software/enterprise/security/model/BackupNotFoundException.java'
exclude 'stirling/software/enterprise/security/model/PersistentLogin.java'
exclude 'stirling/software/enterprise/security/model/SessionEntity.java'
exclude 'stirling/software/enterprise/security/model/User.java'
exclude 'stirling/software/enterprise/security/database/repository/**'
} }
if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") { if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") {
@ -415,7 +425,6 @@ configurations.all {
dependencies { dependencies {
implementation project(':common') implementation project(':common')
implementation project(':enterprise')
//tmp for security bumps //tmp for security bumps
implementation 'ch.qos.logback:logback-core:1.5.18' implementation 'ch.qos.logback:logback-core:1.5.18'
@ -429,6 +438,10 @@ dependencies {
exclude group: 'org.bouncycastle', module: 'bcmail-jdk15on' exclude group: 'org.bouncycastle', module: 'bcmail-jdk15on'
} }
if (System.getenv("DOCKER_ENABLE_SECURITY") == "true") {
implementation project(':enterprise')
}
if (System.getenv("STIRLING_PDF_DESKTOP_UI") != "false") { if (System.getenv("STIRLING_PDF_DESKTOP_UI") != "false") {
implementation "me.friwi:jcefmaven:132.3.1" implementation "me.friwi:jcefmaven:132.3.1"
implementation "org.openjfx:javafx-controls:21" implementation "org.openjfx:javafx-controls:21"
@ -448,36 +461,6 @@ dependencies {
implementation 'com.posthog.java:posthog:1.2.0' implementation 'com.posthog.java:posthog:1.2.0'
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE"
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-mail:$springBootVersion"
implementation "org.springframework.session:spring-session-core:3.4.3"
implementation "org.springframework:spring-jdbc:6.2.6"
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
// Don't upgrade h2database
runtimeOnly "com.h2database:h2:2.3.232"
runtimeOnly "org.postgresql:postgresql:42.7.5"
constraints {
implementation "org.opensaml:opensaml-core:$openSamlVersion"
implementation "org.opensaml:opensaml-saml-api:$openSamlVersion"
implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion"
}
implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion"
// implementation 'org.springframework.security:spring-security-core:$springSecuritySamlVersion'
implementation 'com.coveo:saml-client:5.0.0'
}
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
// Batik // Batik
implementation "org.apache.xmlgraphics:batik-all:1.19" implementation "org.apache.xmlgraphics:batik-all:1.19"
@ -508,8 +491,6 @@ dependencies {
implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion") implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion")
implementation "org.apache.pdfbox:preflight:$pdfboxVersion" implementation "org.apache.pdfbox:preflight:$pdfboxVersion"
implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion") implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion")
// https://mvnrepository.com/artifact/technology.tabula/tabula // https://mvnrepository.com/artifact/technology.tabula/tabula
@ -534,6 +515,7 @@ dependencies {
compileOnly "org.projectlombok:lombok:$lombokVersion" compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion"
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0' testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
} }

View File

@ -35,6 +35,7 @@ import stirling.software.common.model.ApplicationProperties;
@RequiredArgsConstructor @RequiredArgsConstructor
public class AppConfig { public class AppConfig {
private final Environment env;
private final ApplicationProperties applicationProperties; private final ApplicationProperties applicationProperties;
private final Environment env; private final Environment env;
@ -64,6 +65,11 @@ public class AppConfig {
return applicationProperties.getSecurity().getEnableLogin(); return applicationProperties.getSecurity().getEnableLogin();
} }
@Bean
public boolean activeSecurity() {
return env.getProperty("DOCKER_SECURITY_ENABLED", Boolean.class, true);
}
@Bean(name = "appName") @Bean(name = "appName")
public String appName() { public String appName() {
String homeTitle = applicationProperties.getUi().getAppName(); String homeTitle = applicationProperties.getUi().getAppName();
@ -147,10 +153,10 @@ public class AppConfig {
} }
} }
@ConditionalOnMissingClass("stirling.software.SPDF.config.security.SecurityConfiguration") @Bean(name = "missingActiveSecurity")
@Bean(name = "activeSecurity") @ConditionalOnMissingClass("stirling.software.enterprise.security.SecurityConfiguration")
public boolean missingActiveSecurity() { public boolean missingActiveSecurity() {
return false; return true;
} }
@Bean(name = "directoryFilter") @Bean(name = "directoryFilter")

View File

@ -1,4 +1,4 @@
package stirling.software.enterprise.security.model; package stirling.software.common.model.enumeration;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;

196
enterprise/.gitignore vendored Normal file
View File

@ -0,0 +1,196 @@
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.exe
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
.classpath
.project
version.properties
#### Stirling-PDF Files ###
pipeline/watchedFolders/
pipeline/finishedFolders/
customFiles/
configs/
watchedFolders/
clientWebUI/
!cucumber/
!cucumber/exampleFiles/
!cucumber/exampleFiles/example_html.zip
exampleYmlFiles/stirling/
/testing/file_snapshots
SwaggerDoc.json
# Gradle
.gradle
.lock
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project
### Eclipse Patch ###
# Spring Boot Tooling
.sts4-cache/
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
*.db
/build
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*.pyo
# Virtual environments
.env*
.venv*
env*/
venv*/
ENV/
env.bak/
venv.bak/
# VS Code
/.vscode/**/*
!/.vscode/settings.json
!/.vscode/extensions.json
# IntelliJ IDEA
.idea/
*.iml
out/
# Ignore Mac DS_Store files
.DS_Store
**/.DS_Store
# cucumber
/cucumber/reports/**
# Certs and Security Files
*.p12
*.pk8
*.pem
*.crt
*.cer
*.cert
*.der
*.key
*.csr
*.kdbx
*.jks
*.asc
# SSH Keys
*.pub
*.priv
id_rsa
id_rsa.pub
id_ecdsa
id_ecdsa.pub
id_ed25519
id_ed25519.pub
.ssh/
*ssh
# cache
.cache
.ruff_cache
.mypy_cache
.pytest_cache
.ipynb_checkpoints
**/jcef-bundle/
# node_modules
node_modules/
*.mjs

View File

@ -21,6 +21,46 @@ ext {
lombokVersion = "1.18.38" lombokVersion = "1.18.38"
} }
sourceSets {
main {
java {
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") {
exclude 'stirling/software/enterprise/security/UserAuthenticationFilter.java'
exclude 'stirling/software/enterprise/security/UserBasedRateLimitingFilter.java'
exclude 'stirling/software/enterprise/security/CustomAuthenticationSuccessHandler.java'
exclude 'stirling/software/enterprise/security/CustomLogoutSuccessHandler.java'
exclude 'stirling/software/enterprise/security/FirstLoginFilter.java'
exclude 'stirling/software/enterprise/security/IPRateLimitingFilter.java'
exclude 'stirling/software/enterprise/security/RateLimitResetScheduler.java'
exclude 'stirling/software/enterprise/security/CustomAuthenticationFailureHandler.java'
exclude 'stirling/software/enterprise/security/InitialSecuritySetup.java'
exclude 'stirling/software/enterprise/security/configuration/**'
exclude 'stirling/software/enterprise/security/controller/**'
exclude 'stirling/software/enterprise/security/database/**'
exclude 'stirling/software/enterprise/security/oauth2/**'
exclude 'stirling/software/enterprise/security/saml2/**'
exclude 'stirling/software/enterprise/security/service/**'
exclude 'stirling/software/enterprise/security/session/**'
exclude 'stirling/software/enterprise/security/model/ApiKeyAuthenticationToken.java'
exclude 'stirling/software/enterprise/security/model/AttemptCounter.java'
exclude 'stirling/software/enterprise/security/model/Authority.java'
exclude 'stirling/software/enterprise/security/model/BackupNotFoundException.java'
exclude 'stirling/software/enterprise/security/model/PersistentLogin.java'
exclude 'stirling/software/enterprise/security/model/SessionEntity.java'
exclude 'stirling/software/enterprise/security/model/User.java'
}
}
test {
java {
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") {
exclude 'stirling/software/enterprise/security/**'
}
}
}
}
}
configurations.all { configurations.all {
exclude group: 'commons-logging', module: 'commons-logging' exclude group: 'commons-logging', module: 'commons-logging'
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat" exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
@ -38,8 +78,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jetty' implementation 'org.springframework.boot:spring-boot-starter-jetty'
implementation 'io.swagger.core.v3:swagger-core-jakarta:2.2.30' implementation 'io.swagger.core.v3:swagger-core-jakarta:2.2.30'
implementation 'org.springframework:spring-webmvc:6.2.6' implementation 'org.springframework:spring-webmvc:6.2.6'
// implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0' todo: testing
implementation 'com.posthog.java:posthog:1.2.0' implementation 'com.posthog.java:posthog:1.2.0'
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17 // https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
implementation 'com.bucket4j:bucket4j_jdk17-core:8.14.0' implementation 'com.bucket4j:bucket4j_jdk17-core:8.14.0'
implementation 'io.github.pixee:java-security-toolkit:1.2.1' implementation 'io.github.pixee:java-security-toolkit:1.2.1'
@ -76,6 +116,8 @@ dependencies {
testImplementation platform('org.junit:junit-bom:5.10.0') testImplementation platform('org.junit:junit-bom:5.10.0')
testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
} }
test { test {

View File

@ -8,7 +8,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.enterprise.security.model.Role; import stirling.software.common.model.enumeration.Role;
import stirling.software.enterprise.security.service.DatabaseServiceInterface; import stirling.software.enterprise.security.service.DatabaseServiceInterface;
import stirling.software.enterprise.security.service.UserService; import stirling.software.enterprise.security.service.UserService;

View File

@ -3,6 +3,7 @@ package stirling.software.enterprise.security;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import stirling.software.enterprise.security.filter.IPRateLimitingFilter;
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor

View File

@ -1,19 +1,24 @@
package stirling.software.common.configuration; package stirling.software.enterprise.security.configuration;
import javax.sql.DataSource; import javax.sql.DataSource;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import stirling.software.common.configuration.InstallationPathConfig;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.exception.UnsupportedProviderException;
@Slf4j @Slf4j
@Getter @Getter
@Configuration @Configuration
@EnableJpaRepositories(basePackages = "stirling.software.enterprise.security.database.repository")
@EntityScan({"stirling.software.enterprise.security.model"})
public class DatabaseConfig { public class DatabaseConfig {
public final String DATASOURCE_DEFAULT_URL; public final String DATASOURCE_DEFAULT_URL;

View File

@ -1,4 +1,4 @@
package stirling.software.enterprise.security; package stirling.software.enterprise.security.configuration;
import java.util.Optional; import java.util.Optional;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -29,6 +29,12 @@ import org.springframework.security.web.savedrequest.NullRequestCache;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import stirling.software.common.configuration.AppConfig; import stirling.software.common.configuration.AppConfig;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.enterprise.security.CustomAuthenticationFailureHandler;
import stirling.software.enterprise.security.CustomAuthenticationSuccessHandler;
import stirling.software.enterprise.security.CustomLogoutSuccessHandler;
import stirling.software.enterprise.security.filter.FirstLoginFilter;
import stirling.software.enterprise.security.filter.IPRateLimitingFilter;
import stirling.software.enterprise.security.filter.UserAuthenticationFilter;
import stirling.software.enterprise.security.database.repository.JPATokenRepositoryImpl; import stirling.software.enterprise.security.database.repository.JPATokenRepositoryImpl;
import stirling.software.enterprise.security.database.repository.PersistentLoginRepository; import stirling.software.enterprise.security.database.repository.PersistentLoginRepository;
import stirling.software.enterprise.security.model.User; import stirling.software.enterprise.security.model.User;
@ -312,9 +318,4 @@ public class SecurityConfiguration {
public PersistentTokenRepository persistentTokenRepository() { public PersistentTokenRepository persistentTokenRepository() {
return new JPATokenRepositoryImpl(persistentLoginRepository); return new JPATokenRepositoryImpl(persistentLoginRepository);
} }
@Bean
public boolean activeSecurity() {
return true;
}
} }

View File

@ -31,7 +31,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.enterprise.security.model.AuthenticationType; import stirling.software.enterprise.security.model.AuthenticationType;
import stirling.software.enterprise.security.model.Role; import stirling.software.common.model.enumeration.Role;
import stirling.software.enterprise.security.model.User; import stirling.software.enterprise.security.model.User;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.exception.UnsupportedProviderException;

View File

@ -30,7 +30,7 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.enterprise.security.model.Authority; import stirling.software.enterprise.security.model.Authority;
import stirling.software.enterprise.security.model.Role; import stirling.software.common.model.enumeration.Role;
import stirling.software.enterprise.security.model.SessionEntity; import stirling.software.enterprise.security.model.SessionEntity;
import stirling.software.enterprise.security.model.User; import stirling.software.enterprise.security.model.User;
import stirling.software.enterprise.security.database.repository.UserRepository; import stirling.software.enterprise.security.database.repository.UserRepository;

View File

@ -1,4 +1,4 @@
package stirling.software.enterprise.security.session; package stirling.software.enterprise.security.database.repository;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import java.util.Date; import java.util.Date;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config; package stirling.software.enterprise.security.filter;
import java.io.IOException; import java.io.IOException;

View File

@ -1,4 +1,4 @@
package stirling.software.enterprise.security; package stirling.software.enterprise.security.filter;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;

View File

@ -1,4 +1,4 @@
package stirling.software.enterprise.security; package stirling.software.enterprise.security.filter;
import jakarta.servlet.Filter; import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;

View File

@ -1,4 +1,4 @@
package stirling.software.enterprise.security; package stirling.software.enterprise.security.filter;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;

View File

@ -1,4 +1,4 @@
package stirling.software.enterprise.security; package stirling.software.enterprise.security.filter;
import io.github.bucket4j.Bandwidth; import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket; import io.github.bucket4j.Bucket;
@ -20,7 +20,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import stirling.software.enterprise.security.model.Role; import stirling.software.common.model.enumeration.Role;
@Component @Component
public class UserBasedRateLimitingFilter extends OncePerRequestFilter { public class UserBasedRateLimitingFilter extends OncePerRequestFilter {

View File

@ -14,6 +14,7 @@ import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import stirling.software.common.model.enumeration.Role;
@Entity @Entity
@Table(name = "users") @Table(name = "users")

View File

@ -6,6 +6,7 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -36,6 +37,7 @@ import static stirling.software.common.util.ValidationUtil.isStringEmpty;
@Slf4j @Slf4j
@Configuration @Configuration
@ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true") @ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true")
@ConditionalOnExpression("${docker.enable.security:true}")
public class OAuth2Configuration { public class OAuth2Configuration {
public static final String REDIRECT_URI_PATH = "{baseUrl}/login/oauth2/code/"; public static final String REDIRECT_URI_PATH = "{baseUrl}/login/oauth2/code/";

View File

@ -27,11 +27,12 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.common.service.UserServiceInterface;
import stirling.software.enterprise.security.database.repository.AuthorityRepository; import stirling.software.enterprise.security.database.repository.AuthorityRepository;
import stirling.software.enterprise.security.database.repository.UserRepository; import stirling.software.enterprise.security.database.repository.UserRepository;
import stirling.software.enterprise.security.model.AuthenticationType; import stirling.software.enterprise.security.model.AuthenticationType;
import stirling.software.enterprise.security.model.Authority; import stirling.software.enterprise.security.model.Authority;
import stirling.software.enterprise.security.model.Role; import stirling.software.common.model.enumeration.Role;
import stirling.software.enterprise.security.model.User; import stirling.software.enterprise.security.model.User;
import stirling.software.enterprise.security.saml2.CustomSaml2AuthenticatedPrincipal; import stirling.software.enterprise.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.enterprise.security.session.SessionPersistentRegistry; import stirling.software.enterprise.security.session.SessionPersistentRegistry;
@ -39,7 +40,7 @@ import stirling.software.enterprise.security.session.SessionPersistentRegistry;
@Service @Service
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
public class UserService implements UserServiceEnterpriseInterface { public class UserService implements UserServiceInterface {
private final UserRepository userRepository; private final UserRepository userRepository;

View File

@ -1,11 +0,0 @@
package stirling.software.enterprise.security.service;
import stirling.software.common.service.UserServiceInterface;
public interface UserServiceEnterpriseInterface extends UserServiceInterface {
String getApiKeyForUser(String username);
String getCurrentUsername();
long getTotalUsersCount();
}

View File

@ -15,6 +15,7 @@ import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import stirling.software.enterprise.security.database.repository.SessionRepository;
import stirling.software.enterprise.security.model.SessionEntity; import stirling.software.enterprise.security.model.SessionEntity;
import stirling.software.enterprise.security.saml2.CustomSaml2AuthenticatedPrincipal; import stirling.software.enterprise.security.saml2.CustomSaml2AuthenticatedPrincipal;

View File

@ -3,6 +3,7 @@ package stirling.software.enterprise.security.session;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.core.session.SessionRegistryImpl;
import stirling.software.enterprise.security.database.repository.SessionRepository;
@Configuration @Configuration
public class SessionRegistryConfig { public class SessionRegistryConfig {
@ -13,8 +14,7 @@ public class SessionRegistryConfig {
} }
@Bean @Bean
public SessionPersistentRegistry sessionPersistentRegistry( public SessionPersistentRegistry sessionPersistentRegistry(SessionRepository sessionRepository) {
SessionRepository sessionRepository) {
return new SessionPersistentRegistry(sessionRepository); return new SessionPersistentRegistry(sessionRepository);
} }
} }

View File

@ -1,23 +1,17 @@
package stirling.software.SPDF.config.security; package stirling.software.enterprise.security;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.enterprise.security.CustomLogoutSuccessHandler; import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class CustomLogoutSuccessHandlerTest { class CustomLogoutSuccessHandlerTest {

View File

@ -1,4 +1,4 @@
package stirling.software.common.configuration; package stirling.software.enterprise.security.configuration;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;

View File

@ -5,3 +5,7 @@ plugins {
rootProject.name = 'Stirling-PDF' rootProject.name = 'Stirling-PDF'
include 'common', 'enterprise' include 'common', 'enterprise'
//if (System.getenv('DOCKER_ENABLE_SECURITY') == 'true') {
// include 'enterprise'
//}

View File

@ -1,4 +1,6 @@
package stirling.software.enterprise.configuration; package stirling.software.SPDF.EE.configuration;
import static stirling.software.SPDF.EE.configuration.KeygenLicenseVerifier.License;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -6,15 +8,11 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import lombok.extern.slf4j.Slf4j;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.EnterpriseEdition; import stirling.software.common.model.ApplicationProperties.EnterpriseEdition;
import stirling.software.common.model.ApplicationProperties.Premium; import stirling.software.common.model.ApplicationProperties.Premium;
import stirling.software.common.model.ApplicationProperties.Premium.ProFeatures.GoogleDrive; import stirling.software.common.model.ApplicationProperties.Premium.ProFeatures.GoogleDrive;
import static stirling.software.enterprise.configuration.KeygenLicenseVerifier.*;
@Slf4j
@Configuration @Configuration
@Order(Ordered.HIGHEST_PRECEDENCE) @Order(Ordered.HIGHEST_PRECEDENCE)
public class EEAppConfig { public class EEAppConfig {

View File

@ -1,4 +1,4 @@
package stirling.software.enterprise.configuration; package stirling.software.SPDF.EE.configuration;
import java.net.URI; import java.net.URI;
import java.net.http.HttpClient; import java.net.http.HttpClient;
@ -19,15 +19,15 @@ import com.posthog.java.shaded.org.json.JSONObject;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.common.util.GeneralUtils;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.util.GeneralUtils;
@Service @Service
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
public class KeygenLicenseVerifier { public class KeygenLicenseVerifier {
enum License { public enum License {
NORMAL, NORMAL,
PRO, PRO,
ENTERPRISE ENTERPRISE

View File

@ -1,4 +1,4 @@
package stirling.software.enterprise.configuration; package stirling.software.SPDF.EE.configuration;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
@ -10,12 +10,12 @@ import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.enterprise.configuration.KeygenLicenseVerifier.License; import stirling.software.SPDF.EE.configuration.KeygenLicenseVerifier.License;
import stirling.software.common.util.GeneralUtils;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.util.GeneralUtils;
@Component
@Slf4j @Slf4j
@Component
public class LicenseKeyChecker { public class LicenseKeyChecker {
private static final String FILE_PREFIX = "file:"; private static final String FILE_PREFIX = "file:";

View File

@ -35,7 +35,12 @@ import stirling.software.common.util.UrlUtils;
@Slf4j @Slf4j
@EnableScheduling @EnableScheduling
@SpringBootApplication( @SpringBootApplication(
scanBasePackages = {"stirling.software.common", "stirling.software.SPDF"}, scanBasePackages = {
"stirling.software.SPDF",
"stirling.software.common",
"stirling.software.enterprise",
"stirling.software.enterprise.configuration"
},
exclude = { exclude = {
DataSourceAutoConfiguration.class, DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class DataSourceTransactionManagerAutoConfiguration.class
@ -147,8 +152,10 @@ public class SPDFApplication {
public void init() { public void init() {
String baseUrl = appConfig.getBaseUrl(); String baseUrl = appConfig.getBaseUrl();
String contextPath = appConfig.getContextPath(); String contextPath = appConfig.getContextPath();
String serverPort = appConfig.getServerPort();
baseUrlStatic = baseUrl; baseUrlStatic = baseUrl;
contextPathStatic = contextPath; contextPathStatic = contextPath;
serverPortStatic = serverPort;
String url = baseUrl + ":" + getStaticPort() + contextPath; String url = baseUrl + ":" + getStaticPort() + contextPath;
if (webBrowser != null if (webBrowser != null

View File

@ -24,8 +24,8 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.SPDFApplication; import stirling.software.SPDF.SPDFApplication;
import stirling.software.SPDF.model.ApiEndpoint; import stirling.software.SPDF.model.ApiEndpoint;
import stirling.software.enterprise.security.model.Role; import stirling.software.common.model.enumeration.Role;
import stirling.software.enterprise.security.service.UserServiceEnterpriseInterface; import stirling.software.common.service.UserServiceInterface;
@Service @Service
@Slf4j @Slf4j
@ -34,13 +34,13 @@ public class ApiDocService {
private final Map<String, ApiEndpoint> apiDocumentation = new HashMap<>(); private final Map<String, ApiEndpoint> apiDocumentation = new HashMap<>();
private final ServletContext servletContext; private final ServletContext servletContext;
private final UserServiceEnterpriseInterface userService; private final UserServiceInterface userService;
Map<String, List<String>> outputToFileTypes = new HashMap<>(); Map<String, List<String>> outputToFileTypes = new HashMap<>();
JsonNode apiDocsJsonRootNode; JsonNode apiDocsJsonRootNode;
public ApiDocService( public ApiDocService(
ServletContext servletContext, ServletContext servletContext,
@Autowired(required = false) UserServiceEnterpriseInterface userService) { @Autowired(required = false) UserServiceInterface userService) {
this.servletContext = servletContext; this.servletContext = servletContext;
this.userService = userService; this.userService = userService;
} }

View File

@ -35,8 +35,8 @@ import stirling.software.SPDF.SPDFApplication;
import stirling.software.SPDF.model.PipelineConfig; import stirling.software.SPDF.model.PipelineConfig;
import stirling.software.SPDF.model.PipelineOperation; import stirling.software.SPDF.model.PipelineOperation;
import stirling.software.SPDF.model.PipelineResult; import stirling.software.SPDF.model.PipelineResult;
import stirling.software.enterprise.security.model.Role; import stirling.software.common.model.enumeration.Role;
import stirling.software.enterprise.security.service.UserServiceEnterpriseInterface; import stirling.software.common.service.UserServiceInterface;
@Service @Service
@Slf4j @Slf4j
@ -44,13 +44,13 @@ public class PipelineProcessor {
private final ApiDocService apiDocService; private final ApiDocService apiDocService;
private final UserServiceEnterpriseInterface userService; private final UserServiceInterface userService;
private final ServletContext servletContext; private final ServletContext servletContext;
public PipelineProcessor( public PipelineProcessor(
ApiDocService apiDocService, ApiDocService apiDocService,
@Autowired(required = false) UserServiceEnterpriseInterface userService, @Autowired(required = false) UserServiceInterface userService,
ServletContext servletContext) { ServletContext servletContext) {
this.apiDocService = apiDocService; this.apiDocService = apiDocService;
this.userService = userService; this.userService = userService;

View File

@ -28,8 +28,8 @@ import stirling.software.SPDF.model.SignatureFile;
import stirling.software.SPDF.service.SignatureService; import stirling.software.SPDF.service.SignatureService;
import stirling.software.common.configuration.InstallationPathConfig; import stirling.software.common.configuration.InstallationPathConfig;
import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.configuration.RuntimePathConfig;
import stirling.software.common.service.UserServiceInterface;
import stirling.software.common.util.GeneralUtils; import stirling.software.common.util.GeneralUtils;
import stirling.software.enterprise.security.service.UserServiceEnterpriseInterface;
@Controller @Controller
@Tag(name = "General", description = "General APIs") @Tag(name = "General", description = "General APIs")
@ -37,13 +37,13 @@ import stirling.software.enterprise.security.service.UserServiceEnterpriseInterf
public class GeneralWebController { public class GeneralWebController {
private final SignatureService signatureService; private final SignatureService signatureService;
private final UserServiceEnterpriseInterface userService; private final UserServiceInterface userService;
private final ResourceLoader resourceLoader; private final ResourceLoader resourceLoader;
private final RuntimePathConfig runtimePathConfig; private final RuntimePathConfig runtimePathConfig;
public GeneralWebController( public GeneralWebController(
SignatureService signatureService, SignatureService signatureService,
@Autowired(required = false) UserServiceEnterpriseInterface userService, @Autowired(required = false) UserServiceInterface userService,
ResourceLoader resourceLoader, ResourceLoader resourceLoader,
RuntimePathConfig runtimePathConfig) { RuntimePathConfig runtimePathConfig) {
this.signatureService = signatureService; this.signatureService = signatureService;

View File

@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import stirling.software.SPDF.service.SignatureService; import stirling.software.SPDF.service.SignatureService;
import stirling.software.enterprise.security.service.UserServiceEnterpriseInterface; import stirling.software.common.service.UserServiceInterface;
@Controller @Controller
@RequestMapping("/api/v1/general") @RequestMapping("/api/v1/general")
@ -20,11 +20,11 @@ public class SignatureController {
private final SignatureService signatureService; private final SignatureService signatureService;
private final UserServiceEnterpriseInterface userService; private final UserServiceInterface userService;
public SignatureController( public SignatureController(
SignatureService signatureService, SignatureService signatureService,
@Autowired(required = false) UserServiceEnterpriseInterface userService) { @Autowired(required = false) UserServiceInterface userService) {
this.signatureService = signatureService; this.signatureService = signatureService;
this.userService = userService; this.userService = userService;
} }

View File

@ -1,12 +1,21 @@
package stirling.software.SPDF.service; package stirling.software.SPDF.service;
import java.io.File; import java.io.File;
import java.lang.management.*; import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.*; import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -17,7 +26,7 @@ import org.springframework.stereotype.Service;
import com.posthog.java.PostHog; import com.posthog.java.PostHog;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.enterprise.security.service.UserServiceEnterpriseInterface; import stirling.software.common.service.UserServiceInterface;
@Service @Service
public class PostHogService { public class PostHogService {
@ -25,7 +34,7 @@ public class PostHogService {
private final String uniqueId; private final String uniqueId;
private final String appVersion; private final String appVersion;
private final ApplicationProperties applicationProperties; private final ApplicationProperties applicationProperties;
private final UserServiceEnterpriseInterface userService; private final UserServiceInterface userService;
private final Environment env; private final Environment env;
private boolean configDirMounted; private boolean configDirMounted;
@ -35,7 +44,7 @@ public class PostHogService {
@Qualifier("configDirMounted") boolean configDirMounted, @Qualifier("configDirMounted") boolean configDirMounted,
@Qualifier("appVersion") String appVersion, @Qualifier("appVersion") String appVersion,
ApplicationProperties applicationProperties, ApplicationProperties applicationProperties,
@Autowired(required = false) UserServiceEnterpriseInterface userService, @Autowired(required = false) UserServiceInterface userService,
Environment env) { Environment env) {
this.postHog = postHog; this.postHog = postHog;
this.uniqueId = uuid; this.uniqueId = uuid;