Skip to content

Commit

Permalink
Merge pull request #113 from catenax-ng/no-miw-vrel3
Browse files Browse the repository at this point in the history
feat: hosting static jsonld files
  • Loading branch information
tomaszbarwicki authored Apr 29, 2024
2 parents d5803ce + 9d1e542 commit c3861c7
Show file tree
Hide file tree
Showing 25 changed files with 297 additions and 168 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
### Fixed
- Fixed the CVE-2024-22259 and CVE-2024-22257 security issue

### Changed
- unused configuration entries in application.yml are not mandatory (e.g. `app.usersDetails.custodianWallet`
for catena-x-ctx profile)
- if `test` profile is active then authentication is turned off for the service
- files placed to the resources/verifiablecredentials directory are served by the service's web-server as static
resources. If a file has .jsonld extension then correct `Content-Type` is set for it even if extension is missed in URL
(e.g. for URL https://{SERVICE_HOST}/context/sd-document-v2210 the file resources/verifiablecredentials/sd-document-v2210.jsonld
is returned while `Content-Type` is set to `application/ld+json`)
- correct `Content-Type` is set for YAML extension (can be `application/yaml` or `text/yaml`)

## [2.1.10] - 2024-02-28
### Changed
- Updated Spring Boot to 3.2.3 to fix CVE-2024-22234 and CVE-2024-22243
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ For the VC we have to provide valid JSON context where we have a reference to an
from known ontology. This object carries the claims the SD-Factory signs. The document
is published on the github repository of the project. The vocabulary URL can be changed
when will be provided by Trusted Framework. Currently, we support
[a vocabulary for Version 22.10 of Trust Framework](src/main/resources/verifiablecredentials/sd-document-v2210).
[a vocabulary for Version 22.10 of Trust Framework](src/main/resources/verifiablecredentials/sd-document-v2210.jsonld).

# REST Interface

Expand Down
1 change: 1 addition & 0 deletions charts/sdfactory/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Helm Charts for SD Factory application. Self-Description Factory component is re
| sdfactory.secret.jwkSetUri | string | `""` | JWK Set URI |
| sdfactory.secret.realm | string | `""` | Keycloak Realm detail |
| sdfactory.secret.resource | string | `""` | Keycloak Resource detail |
| sdfactory.secret.verifycredentialsUri | string | `""` | Details for Verifying Client uri |
| securityContext.allowPrivilegeEscalation | bool | `false` | |
| securityContext.capabilities.drop[0] | string | `"ALL"` | |
| securityContext.runAsGroup | int | `1000` | |
Expand Down
5 changes: 5 additions & 0 deletions charts/sdfactory/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ spec:
secretKeyRef:
name: {{ include "sdfactory.applicationSecret.name" . }}
key: clearingHouse-clientSecret
- name: APP_VERIFIABLECREDENTIALS_SCHEMA2210URL
valueFrom:
secretKeyRef:
name: {{ include "sdfactory.applicationSecret.name" . }}
key: verifycredentials-uri

readinessProbe:
tcpSocket:
Expand Down
1 change: 1 addition & 0 deletions charts/sdfactory/templates/secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ stringData:
clearingHouse-realm: {{ .Values.sdfactory.secret.clearingHouseRealm | default (printf "%s-%s" "realm" (randAlpha 6)) }}
clearingHouse-clientId: {{ .Values.sdfactory.secret.clearingHouseClientId | default (randAlphaNum 16) }}
clearingHouse-clientSecret: {{ .Values.sdfactory.secret.clearingHouseClientSecret | default (randAlphaNum 16) }}
verifycredentials-uri: {{ .Values.sdfactory.secret.verifycredentialsUri|default "https://verifycredential-uri" }}
1 change: 1 addition & 0 deletions charts/sdfactory/values-beta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ sdfactory:
clearingHouseRealm: "<path:essential-services/data/custodian-beta#clearingHouse-realm>"
clearingHouseClientId: "<path:essential-services/data/custodian-beta#clearingHouse-clientId>"
clearingHouseClientSecret: "<path:essential-services/data/custodian-beta#clearingHouse-clientSecret>"
verifycredentialsUri: "<path:essential-services/data/custodian-beta#verifiableCredentials-schema2210Url>"
1 change: 1 addition & 0 deletions charts/sdfactory/values-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ sdfactory:
clearingHouseRealm: "<path:essential-services/data/custodian-dev#clearingHouse-realm>"
clearingHouseClientId: "<path:essential-services/data/custodian-dev#clearingHouse-clientId>"
clearingHouseClientSecret: "<path:essential-services/data/custodian-dev#clearingHouse-clientSecret>"
verifycredentialsUri: "<path:essential-services/data/custodian-dev#verifiableCredentials-schema2210Url>"
1 change: 1 addition & 0 deletions charts/sdfactory/values-int.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ sdfactory:
clearingHouseRealm: "<path:essential-services/data/custodian#clearingHouse-realm>"
clearingHouseClientId: "<path:essential-services/data/custodian#clearingHouse-clientId>"
clearingHouseClientSecret: "<path:essential-services/data/custodian#clearingHouse-clientSecret>"
verifycredentialsUri: "<path:essential-services/data/custodian#verifiableCredentials-schema2210Url>"
2 changes: 1 addition & 1 deletion charts/sdfactory/values-pen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ sdfactory:
clearingHouseRealm: "<path:essential-services/data/custodian-pen#clearingHouse-realm>"
clearingHouseClientId: "<path:essential-services/data/custodian-pen#clearingHouse-clientId>"
clearingHouseClientSecret: "<path:essential-services/data/custodian-pen#clearingHouse-clientSecret>"

verifycredentialsUri: "<path:essential-services/data/custodian-pen#verifiableCredentials-schema2210Url>"
1 change: 1 addition & 0 deletions charts/sdfactory/values-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,4 @@ sdfactory:
clearingHouseRealm: "<path:essential-services/data/custodian#clearingHouse-realm>"
clearingHouseClientId: "<path:essential-services/data/custodian#clearingHouse-clientId>"
clearingHouseClientSecret: "<path:essential-services/data/custodian#clearingHouse-clientSecret>"
verifycredentialsUri: "<path:essential-services/data/custodian#verifiableCredentials-schema2210Url>"
2 changes: 2 additions & 0 deletions charts/sdfactory/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ sdfactory:
clearingHouseClientId: ""
# -- Details for Clearing House Client Secret
clearingHouseClientSecret: ""
# -- Details for Verifying Client uri
verifycredentialsUri: ""

service:
# -- Type of service
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/********************************************************************************
* Copyright (c) 2022,2023 T-Systems International GmbH
* Copyright (c) 2022,2023 Contributors to the Eclipse Foundation
* Copyright (c) 2022,2024 T-Systems International GmbH
* Copyright (c) 2022,2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand Down Expand Up @@ -28,37 +28,45 @@
import lombok.extern.slf4j.Slf4j;
import org.eclipse.tractusx.selfdescriptionfactory.api.vrel3.ApiApiDelegate;
import org.eclipse.tractusx.selfdescriptionfactory.model.vrel3.SelfdescriptionPostRequest;
import org.eclipse.tractusx.selfdescriptionfactory.service.AuthChecker;
import org.eclipse.tractusx.selfdescriptionfactory.service.clearinghouse.ClearingHouse;
import org.eclipse.tractusx.selfdescriptionfactory.service.wallet.CustodianWallet;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.function.Function;

/**
* A service to create and manipulate of Self-Description document
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class SDFactory implements ApiApiDelegate {
public class SDFactory implements ApiApiDelegate, InitializingBean {
@Value("${app.verifiableCredentials.durationDays:90}")
private int duration;

private final CustodianWallet custodianWallet;
private final ConversionService conversionService;
private final ClearingHouse clearingHouse;
private final Environment environment;
private final AuthChecker authChecker;

private Function<SelfdescriptionPostRequest, ResponseEntity<Void>> decoratedFunction;

@PreAuthorize("hasAuthority(@securityRoles.createRole)")
@Override
public ResponseEntity<Void> selfdescriptionPost(SelfdescriptionPostRequest selfdescriptionPostRequest) {
return decoratedFunction.apply(selfdescriptionPostRequest);
}

private ResponseEntity<Void> doWork(SelfdescriptionPostRequest selfdescriptionPostRequest) {
var processed = Objects.requireNonNull(conversionService.convert(selfdescriptionPostRequest, SelfDescription.class), "Converted SD-Document is null. Very strange");
var verifiableCredential = VerifiableCredential.builder()
.contexts(processed.getContexts())
Expand All @@ -69,13 +77,17 @@ public ResponseEntity<Void> selfdescriptionPost(SelfdescriptionPostRequest selfd
.credentialSubject(CredentialSubject.fromJsonObject(processed))
.type(processed.getType())
.build();
// This call signs the VC at MIW as it was in versions prior to CH
// var verifiableCredentialSigned = custodianWallet.getSignedVC(verifiableCredential);
clearingHouse.sendToClearingHouse(verifiableCredential, processed.getExternalId());

return new ResponseEntity<>(HttpStatus.ACCEPTED);
}

@Override
public void afterPropertiesSet() {
decoratedFunction = Arrays.asList(environment.getActiveProfiles()).contains("test")
? this::doWork
: authChecker.getAuthorizedFn(this::doWork);
}

@Getter
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/********************************************************************************
* Copyright (c) 2022,2023 T-Systems International GmbH
* Copyright (c) 2022,2023 Contributors to the Eclipse Foundation
* Copyright (c) 2022,2024 T-Systems International GmbH
* Copyright (c) 2022,2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand Down Expand Up @@ -41,11 +41,17 @@
@Slf4j
public class DefaultFeignConfig {
@Bean
public RequestInterceptor getRequestInterceptor(KeycloakManager keycloakManager) {
return requestTemplate -> Optional.of(requestTemplate.feignTarget().name())
.map(keycloakManager::getToken)
.ifPresent(token -> requestTemplate.header("Authorization", "Bearer ".concat(token)));

public RequestInterceptor getRequestInterceptor(KeycloakManager keycloakManager, TechnicalUsersDetails technicalUsersDetails) {
return requestTemplate -> {
Optional.of(requestTemplate.feignTarget().name())
.map(keycloakManager::getToken)
.map("Bearer "::concat)
.ifPresent(token -> requestTemplate.header("Authorization", token));
Optional.of(requestTemplate.feignTarget().name())
.map(technicalUsersDetails.getUsersDetails()::get)
.map(TechnicalUsersDetails.UserDetail::uri)
.ifPresent(requestTemplate::target);
};
}

@Bean
Expand All @@ -64,6 +70,8 @@ public ErrorDecoder getErrorDecoder(ObjectMapper mapper) {
.getOrElse(responseStr);
var statusCode = HttpStatusCode.valueOf(response.status());
log.error("Error in Feign client: {}", msg);
log.error("Status code: {}", statusCode);
log.error("URL: {}", response.request().url());
if (response.request().body() != null) {
log.error("Original payload: {}", new String(response.request().body(), response.request().charset()));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/********************************************************************************
* Copyright (c) 2022,2023 T-Systems International GmbH
* Copyright (c) 2022,2023 Contributors to the Eclipse Foundation
* Copyright (c) 2022,2024 T-Systems International GmbH
* Copyright (c) 2022,2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -20,16 +20,19 @@

package org.eclipse.tractusx.selfdescriptionfactory.config;

import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.env.Environment;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
Expand All @@ -41,6 +44,7 @@
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
Expand All @@ -49,13 +53,12 @@
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {

private static final String[] PUBLIC_URL = { "/ping", "/*/public/**", "/api-docs/**", "/swagger-ui/**",
"*/swagger-ui/**", "/v3/api-docs/**" };

@Value("${keycloak.resource.clientid}")
private String resourceName;
private final Environment environment;

public interface Jwt2AuthoritiesConverter extends Converter<Jwt, Collection<? extends GrantedAuthority>> {
}
Expand Down Expand Up @@ -85,31 +88,41 @@ public Jwt2AuthenticationConverter authenticationConverter(Jwt2AuthoritiesConver

@SneakyThrows
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, Jwt2AuthenticationConverter authenticationConverter,
ServerProperties serverProperties) {
public SecurityFilterChain filterChain(HttpSecurity http, Jwt2AuthenticationConverter authenticationConverter) {

// Configure OAuth2 with custom authorities mapping
http.oauth2ResourceServer(oauth2 -> oauth2.jwt(
jwt -> jwt.jwtAuthenticationConverter(authenticationConverter)
));

// Enable OAuth2 with custom authorities mapping
http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(authenticationConverter);
// Enable anonymous access
http.anonymous(Customizer.withDefaults());

// Enable anonymous
http.anonymous();
// Configure CORS with custom source
http.cors(cors -> cors.configurationSource(corsConfigurationSource()));

// Enable and configure CORS
http.cors().configurationSource(corsConfigurationSource());
// Configure stateless session management
http.sessionManagement(session -> session.sessionCreationPolicy(
SessionCreationPolicy.STATELESS
));

// State-less session (state in access-token only)
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Disable CSRF due to stateless session management
http.csrf(AbstractHttpConfigurer::disable);

// Disable CSRF because of state-less session-management
http.csrf().disable();
http.headers(headers -> {
// Equivalent to xssProtection().and() in the deprecated configuration
// The XSS protection is enabled by default and the X-XSS-Protection header is not necessary to set if you're using modern browser security features.

http.authorizeHttpRequests()
//.requestMatchers("/actuator/**").authenticated()
.anyRequest().permitAll();
// Content Security Policy configuration
headers.contentSecurityPolicy(csp -> csp.policyDirectives("default-src 'self'; script-src 'self' 'unsafe-inline'"));
// The .and() is not needed as the lambda configuration allows chaining within the same context.

http.headers().xssProtection().and()
.contentSecurityPolicy("default-src 'self'; script-src 'self' 'unsafe-inline'").and()
.httpStrictTransportSecurity().requestMatcher(AnyRequestMatcher.INSTANCE);
// HTTP Strict Transport Security configuration
headers.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)
.maxAgeInSeconds(31536000)
.requestMatcher(AnyRequestMatcher.INSTANCE)); // Apply HSTS to all requests
});

return http.build();
}
Expand All @@ -128,4 +141,4 @@ protected CorsConfigurationSource corsConfigurationSource() {
return source;
}

}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/********************************************************************************
* Copyright (c) 2022,2023 T-Systems International GmbH
* Copyright (c) 2022,2023 Contributors to the Eclipse Foundation
* Copyright (c) 2022,2024 T-Systems International GmbH
* Copyright (c) 2022,2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand Down Expand Up @@ -31,6 +31,7 @@
public class TechnicalUsersDetails {
private Map<String, UserDetail> usersDetails;
public record UserDetail (
String uri,
String serverUrl,
String realm,
String username,
Expand Down
Loading

0 comments on commit c3861c7

Please sign in to comment.