Skip to content

Commit cf3813e

Browse files
Kbayeromjabascal10JocLRojasCopilotelmilan06
authored
Release/v11.1.0 (#1504)
* feat: update database schema and properties for v11 release * feat: refactor constants for log event data and update Elasticsearch query * feat: refactor event handling to use Event type and update related components Signed-off-by: Manuel Abascal <[email protected]> * feat: enhance agent console UI and improve password input handling Signed-off-by: Manuel Abascal <[email protected]> * feat: refactor layout and styling for active directory components Signed-off-by: Manuel Abascal <[email protected]> * feat: enhance add rule component with after events section and modal styling Signed-off-by: Manuel Abascal <[email protected]> * feat: improve layout and styling for active directory event component Signed-off-by: Manuel Abascal <[email protected]> * feat: add changelogs to hide compliance menu items and update filters visualization * feat: filter compliance standards by ID in the HTTP response Signed-off-by: Manuel Abascal <[email protected]> * feat: implement search functionality for fields in condition item component Signed-off-by: Manuel Abascal <[email protected]> * feat: remove duplicate alert badge fields and clean up HTML structure Signed-off-by: Manuel Abascal <[email protected]> * feat: remove loading spinner from visualization preview tooltip Signed-off-by: Manuel Abascal <[email protected]> * feat: update aggregation field mappings in filters visualization * feat: comment out documentation alert in logstash filter create component Signed-off-by: Manuel Abascal <[email protected]> * feat: add changelog to disable correlation rules with regex * feat: update placement attribute to support multiple positions in alert action select component Signed-off-by: Manuel Abascal <[email protected]> * feat: condition builder visibility based on fields availability Signed-off-by: Manuel Abascal <[email protected]> * feat: add system owner field to alert response rules and update related logic * feat: add systemOwner filter to playbooks component Signed-off-by: Manuel Abascal <[email protected]> * feat: add system owner field to alert response rules and update related logic * feat: enhance playbook component with improved layout and functionality Signed-off-by: Manuel Abascal <[email protected]> * feat: enhance playbook component with improved layout and functionality Signed-off-by: Manuel Abascal <[email protected]> * feat: enhance playbook component with improved layout and functionality Signed-off-by: Manuel Abascal <[email protected]> * feat: add system owner field to alert response rules and update related logic * feat: enhance playbook component with improved layout and functionality Signed-off-by: Manuel Abascal <[email protected]> * feat: update agent handling strategy description for clarity and context Signed-off-by: Manuel Abascal <[email protected]> * feat: update agent handling strategy description for clarity and context Signed-off-by: Manuel Abascal <[email protected]> * fix: change PostgreSQL logger level from WARN to ERROR * feat: update log handling and display logic for improved clarity and consistency Signed-off-by: Manuel Abascal <[email protected]> * feat: update log filter selection to improve user experience Signed-off-by: Manuel Abascal <[email protected]> * fix: handle potential null value in audits length check Signed-off-by: Manuel Abascal <[email protected]> * fix: update filterBySelect method to accept a generic field type Signed-off-by: Manuel Abascal <[email protected]> * feat: update workflows and send to new cm in gcp * feat: include script to compile installer * fix: resolve workflow errors and improve cross-platform compatibility * fix problem with agent SIGN KEY * feat: implement service to automatically assign asset groups to alerts * feat: add asset group fields to alert constants and configuration Signed-off-by: Manuel Abascal <[email protected]> * feat(agent/syslog): add RFC 5424 octet counting framing support and improve message handling * fix: always update pending versions * improve v11 changelog * feat: enhance playbook UI and loading behavior, add new alert fields Signed-off-by: Manuel Abascal <[email protected]> * feat(oauth2): implement corporate authentication with OAuth2 support * feat(identity-provider): add OAuth2/OpenID Connect provider management Signed-off-by: Manuel Abascal <[email protected]> * feat(identity-provider): add OAuth2/OpenID Connect provider management Signed-off-by: Manuel Abascal <[email protected]> * feat: implement service to automatically assign asset groups to alerts * feat(identity-provider): add OAuth2/OpenID Connect provider management Signed-off-by: Manuel Abascal <[email protected]> * feat(oauth2): enhance corporate authentication with additional fields and event handling * feat: add CrowdStrike plugin core implementation * feat: add gRPC configuration management for CrowdStrike * feat(oauth2): enhance corporate authentication with additional fields and event handling * feat(oauth2): enhance corporate authentication with additional fields and event handling * feat(identity-provider): add OAuth2/OpenID Connect provider management Signed-off-by: Manuel Abascal <[email protected]> * feat(oauth2): enhance corporate authentication with additional fields and event handling * feat(identity-provider): add OAuth2/OpenID Connect provider management Signed-off-by: Manuel Abascal <[email protected]> * refactor: update version info handling and clean up community module display Signed-off-by: Manuel Abascal <[email protected]> * Update frontend/src/app/shared/components/auth/login/login.component.ts Co-authored-by: Copilot <[email protected]> * Update frontend/src/app/shared/components/auth/login-providers/login-providers.component.ts Co-authored-by: Copilot <[email protected]> * Update backend/src/main/java/com/park/utmstack/config/SecurityConfiguration.java Co-authored-by: Copilot <[email protected]> * Update backend/src/main/java/com/park/utmstack/service/idp_provider/IdentityProviderService.java Co-authored-by: Copilot <[email protected]> * Update frontend/src/app/app-management/identity-provider/shared/components/provider-form/provider-form.component.ts Co-authored-by: Copilot <[email protected]> * feat(oauth2): enhance corporate authentication with additional fields and event handling * refactor: simplify request structure and improve provider toggle logic Signed-off-by: Manuel Abascal <[email protected]> * feat(oauth2): implement enterprise version handling for identity providers Signed-off-by: Manuel Abascal <[email protected]> * feat: add adversary view menu and associated authorities to database * feat: add adversary management module with routing and view components Signed-off-by: Manuel Abascal <[email protected]> * refactor: remove deprecated standalone plugin architecture * feat: add adversary management module with routing and view components Signed-off-by: Manuel Abascal <[email protected]> * feat: implement adversary alerts management with new DTOs and service * feat: add SQL query support to LogExplorer via OpenSearch * feat: add SQL query support to LogExplorer via OpenSearch * feat: implement adversary alerts graph and service for data retrieval Signed-off-by: Manuel Abascal <[email protected]> * feat: enhance timezone handling by dynamically generating timezone list Signed-off-by: Manuel Abascal <[email protected]> * feat: enhance timezone handling by dynamically generating timezone list Signed-off-by: Manuel Abascal <[email protected]> * feat: add adversary management module with routing and view components Signed-off-by: Manuel Abascal <[email protected]> * feat: add adversary management module with routing and view components Signed-off-by: Manuel Abascal <[email protected]> * feat: add adversary view menu and associated authorities to database * feat: implement adversary alerts graph and service for data retrieval Signed-off-by: Manuel Abascal <[email protected]> * feat: implement adversary alerts management with new DTOs and service * feat: enhance adversary alerts graph layout and styling for improved visualization Signed-off-by: Manuel Abascal <[email protected]> * feat: enhance adversary alerts graph layout and styling for improved visualization Signed-off-by: Manuel Abascal <[email protected]> * fix[bitdefender-plugin]: make StartServer blocking and remove retry loop * update macos guide * feat: enhance adversary alerts graph layout and styling for improved visualization Signed-off-by: Manuel Abascal <[email protected]> * feat: enhance adversary alerts graph layout and styling for improved visualization Signed-off-by: Manuel Abascal <[email protected]> * feat: implement adversary alerts management with new DTOs and service * fix: adjust TFA expiration time to use configurable constant * feat: conditionally render module card based on module name Signed-off-by: Manuel Abascal <[email protected]> * feat: add application version info retrieval functionality * feat: add application version info retrieval functionality Signed-off-by: Manuel Abascal <[email protected]> * feat: compliance report view component * feat: add SQL query support to LogExplorer via OpenSearch * feat: add SQL query support to LogExplorer via OpenSearch * feat(saml): implement SAML authentication support with identity provider configuration * feat(saml): implement SAML authentication support with identity provider configuration Signed-off-by: Manuel Abascal <[email protected]> * feat: add application version info retrieval functionality * fix: remove conditional rendering for AS_400 module and filter out in module retrieval Signed-off-by: Manuel Abascal <[email protected]> * feat(saml): enhance SAML authentication success handler to include role-based authorities * feat(o365-plugin): add multi-cloud environment support for Microsoft Cloud (Commercial, GCC, GCC High, DoD) * feat: add exception handling for MethodArgumentNotValidException and update UtmModuleConfigValidator logic * fix(o365-plugin): Remove invalid field check and add multi-cloud support - Implement cloud-aware connection checking per authority - Use correct endpoints and scopes for each cloud environment * feat: add SQL query support to LogExplorer via OpenSearch * feat(o365-plugin): add Office 365 cloud environment configuration options * Update backend/src/main/resources/config/liquibase/changelog/20251125001_add_environment_o365_integration.xml Co-authored-by: Copilot <[email protected]> * Update backend/src/main/java/com/park/utmstack/domain/application_modules/factory/impl/ModuleO365.java Co-authored-by: Copilot <[email protected]> * Update backend/src/main/java/com/park/utmstack/domain/application_modules/UtmModuleGroupConfiguration.java Co-authored-by: Copilot <[email protected]> * feat: add SQL query support to LogExplorer via OpenSearch * feat: add SQL query support to LogExplorer via OpenSearch * feat: add SQL query support to LogExplorer via OpenSearch * feat: add SQL query support to LogExplorer via OpenSearch * feat: add SQL query support to LogExplorer via OpenSearch * fix: update file permissions from 777 to 755 for security improvements * feat(azure plugin): enhance Azure cloud detection and connection validation * feat(o365_validation-modules-config): add Management API validation and multi-cloud endpoint support * feat(header): integrate version info display and update logic Signed-off-by: Manuel Abascal <[email protected]> * refactor: rename UtmStackConnectionService to ModuleConfigurationValidationService and enhance validation logic * feat(exception-handling): add ApiException class and global exception handler * feat: add SQL query support to LogExplorer via OpenSearch * feat: add SQL query support to LogExplorer via OpenSearch * feat(int-generic-group-config): improve searchable option based on config options length Signed-off-by: Manuel Abascal <[email protected]> * feat(int-generic-group-config): improve searchable option based on config options length Signed-off-by: Manuel Abascal <[email protected]> * fix(modules-config): disable CROWDSTRIKE module not implemented in backend. * refactor(plugins): standardize logging with catcher * feat(saml): update identity provider configuration to include metadata URL and remove deprecated fields * style(dashboard): adjust padding and layout for improved UI consistency Signed-off-by: Manuel Abascal <[email protected]> * fix: optimize cloud detection logic in connection string parsing * feat(elastic-filter-time): enhance time filter functionality and update UI interactions Signed-off-by: Manuel Abascal <[email protected]> * feat(azure): extract individual records from Azure Event Hub logs Parse Azure logs with 'records' array structure and send each record as a separate log entry for better indexing and security analysis. Maintains backward compatibility for logs without records array. * fix(modules-config): remove gin default logger middleware to eliminate non-standardized HTTP logs while maintaining catcher logging standard and panic protection. * refactor(azure-filter): deleted 'Expand log.records' data to improve parsing * refactor(gcp-filter): deleted 'Expand jsonPayload.structuredRdata' data to improve parsing * update the version of the Azure and GCP filters * feat(saml): update identity provider configuration to include metadata URL and remove deprecated fields * feat(provider): add SAML 2.0 support with metadata URL and service provider configuration Signed-off-by: Manuel Abascal <[email protected]> * feat(saml): enhance identity provider creation with multipart form data and encryption for private key * feat(provider): add SAML 2.0 support with metadata URL and service provider configuration Signed-off-by: Manuel Abascal <[email protected]> * fix(totp): prevent potential error by checking subscription before unsubscribe Signed-off-by: Manuel Abascal <[email protected]> * style(totp): comment out unused email resend container for cleaner code Signed-off-by: Manuel Abascal <[email protected]> * style(utm-code-view): add word-break class to code element for better text handling Signed-off-by: Manuel Abascal <[email protected]> * feat(filters): add Azure and GCP filters with updated field mappings and severity handling * refactor(ModuleSocAi): remove unused getName method for cleaner code * fix(deployment-pipeline): update tag pattern for v10 to support semantic versioning * chore(changelog): update release notes for UTMStack v11.0.3 with fixed issues and performance improvements * chore(changelog): update release notes for UTMStack v11.0.3 with fixed issues and performance improvements * feat(authentication): add SAML and OIDC support with validation for private keys and certificates * chore(master.xml): remove outdated environment integration and filter update changelogs * feat(identity-provider): enhance provider management with file uploads and validation Signed-off-by: Manuel Abascal <[email protected]> * feat(authentication): enhance SAML and OIDC support with file validation and metadata URL checks * feat(identity-provider): enhance provider management with file uploads and validation Signed-off-by: Manuel Abascal <[email protected]> * feat(identity-provider): enhance provider management with file uploads and validation Signed-off-by: Manuel Abascal <[email protected]> * Refactor adversary alerts graph component and update no data display Signed-off-by: Manuel Abascal <[email protected]> * Remove redundant getName() method override in ModuleSocAi * Update frontend/src/app/data-management/alert-management/shared/components/filters/alert-generic-filter/alert-generic-filter.component.ts Co-authored-by: Copilot <[email protected]> * feat: add SQL query support to LogExplorer via OpenSearch * feat: add SQL query support to LogExplorer via OpenSearch * feat: enhance LogExplorer with SQL query support and custom keyword suggestions * Update backend/src/main/java/com/park/utmstack/service/dto/elastic/SqlSearchDto.java Co-authored-by: Copilot <[email protected]> * feat: enhance identity provider management with role requirements and UI improvements Signed-off-by: Manuel Abascal <[email protected]> * feat: update login components for improved styling and provider text Signed-off-by: Manuel Abascal <[email protected]> * feat: add loading screen with spinner and enhance app initialization Signed-off-by: Manuel Abascal <[email protected]> * feat(agents): update agent guide with Kali Linux tab and enhance installation command structure * feat: add SAML OIDC corporate authentication configuration fields * feat: add SAML OIDC corporate authentication support with SP entity ID and ACS URL Signed-off-by: Manuel Abascal <[email protected]> * feat(api-keys): implement API key management with creation, retrieval, update, and deletion functionalities * feat: integrate app version management and enterprise feature directive Signed-off-by: Manuel Abascal <[email protected]> * feat: enhance SAML2 login handlers with role validation and logging * feat: enhance SAML2 login handlers with role validation and logging * feat: enhance SAML2 login handlers with role validation and logging * feat: integrate app version management and enterprise feature directive Signed-off-by: Manuel Abascal <[email protected]> * feat: update API route for version checking to check-for-updates Signed-off-by: Manuel Abascal <[email protected]> * feat: remove client secret display from provider details Signed-off-by: Manuel Abascal <[email protected]> * fix: update application version file path and improve pagination offset calculation * fix: update application version file path and improve pagination offset calculation * fix: update opensearch-connector version to 1.0.4 * feat: enhance enterprise module directive to support dynamic menu names and icons Signed-off-by: Manuel Abascal <[email protected]> * fix: streamline loading state management in playbook service and clean up filter parameters in playbooks component Signed-off-by: Manuel Abascal <[email protected]> * fix[installer]: install latest version * fix: handle version info loading error gracefully by resolving instead of rejecting Signed-off-by: Manuel Abascal <[email protected]> * fix: correct XML tag formatting in installation scripts for AS400 collectors Signed-off-by: Manuel Abascal <[email protected]> * chore: update CHANGELOG for UTMStack v11.1.0 release with new features and enhancements Signed-off-by: Manuel Abascal <[email protected]> --------- Signed-off-by: Manuel Abascal <[email protected]> Co-authored-by: Manuel Abascal <[email protected]> Co-authored-by: JocLRojas <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: Elena Lopez Milan <[email protected]> Co-authored-by: Osmany Montero <[email protected]> Co-authored-by: Yadian Llada Lopez <[email protected]>
1 parent 56bf79d commit cf3813e

File tree

133 files changed

+5817
-331
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+5817
-331
lines changed

CHANGELOG.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
# UTMStack 11.0.3
1+
# UTMStack 11.1.0
22

3-
This is the release notes for **UTMStack v11.0.3**, a minor update focused on bug fixes and performance improvements.
3+
These are the release notes for **UTMStack v11.1.0**, highlighting new features, bug fixes, and performance improvements.
44

5-
## Fixed Issues
5+
## Features
66

7-
- Fixed a bug in the SOC-AI integration that caused occasional failures when generating insights.
8-
- Fixed a bug when trying to enroll and authenticate by TFA.
9-
10-
## Enhancements
11-
12-
- SIEM configuration now adapts to the Sovereign Cloud Model implemented by the provider in each region for Azure and Microsoft 365 integrations.
7+
- Introduced SQL query support in LogExplorer, enabling users to execute SQL queries on OpenSearch indices directly from the user interface.
8+
- Added an interactive Adversary View to the Threat Management module, providing a graphical, filterable visualization of relationships between Adversaries, their generated Alerts, and associated Echoes.

backend/pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@
192192
<groupId>org.springframework.boot</groupId>
193193
<artifactId>spring-boot-starter-mail</artifactId>
194194
</dependency>
195+
<!-- SAML2 Service Provider -->
196+
<dependency>
197+
<groupId>org.springframework.security</groupId>
198+
<artifactId>spring-security-saml2-service-provider</artifactId>
199+
</dependency>
195200
<dependency>
196201
<groupId>org.springframework.boot</groupId>
197202
<artifactId>spring-boot-starter-security</artifactId>
@@ -278,7 +283,7 @@
278283
<dependency>
279284
<groupId>com.utmstack</groupId>
280285
<artifactId>opensearch-connector</artifactId>
281-
<version>1.0.2</version>
286+
<version>1.0.4</version>
282287
</dependency>
283288
<dependency>
284289
<groupId>jakarta.json</groupId>

backend/src/main/java/com/park/utmstack/config/Constants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public final class Constants {
140140
// ----------------------------------------------------------------------------------
141141
public static final String STATISTICS_INDEX_PATTERN = "v11-statistics-*";
142142
public static final String V11_API_ACCESS_LOGS = "v11-api-access-logs-*";
143+
public static final String V11_ALERTS_INDEX_PATTERN = "v11-alert-*";
143144

144145
// Logging
145146
public static final String TRACE_ID_KEY = "traceId";

backend/src/main/java/com/park/utmstack/config/SecurityConfiguration.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
package com.park.utmstack.config;
22

3-
import com.park.utmstack.loggin.api_key.ApiKeyUsageLoggingService;
4-
import com.park.utmstack.loggin.filter.MdcCleanupFilter;
53
import com.park.utmstack.repository.UserRepository;
64
import com.park.utmstack.security.AuthoritiesConstants;
75
import com.park.utmstack.security.api_key.ApiKeyConfigurer;
86
import com.park.utmstack.security.api_key.ApiKeyFilter;
97
import com.park.utmstack.security.internalApiKey.InternalApiKeyConfigurer;
108
import com.park.utmstack.security.internalApiKey.InternalApiKeyProvider;
119
import com.park.utmstack.security.jwt.JWTConfigurer;
12-
import com.park.utmstack.security.jwt.JWTFilter;
1310
import com.park.utmstack.security.jwt.TokenProvider;
14-
import com.park.utmstack.service.api_key.ApiKeyService;
11+
import com.park.utmstack.security.saml.Saml2LoginFailureHandler;
12+
import com.park.utmstack.security.saml.Saml2LoginSuccessHandler;
1513
import lombok.RequiredArgsConstructor;
16-
import org.apache.commons.net.util.SubnetUtils;
1714
import org.springframework.beans.factory.BeanInitializationException;
18-
import org.springframework.boot.web.servlet.FilterRegistrationBean;
1915
import org.springframework.context.annotation.Bean;
2016
import org.springframework.context.annotation.Configuration;
2117
import org.springframework.context.annotation.Import;
@@ -35,10 +31,10 @@
3531
import org.springframework.web.filter.CorsFilter;
3632
import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;
3733

34+
3835
import javax.annotation.PostConstruct;
3936
import javax.servlet.http.HttpServletResponse;
40-
import java.util.concurrent.ConcurrentHashMap;
41-
import java.util.concurrent.ConcurrentMap;
37+
4238

4339
@Configuration
4440
@RequiredArgsConstructor
@@ -53,6 +49,8 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
5349
private final CorsFilter corsFilter;
5450
private final InternalApiKeyProvider internalApiKeyProvider;
5551
private final ApiKeyFilter apiKeyFilter;
52+
private final UserRepository userRepository;
53+
5654

5755
@PostConstruct
5856
public void init() {
@@ -110,7 +108,9 @@ public void configure(HttpSecurity http) throws Exception {
110108
.antMatchers("/api/releaseInfo").permitAll()
111109
.antMatchers("/api/account/reset-password/init").permitAll()
112110
.antMatchers("/api/account/reset-password/finish").permitAll()
111+
.antMatchers("/api/utm-providers").permitAll()
113112
.antMatchers("/api/images/all").permitAll()
113+
.antMatchers("/api/info/version").permitAll()
114114
.antMatchers("/api/enrollment/**").hasAnyAuthority(AuthoritiesConstants.PRE_VERIFICATION_USER)
115115
.antMatchers("/api/tfa/verify-code").hasAnyAuthority(AuthoritiesConstants.PRE_VERIFICATION_USER, AuthoritiesConstants.USER, AuthoritiesConstants.ADMIN)
116116
.antMatchers("/api/tfa/refresh").hasAnyAuthority(AuthoritiesConstants.PRE_VERIFICATION_USER, AuthoritiesConstants.USER, AuthoritiesConstants.ADMIN)
@@ -126,6 +126,12 @@ public void configure(HttpSecurity http) throws Exception {
126126
.antMatchers("/management/info").permitAll()
127127
.antMatchers("/management/**").hasAnyAuthority(AuthoritiesConstants.ADMIN, AuthoritiesConstants.USER)
128128
.and()
129+
.saml2Login()
130+
.successHandler(new Saml2LoginSuccessHandler(tokenProvider,
131+
userRepository,
132+
saml2LoginFailureHandler()))
133+
.failureHandler(new Saml2LoginFailureHandler())
134+
.and()
129135
.apply(securityConfigurerAdapterForJwt())
130136
.and()
131137
.apply(securityConfigurerAdapterForInternalApiKey())
@@ -147,4 +153,10 @@ private ApiKeyConfigurer securityConfigurerAdapterForApiKey() {
147153
return new ApiKeyConfigurer(apiKeyFilter);
148154
}
149155

156+
157+
@Bean
158+
public Saml2LoginFailureHandler saml2LoginFailureHandler() {
159+
return new Saml2LoginFailureHandler();
160+
}
161+
150162
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.park.utmstack.config.saml;
2+
3+
import com.park.utmstack.repository.idp_provider.IdentityProviderConfigRepository;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
@Configuration
8+
public class OAuth2ClientConfig {
9+
10+
@Bean
11+
public SamlRelyingPartyRegistrationRepository clientRegistrationRepository(IdentityProviderConfigRepository repo) {
12+
return new SamlRelyingPartyRegistrationRepository(repo);
13+
}
14+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.park.utmstack.config.saml;
2+
3+
import com.park.utmstack.repository.idp_provider.IdentityProviderConfigRepository;
4+
import com.park.utmstack.util.events.ProviderChangedEvent;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.context.event.EventListener;
7+
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
8+
import org.springframework.stereotype.Component;
9+
10+
@Component
11+
@RequiredArgsConstructor
12+
public class ProviderChangeListener {
13+
14+
private final RelyingPartyRegistrationRepository repository;
15+
private final IdentityProviderConfigRepository identityProviderConfigRepository;
16+
17+
@EventListener
18+
public void handleProviderChanged(ProviderChangedEvent event) {
19+
if (repository instanceof SamlRelyingPartyRegistrationRepository customRepo) {
20+
customRepo.reloadProviders(identityProviderConfigRepository);
21+
}
22+
}
23+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.park.utmstack.config.saml;
2+
3+
import com.park.utmstack.config.Constants;
4+
import com.park.utmstack.domain.idp_provider.IdentityProviderConfig;
5+
import com.park.utmstack.repository.idp_provider.IdentityProviderConfigRepository;
6+
import com.park.utmstack.util.CipherUtil;
7+
import com.park.utmstack.util.saml.PemUtils;
8+
import org.springframework.security.saml2.core.Saml2X509Credential;
9+
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
10+
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
11+
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrations;
12+
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
13+
14+
import java.security.PrivateKey;
15+
import java.security.cert.X509Certificate;
16+
import java.util.Map;
17+
import java.util.concurrent.ConcurrentHashMap;
18+
19+
public class SamlRelyingPartyRegistrationRepository implements RelyingPartyRegistrationRepository {
20+
21+
private final Map<String, RelyingPartyRegistration> registrations = new ConcurrentHashMap<>();
22+
23+
public SamlRelyingPartyRegistrationRepository(IdentityProviderConfigRepository jpaProviderRepository) {
24+
loadProviders(jpaProviderRepository);
25+
}
26+
27+
@Override
28+
public RelyingPartyRegistration findByRegistrationId(String registrationId) {
29+
return registrations.get(registrationId);
30+
}
31+
32+
public void reloadProviders(IdentityProviderConfigRepository jpaProviderRepository) {
33+
registrations.clear();
34+
loadProviders(jpaProviderRepository);
35+
}
36+
37+
private void loadProviders(IdentityProviderConfigRepository jpaProviderRepository) {
38+
jpaProviderRepository.findAllByActiveTrue().forEach(entity -> {
39+
RelyingPartyRegistration registration = buildRelyingPartyRegistration(entity);
40+
registrations.put(entity.getProviderType().name().toLowerCase(), registration);
41+
});
42+
}
43+
44+
private RelyingPartyRegistration buildRelyingPartyRegistration(IdentityProviderConfig entity) {
45+
46+
PrivateKey spKey = PemUtils.parsePrivateKey(CipherUtil.decrypt(
47+
entity.getSpPrivateKeyPem(),
48+
System.getenv(Constants.ENV_ENCRYPTION_KEY)
49+
));
50+
X509Certificate spCert = PemUtils.parseCertificate(entity.getSpCertificatePem());
51+
52+
return RelyingPartyRegistrations
53+
.fromMetadataLocation(entity.getMetadataUrl())
54+
.registrationId(entity.getName())
55+
.entityId(entity.getSpEntityId())
56+
.assertionConsumerServiceLocation(entity.getSpAcsUrl())
57+
.signingX509Credentials(c -> c.add(Saml2X509Credential.signing(spKey, spCert)))
58+
.build();
59+
}
60+
61+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.park.utmstack.domain.idp_provider;
2+
3+
import com.park.utmstack.domain.idp_provider.enums.ProviderType;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Data;
6+
import lombok.EqualsAndHashCode;
7+
import lombok.NoArgsConstructor;
8+
import org.hibernate.annotations.Type;
9+
10+
import javax.persistence.*;
11+
import java.time.LocalDateTime;
12+
13+
@Entity
14+
@Table(name = "utm_identity_provider_config")
15+
@Data
16+
@NoArgsConstructor
17+
@AllArgsConstructor
18+
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
19+
public class IdentityProviderConfig {
20+
21+
@Id
22+
@GeneratedValue(strategy = GenerationType.IDENTITY)
23+
@EqualsAndHashCode.Include
24+
private Long id;
25+
26+
@Column(nullable = false)
27+
private String name;
28+
29+
@Enumerated(EnumType.STRING)
30+
@Column(nullable = false)
31+
private ProviderType providerType;
32+
33+
/**
34+
* Metadata URL of the IdP (Keycloak, Okta, Azure, etc.)
35+
* Example: https://localhost:8443/realms/UTMSTACK/protocol/saml/descriptor
36+
*/
37+
@Column(name = "metadata_url", nullable = false, length = 512)
38+
private String metadataUrl;
39+
40+
/**
41+
* Service Provider private key in PEM format
42+
* Used to sign AuthnRequests and other outgoing SAML messages
43+
*/
44+
@Type(type = "text")
45+
@Column(name = "sp_private_key_pem", nullable = false, columnDefinition = "TEXT")
46+
private String spPrivateKeyPem;
47+
48+
/**
49+
* Service Provider public certificate in PEM format
50+
* Shared with IdP so it can validate signed requests from the SP
51+
*/
52+
@Type(type = "text")
53+
@Column(name = "sp_certificate_pem", nullable = false, columnDefinition = "TEXT")
54+
private String spCertificatePem;
55+
56+
@Column(name = "sp_entity_id", nullable = false, length = 512)
57+
private String spEntityId;
58+
59+
@Column(name = "sp_acs_url", nullable = false, length = 512)
60+
private String spAcsUrl;
61+
62+
/**
63+
* Flag to enable or disable this IdP configuration
64+
*/
65+
@Column(nullable = false)
66+
private Boolean active;
67+
68+
/**
69+
* Timestamp when the record was created
70+
*/
71+
@Column(nullable = false)
72+
private LocalDateTime createdAt;
73+
74+
/**
75+
* Timestamp when the record was last updated
76+
*/
77+
@Column(nullable = false)
78+
private LocalDateTime updatedAt;
79+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.park.utmstack.domain.idp_provider.enums;
2+
3+
public enum ProviderType {
4+
GOOGLE,
5+
KEYCLOAK,
6+
OKTA,
7+
MICROSOFT;
8+
9+
public static ProviderType from(String value) {
10+
return ProviderType.valueOf(value.toUpperCase());
11+
}
12+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.park.utmstack.repository.idp_provider;
2+
3+
import com.park.utmstack.domain.idp_provider.IdentityProviderConfig;
4+
import com.park.utmstack.domain.idp_provider.enums.ProviderType;
5+
import org.springframework.data.jpa.repository.JpaRepository;
6+
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
7+
import org.springframework.stereotype.Repository;
8+
9+
import java.util.List;
10+
import java.util.Optional;
11+
12+
@Repository
13+
public interface IdentityProviderConfigRepository extends JpaRepository<IdentityProviderConfig, Long>, JpaSpecificationExecutor<IdentityProviderConfig> {
14+
15+
Optional<IdentityProviderConfig> findByProviderTypeAndActiveTrue(ProviderType providerType);
16+
17+
List<IdentityProviderConfig> findAllByActiveTrue();
18+
}

0 commit comments

Comments
 (0)