added additional checks for v2/jwt props

This commit is contained in:
Dario Ghunney Ware 2025-09-08 11:58:23 +01:00
parent 2a70461437
commit 9d535ed7a5
5 changed files with 74 additions and 19 deletions

View File

@ -379,7 +379,7 @@ public class ApplicationProperties {
public String getBaseTmpDir() { public String getBaseTmpDir() {
return baseTmpDir != null && !baseTmpDir.isEmpty() return baseTmpDir != null && !baseTmpDir.isEmpty()
? baseTmpDir ? baseTmpDir
: java.lang.System.getProperty("java.io.tmpdir") + "/stirling-pdf"; : java.lang.System.getProperty("java.io.tmpdir") + "stirling-pdf";
} }
@JsonIgnore @JsonIgnore

View File

@ -1,9 +1,8 @@
package stirling.software.SPDF.controller.api.misc; package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames; import java.nio.charset.StandardCharsets;
import io.swagger.v3.oas.annotations.Operation; import java.util.Map;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDNameTreeNode; import org.apache.pdfbox.pdmodel.common.PDNameTreeNode;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript;
@ -14,13 +13,17 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import stirling.software.common.model.api.PDFFile; import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.WebResponseUtils; import stirling.software.common.util.WebResponseUtils;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@RestController @RestController
@RequestMapping("/api/v1/misc") @RequestMapping("/api/v1/misc")
@Tag(name = "Misc", description = "Miscellaneous APIs") @Tag(name = "Misc", description = "Miscellaneous APIs")
@ -55,12 +58,14 @@ public class ShowJavascript {
if (jsCodeStr != null && !jsCodeStr.trim().isEmpty()) { if (jsCodeStr != null && !jsCodeStr.trim().isEmpty()) {
script.append("// File: ") script.append("// File: ")
.append(Filenames.toSimpleFileName(inputFile.getOriginalFilename())) .append(
.append(", Script: ") Filenames.toSimpleFileName(
.append(name) inputFile.getOriginalFilename()))
.append("\n") .append(", Script: ")
.append(jsCodeStr) .append(name)
.append("\n"); .append("\n")
.append(jsCodeStr)
.append("\n");
foundScript = true; foundScript = true;
} }
} }
@ -68,9 +73,10 @@ public class ShowJavascript {
} }
if (!foundScript) { if (!foundScript) {
script = new StringBuilder("PDF '") script =
.append(Filenames.toSimpleFileName(inputFile.getOriginalFilename())) new StringBuilder("PDF '")
.append("' does not contain Javascript"); .append(Filenames.toSimpleFileName(inputFile.getOriginalFilename()))
.append("' does not contain Javascript");
} }
return WebResponseUtils.bytesToWebResponse( return WebResponseUtils.bytesToWebResponse(

View File

@ -5,6 +5,7 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
@ -26,6 +27,9 @@ import stirling.software.proprietary.security.service.UserService;
@RequiredArgsConstructor @RequiredArgsConstructor
public class InitialSecuritySetup { public class InitialSecuritySetup {
@Value("${v2:false}")
private boolean v2Enabled = false;
private final UserService userService; private final UserService userService;
private final TeamService teamService; private final TeamService teamService;
private final ApplicationProperties applicationProperties; private final ApplicationProperties applicationProperties;
@ -43,6 +47,7 @@ public class InitialSecuritySetup {
} }
} }
configureJWTSettings();
assignUsersToDefaultTeamIfMissing(); assignUsersToDefaultTeamIfMissing();
initializeInternalApiUser(); initializeInternalApiUser();
} catch (IllegalArgumentException | SQLException | UnsupportedProviderException e) { } catch (IllegalArgumentException | SQLException | UnsupportedProviderException e) {
@ -51,6 +56,19 @@ public class InitialSecuritySetup {
} }
} }
private void configureJWTSettings() {
ApplicationProperties.Security.Jwt jwtProperties =
applicationProperties.getSecurity().getJwt();
if (!v2Enabled) {
log.debug("v2 is disabled - disabling all JWT features");
jwtProperties.setEnableKeystore(false);
jwtProperties.setEnableKeyRotation(false);
jwtProperties.setEnableKeyCleanup(false);
jwtProperties.setSecureCookie(false);
}
}
private void assignUsersToDefaultTeamIfMissing() { private void assignUsersToDefaultTeamIfMissing() {
Team defaultTeam = teamService.getOrCreateDefaultTeam(); Team defaultTeam = teamService.getOrCreateDefaultTeam();
Team internalTeam = teamService.getOrCreateInternalTeam(); Team internalTeam = teamService.getOrCreateInternalTeam();

View File

@ -62,6 +62,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
protected void doFilterInternal( protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException { throws ServletException, IOException {
validateAndNormalizeJwtSettings();
if (!jwtService.isJwtEnabled()) { if (!jwtService.isJwtEnabled()) {
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
return; return;
@ -112,6 +114,32 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
} }
private void validateAndNormalizeJwtSettings() {
ApplicationProperties.Security.Jwt jwtProperties = securityProperties.getJwt();
boolean enableKeystore = jwtProperties.isEnableKeystore();
boolean enableKeyRotation = jwtProperties.isEnableKeyRotation();
boolean enableKeyCleanup = jwtProperties.isEnableKeyCleanup();
boolean secureCookie = jwtProperties.isSecureCookie();
// If any JWT property is disabled, disable all JWT properties for consistency
if (!enableKeystore || !enableKeyRotation || !enableKeyCleanup || !secureCookie) {
log.debug(
"One or more JWT properties are disabled - normalizing all JWT settings to false");
log.debug(
"Current settings: keystore={}, rotation={}, cleanup={}, secureCookie={}",
enableKeystore,
enableKeyRotation,
enableKeyCleanup,
secureCookie);
jwtProperties.setEnableKeystore(false);
jwtProperties.setEnableKeyRotation(false);
jwtProperties.setEnableKeyCleanup(false);
jwtProperties.setSecureCookie(false);
}
}
private boolean apiKeyExists(HttpServletRequest request, HttpServletResponse response) private boolean apiKeyExists(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException { throws IOException, ServletException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

View File

@ -75,8 +75,11 @@ public class CustomUserDetailsService implements UserDetailsService {
*/ */
private AuthenticationType determinePreferredSSOType() { private AuthenticationType determinePreferredSSOType() {
// Check what SSO types are enabled and prefer in order: OAUTH2 > SAML2 > fallback to OAUTH2 // Check what SSO types are enabled and prefer in order: OAUTH2 > SAML2 > fallback to OAUTH2
boolean oauth2Enabled = securityProperties.getOauth2() != null && securityProperties.getOauth2().getEnabled(); boolean oauth2Enabled =
boolean saml2Enabled = securityProperties.getSaml2() != null && securityProperties.getSaml2().getEnabled(); securityProperties.getOauth2() != null
&& securityProperties.getOauth2().getEnabled();
boolean saml2Enabled =
securityProperties.getSaml2() != null && securityProperties.getSaml2().getEnabled();
if (oauth2Enabled) { if (oauth2Enabled) {
return AuthenticationType.OAUTH2; return AuthenticationType.OAUTH2;