Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstract key storage and signing operations to facilitate different key storage types #291

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
0247648
add KeyStorageService Interface & implement DBSKeytorage
PManaras Mar 19, 2024
b3cd848
add encoding type also for holders credential config
PManaras Mar 20, 2024
5fc27ca
fix missing encoding in updateSummaryCredential
PManaras Mar 20, 2024
bb8af0a
make KeyService.createCredential return VerifiableCredential
PManaras Mar 20, 2024
e7b3c22
clean up
PManaras Mar 20, 2024
44688b3
clean up testutils
PManaras Mar 20, 2024
765eed8
add column for keystore type through separate changeset
PManaras Mar 20, 2024
5ceb5cb
cleanup PresentationService
PManaras Mar 20, 2024
df397ae
introduce SigningService and KeyProvider interfaces
PManaras Mar 20, 2024
42ad5b5
cleanup unnecessary imports
PManaras Mar 20, 2024
54abaa4
add KeyCreationOptions, pass keyCreationOptions to SigningService.getKey
PManaras Mar 21, 2024
1a02d0c
extend add LocalSigningService interface
PManaras Mar 21, 2024
fd4b247
add lombok validation for config builders, add AUTHORITY_SIGNING_SERV…
PManaras Mar 21, 2024
f3c9813
fix docker-env: remove unncessary env var
PManaras Mar 21, 2024
587b058
remove unecessary imports and vars
PManaras Mar 21, 2024
297b78d
add migration for existing wallets & migration test
PManaras Mar 21, 2024
3133070
remove unncessary java migration
PManaras Mar 21, 2024
5c8e1c3
add javadoc for new interfaces
PManaras Mar 21, 2024
8d6ed32
remove comments from test
PManaras Mar 21, 2024
e140002
rebase onto develop
PManaras Apr 11, 2024
4c99ee0
integrate changes
PManaras Apr 12, 2024
d2a5cd8
add issueToken to SigningService
PManaras Apr 15, 2024
2aeb2e4
refactor token issuer to use configured keyprovider to retrieve keypair
PManaras Apr 15, 2024
8f8fdbf
remove wallet key repository from secure token issuer
PManaras Apr 15, 2024
537758f
remove unused imports and commented segments
PManaras Apr 16, 2024
fec91a8
remove unused imports, remove comments
PManaras Apr 25, 2024
b02e477
chore(release): 1.0.0-develop.2 [skip ci]
PManaras Apr 22, 2024
83e338b
revert copyright to 2023 in ManagedIdentityWalletsApplication.java
PManaras Apr 25, 2024
b2959e6
fix: ficense header updated
nitin-vavdiya May 27, 2024
099fabb
fix: chart file
nitin-vavdiya May 28, 2024
8b16023
fix: chart file
nitin-vavdiya May 28, 2024
22e3bb8
fix: test cases
nitin-vavdiya May 28, 2024
e264c0f
fix: direct access to WalletKeyService while signing VC removed
nitin-vavdiya May 28, 2024
a7fb417
fix: sonar issues
nitin-vavdiya May 28, 2024
171434e
doc: readme updated
nitin-vavdiya May 29, 2024
af87ecb
fix: javadoc, imports and throws
nitin-vavdiya May 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# [0.5.0-develop.17](https://github.com/eclipse-tractusx/managed-identity-wallet/compare/v0.5.0-develop.16...v0.5.0-develop.17) (2024-05-29)



### Bug Fixes

* api doc folder structure ([ebd691a](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/ebd691a8a5c05f26a6aa10b778d4c8be6189a4af))
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ This process ensures that any issues with the database schema are resolved by re
| ENFORCE_HTTPS_IN_DID_RESOLUTION | Enforce https during web did resolution | true |
| CONTRACT_TEMPLATES_URL | Contract templates URL used in summary VC | https://public.catena-x.org/contracts/ |
| APP_LOG_LEVEL | Log level of application | INFO |
| AUTHORITY_SIGNING_SERVICE_TYPE | Base wallet signing type, Currency only LOCAL is supported | Local |
| LOCAL_SIGNING_KEY_STORAGE_TYPE | Key storage type, currently only DB is supported | DB |
| | | |

# Technical Debts and Known issue
Expand Down
2 changes: 2 additions & 0 deletions dev-assets/env-files/env.docker.dist
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ ENCRYPTION_KEY=
AUTHORITY_WALLET_BPN=BPNL000000000000
AUTHORITY_WALLET_DID=did:web:localhost:BPNL000000000000
AUTHORITY_WALLET_NAME=Catena-X
AUTHORITY_SIGNING_SERVICE_TYPE=LOCAL
LOCAL_SIGNING_KEY_STORAGE_TYPE=DB
KEYCLOAK_REALM=miw_test
VC_SCHEMA_LINK="https://www.w3.org/2018/credentials/v1, https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json"
VC_EXPIRY_DATE=01-01-2025
Expand Down
2 changes: 2 additions & 0 deletions dev-assets/env-files/env.local.dist
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ ENCRYPTION_KEY=
AUTHORITY_WALLET_BPN=BPNL000000000000
AUTHORITY_WALLET_DID=did:web:localhost:BPNL000000000000
AUTHORITY_WALLET_NAME=Catena-X
AUTHORITY_SIGNING_SERVICE_TYPE=LOCAL
LOCAL_SIGNING_KEY_STORAGE_TYPE=DB
KEYCLOAK_REALM=miw_test
VC_SCHEMA_LINK="https://www.w3.org/2018/credentials/v1, https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json"
VC_EXPIRY_DATE=01-01-2025
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* *******************************************************************************
* Copyright (c) 2021,2023 Contributors to the Eclipse Foundation
* Copyright (c) 2021,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,6 +28,10 @@
import com.smartsensesolutions.java.commons.specification.SpecificationUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringEscapeUtils;
import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType;
import org.eclipse.tractusx.managedidentitywallets.signing.KeyProvider;
import org.eclipse.tractusx.managedidentitywallets.signing.LocalSigningService;
import org.eclipse.tractusx.managedidentitywallets.signing.SigningService;
import org.springdoc.core.properties.SwaggerUiConfigProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand All @@ -40,6 +44,9 @@
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.nio.charset.StandardCharsets;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

/**
* The type Application config.
Expand All @@ -50,11 +57,13 @@ public class ApplicationConfig implements WebMvcConfigurer {

private final SwaggerUiConfigProperties properties;
private final String resourceBundlePath;
private final MIWSettings miwSettings;

@Autowired
public ApplicationConfig(@Value("${resource.bundle.path:classpath:i18n/language}") String resourceBundlePath, SwaggerUiConfigProperties properties) {
public ApplicationConfig(@Value("${resource.bundle.path:classpath:i18n/language}") String resourceBundlePath, SwaggerUiConfigProperties properties, MIWSettings miwSettings) {
this.resourceBundlePath = resourceBundlePath;
this.properties = properties;
this.miwSettings = miwSettings;
}

/**
Expand Down Expand Up @@ -98,4 +107,23 @@ public LocalValidatorFactoryBean validator() {
beanValidatorFactory.setValidationMessageSource(messageSource());
return beanValidatorFactory;
}

@Bean
public Map<SigningServiceType, SigningService> availableKeyStorages(List<SigningService> storages, List<KeyProvider> keyProviders) {
KeyProvider localSigningKeyProvider = keyProviders.stream().filter(s -> s.getKeyStorageType().equals(miwSettings.localSigningKeyStorageType()))
.findFirst()
.orElseThrow(() -> new IllegalStateException("no key provider with type %s found".formatted(miwSettings.localSigningKeyStorageType())));

Map<SigningServiceType, SigningService> available = new EnumMap<>(SigningServiceType.class);
storages.forEach(
s -> {
if(s instanceof LocalSigningService local){
local.setKeyProvider(localSigningKeyProvider);
}
available.put(s.getSupportedServiceType(), s);
}
);

return available;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* *******************************************************************************
* Copyright (c) 2021,2023 Contributors to the Eclipse Foundation
* Copyright (c) 2021,2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -21,6 +21,8 @@

package org.eclipse.tractusx.managedidentitywallets.config;

import org.eclipse.tractusx.managedidentitywallets.domain.KeyStorageType;
import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.format.annotation.DateTimeFormat;

Expand All @@ -39,5 +41,8 @@ public record MIWSettings(String host, String encryptionKey, String authorityWal
@DateTimeFormat(pattern = "dd-MM-yyyy") Date vcExpiryDate,
Set<String> supportedFrameworkVCTypes,
boolean enforceHttps, String contractTemplatesUrl,
List<URI> didDocumentContextUrls) {
List<URI> didDocumentContextUrls,
KeyStorageType localSigningKeyStorageType,
SigningServiceType authoritySigningServiceType) {
}

Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@

package org.eclipse.tractusx.managedidentitywallets.constant;

import lombok.experimental.UtilityClass;

/**
* The type Miw verifiable credential type.
*/
@UtilityClass
public class MIWVerifiableCredentialType {

public static final String VERIFIABLE_CREDENTIAL = "VerifiableCredential";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ private StringPool() {

public static final String BPN_NUMBER_REGEX = "^(BPN)(L|S|A)[0-9A-Z]{12}";

public static final String W3_ID_JWS_2020_V1_CONTEXT_URL = "https://w3id.org/security/suites/jws-2020/v1";

public static final String COMA_SEPARATOR = ", ";
public static final String BLANK_SEPARATOR = " ";
public static final String COLON_SEPARATOR = ":";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,21 @@
import org.apache.commons.lang3.StringUtils;
import org.eclipse.tractusx.managedidentitywallets.apidocs.SecureTokenControllerApiDoc;
import org.eclipse.tractusx.managedidentitywallets.constant.StringPool;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet;
import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository;
import org.eclipse.tractusx.managedidentitywallets.domain.BusinessPartnerNumber;
import org.eclipse.tractusx.managedidentitywallets.domain.DID;
import org.eclipse.tractusx.managedidentitywallets.domain.IdpTokenResponse;
import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType;
import org.eclipse.tractusx.managedidentitywallets.domain.StsTokenErrorResponse;
import org.eclipse.tractusx.managedidentitywallets.domain.StsTokenResponse;
import org.eclipse.tractusx.managedidentitywallets.dto.SecureTokenRequest;
import org.eclipse.tractusx.managedidentitywallets.exception.InvalidIdpTokenResponseException;
import org.eclipse.tractusx.managedidentitywallets.exception.InvalidSecureTokenRequestException;
import org.eclipse.tractusx.managedidentitywallets.exception.UnknownBusinessPartnerNumberException;
import org.eclipse.tractusx.managedidentitywallets.exception.UnsupportedGrantTypeException;
import org.eclipse.tractusx.managedidentitywallets.interfaces.SecureTokenService;
import org.eclipse.tractusx.managedidentitywallets.service.IdpAuthorization;
import org.eclipse.tractusx.managedidentitywallets.signing.SigningService;
import org.eclipse.tractusx.managedidentitywallets.validator.SecureTokenRequestValidator;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
Expand All @@ -57,6 +59,7 @@
import org.springframework.web.bind.annotation.RestController;

import java.text.ParseException;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

Expand All @@ -69,17 +72,19 @@
@Tag(name = "STS")
public class SecureTokenController {

private final SecureTokenService tokenService;

private final IdpAuthorization idpAuthorization;

private final WalletRepository walletRepo;

private final Map<SigningServiceType, SigningService> availableSigningServices;

@InitBinder
void initBinder(WebDataBinder webDataBinder) {
webDataBinder.addValidators(new SecureTokenRequestValidator());
}


@SneakyThrows
@PostMapping(path = "/api/token", consumes = { MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE })
@SecureTokenControllerApiDoc.PostSecureTokenDocJson
Expand All @@ -103,7 +108,8 @@ private ResponseEntity<StsTokenResponse> processTokenRequest(SecureTokenRequest
// handle idp authorization
IdpTokenResponse idpResponse = idpAuthorization.fromSecureTokenRequest(secureTokenRequest);
BusinessPartnerNumber bpn = idpResponse.bpn();
DID selfDid = new DID(walletRepo.getByBpn(bpn.toString()).getDid());
Wallet selfWallet = walletRepo.getByBpn(bpn.toString());
DID selfDid = new DID(selfWallet.getDid());
DID partnerDid;
if (Pattern.compile(StringPool.BPN_NUMBER_REGEX).matcher(secureTokenRequest.getAudience()).matches()) {
partnerDid = new DID(walletRepo.getByBpn(secureTokenRequest.getAudience()).getDid());
Expand All @@ -113,18 +119,21 @@ private ResponseEntity<StsTokenResponse> processTokenRequest(SecureTokenRequest
throw new InvalidSecureTokenRequestException("You must provide an audience either as a BPN or DID.");
}

SigningServiceType signingServiceType = selfWallet.getSigningServiceType();
SigningService signingService = availableSigningServices.get(signingServiceType);

// create the SI token and put/create the access_token inside
JWT responseJwt;
if (secureTokenRequest.assertValidWithAccessToken()) {
log.debug("Signing si token.");
responseJwt = tokenService.issueToken(
responseJwt = signingService.issueToken(
selfDid,
partnerDid,
JWTParser.parse(secureTokenRequest.getAccessToken())
);
} else if (secureTokenRequest.assertValidWithScopes()) {
log.debug("Creating access token and signing si token.");
responseJwt = tokenService.issueToken(
responseJwt = signingService.issueToken(
selfDid,
partnerDid,
Set.of(secureTokenRequest.getBearerAccessScope())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* *******************************************************************************
* Copyright (c) 2021,2023 Contributors to the Eclipse Foundation
* Copyright (c) 2021,2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -27,6 +27,8 @@
import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand All @@ -37,6 +39,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType;
import org.eclipse.tractusx.managedidentitywallets.utils.StringToDidDocumentConverter;
import org.eclipse.tractusx.ssi.lib.model.did.DidDocument;
import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential;
Expand Down Expand Up @@ -72,6 +75,10 @@ public class Wallet extends MIWBaseEntity {
@Column(nullable = false)
private String algorithm;

@Enumerated(EnumType.STRING)
@Column(name = "signing_service_type", nullable = false)
private SigningServiceType signingServiceType;

@Column(nullable = false)
@Convert(converter = StringToDidDocumentConverter.class)
private DidDocument didDocument;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* *******************************************************************************
* Copyright (c) 2021,2023 Contributors to the Eclipse Foundation
* Copyright (c) 2021,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 @@ -30,7 +30,7 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MapsId;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -47,13 +47,14 @@
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Table(name="wallet_key")
public class WalletKey extends MIWBaseEntity {

@Id
@JsonIgnore
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", columnDefinition = "serial", nullable = false, unique = true)
private Long id;
private long id;

@Column(nullable = false)
private String vaultAccessToken;
Expand All @@ -68,8 +69,7 @@ public class WalletKey extends MIWBaseEntity {
private String publicKey;

@ManyToOne
@MapsId
@JoinColumn(name = "walletId", columnDefinition = "bigint")
@JoinColumn(name = "wallet_id", columnDefinition = "bigint")
@JsonBackReference
private Wallet wallet;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,43 @@ public interface WalletKeyRepository extends BaseRepository<WalletKey, Long> {
/**
* Gets by wallet id and algorithm.
*
* @param id the id
* param algorithm the algorithm
* @param id the wallet id
* @param algorithm the algorithm
* @return the by wallet id
*/
WalletKey getByWalletIdAndAlgorithm(Long id, String algorithm);

/**
* Gets by wallet id.
* @param id
* @return WalletKey
* Find first by wallet bpn wallet key.
*
* @param bpn the bpn
* @return the wallet key
*/
WalletKey getByWalletId(Long id);

WalletKey findFirstByWallet_Bpn(String bpn);

/**
* Find first by wallet did wallet key.
*
* @param did the did
* @return the wallet key
*/
WalletKey findFirstByWallet_Did(String did);

/**
* Gets by key id and algorithm.
*
* @param keyId the key id
* @param algorithm the algorithm
* @return the by key id and algorithm
*/
WalletKey getByKeyIdAndAlgorithm(String keyId, String algorithm);

/**
* Gets by algorithm and wallet bpn.
*
* @param name the name
* @param keyName the key name
* @return the by algorithm and wallet bpn
*/
WalletKey getByAlgorithmAndWallet_Bpn(String name, String keyName);
}
Loading
Loading