Skip to content

Commit

Permalink
feat: reamdme added with env verables, vp as jwt, credentials id adde…
Browse files Browse the repository at this point in the history
…d in table, search with credential id
  • Loading branch information
nitin-vavdiya committed Jun 1, 2023
1 parent 2e00386 commit e654a57
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 16 deletions.
191 changes: 191 additions & 0 deletions README_did_web.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# !!! Under Contruction !!!

# Managed Identity Wallets <a id="introduction"></a>

The Managed Identity Wallets (MIW) service implements the Self-Sovereign-Identity (SSI)
readiness by providing a wallet hosting platform including a DID resolver,
service endpoints and the company wallets itself.

> **Warning**
> Heavily under development
>
# Developer Documentation

To run MIW locally, this section describes the tooling as well as
the local development setup.

## Tooling
To be added

## Environment Variables <a id= "environmentVariables"></a>

| name | description | default value |
|----------------------------|-----------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|
| APPLICATION_PORT | port number of application | 8087 |
| APPLICATION_ENVIRONMENT | Environment of the application ie. local, dev, int and prod | local |
| DB_HOST | Database host | localhost |
| DB_PORT | Port of database | 5432 |
| DB_NAME | Database name | miw |
| USE_SSL | Whether SSL is enabled in database server | false |
| DB_USER_NAME | Database username | |
| DB_PASSWORD | Database password | |
| DB_POOL_SIZE | Max number of database connection acquired by application | 10 |
| KEYCLOAK_MIW_PUBLIC_CLIENT | Only needed if we want enable login with keyalock in swagger | miw_public |
| MANAGEMENT_PORT | Spring actuator port | 8090 |
| MIW_HOST_NAME | Application host name, this will be used in creation of did ie. did:web:MIW_HOST_NAME:BPN | localhost |
| ENCRYPTION_KEY | encryption key used to encrypt and decrypt private and public key of wallet | |
| AUTHORITY_WALLET_BPN | base wallet BPN number | BPNL000000000000 |
| AUTHORITY_WALLET_NAME | Base wallet name | Catena-X |
| AUTHORITY_WALLET_DID | Base wallet web did | web:did:host:BPNL000000000000 |
| VC_SCHEMA_LINK | Comma separated list of VC schema URL | https://www.w3.org/2018/credentials/v1, https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData |
| VC_EXPIRY_DATE | Expiry date of VC (dd-MM-yyyy ie. 01-01-2025 expiry date will be 2024-12-31T18:30:00Z in VC) | 01-01-2025 |
| KEYCLOAK_REALM | Realm name of keycloak | miw_test |
| KEYCLOAK_CLIENT_ID | Keycloak private client id | |
| AUTH_SERVER_URL | Keycloak server url | |
| | | |
## Local Development Setup

*Work in progress*

## Setup Summary

| Service | URL | Description |
|-----------------------|-------------------------|-------------|
| postgreSQL database | port 5432 on `localhost`| within the Docker Compose setup |
| Keycloak | http://localhost:8081/ | within the Docker Compose setup, username: `admin` and password: `changeme`, client id: `ManagedIdentityWallets` and client secret can be found under the Clients &gt; ManagedIdentityWallets &gt; Credentials |
| MIW service | http://localhost:8080/ | |


# Administrator Documentation

## Manual Keycloak Configuration

Within the development setup the Keycloak is initially prepared with the
values in `./dev-assets/dev-containers/keycloak`. The realm could also be
manually added and configured at http://localhost:8081 via the "Add realm"
button. It can be for example named `localkeycloak`. Also add an additional client,
e.g. named `ManagedIdentityWallets` with *valid redirect url* set to
`http://localhost:8080/*`. The roles
* add_wallets
* view_wallets
* update_wallets
* delete_wallets
* view_wallet
* update_wallet
can be added under *Clients > ManagedIdentityWallets > Roles* and then
assigned to the client using *Clients > ManagedIdentityWallets > Client Scopes*
*> Service Account Roles > Client Roles > ManagedIdentityWallets*. The
available scopes/roles are:

1. Role `add_wallets` to create a new wallet

1. Role `view_wallets`:
* to get a list of all wallets
* to retrieve one wallet by its identifier
* to validate a Verifiable Presentation
* to get all stored Verifiable Credentials

1. Role `update_wallets` for the following actions:
* to store Verifiable Credential
* to set the wallet DID to public on chain
* to issue a Verifiable Credential
* to issue a Verifiable Presentation
* to add, update and delete service endpoint of DIDs
* to trigger the update of Business Partner Data of all existing wallets

1. Role `delete_wallets` to remove a wallet

1. Role `view_wallet` requires the BPN of Caller and it can be used:
* to get the Wallet of the related BPN
* to get stored Verifiable Credentials of the related BPN
* to validate any Verifiable Presentation

1. Role `update_wallet` requires the BPN of Caller and it can be used:
* to issue Verifiable Credentials (The BPN of issuer will be checked)
* to issue Verifiable Presentations (The BPN of holder will be checked)
* to store Verifiable Credentials (The BPN of holder will be checked)
* to trigger Business Partner Data update for its own BPN

Additionally a Token mapper can to be created under *Clients* &gt;
*ManagedIdentityWallets* &gt; *Mappers* &gt; *create* with the following
configuration (using as example `BPNL000000001`):

| Key | Value |
|---------------------|---------------------------|
| Name | StaticBPN |
| Mapper Type | Hardcoded claim |
| Token Claim Name | BPN |
| Claim value | BPNL000000001 |
| Claim JSON Type | String |
| Add to ID token | OFF |
| Add to access token | ON |
| Add to userinfo | OFF |
| includeInAccessTokenResponse.label | ON |

If you receive an error message, that the client secret is not valid, please go into
keycloak admin and within *Clients > Credentials* recreate the secret.


## Local docker deployment

First step is to create the distribution of the application:

```bash
./gradlew installDist
```

Next step is to build and tag the Docker image, replacing the
`<VERSION>` with the app version:

```
docker build -t managed-identity-wallets:<VERSION> .
```

Finally, start the image (please make sure that there are no quotes around the
values in the env file):

```
docker run --env-file .env.docker -p 8080:8080 managed-identity-wallets:<VERSION>
```

## Deployment on Kubernetes

*Work in progress*

# End Users

See OpenAPI documentation, which is automatically created from
the source and available on each deployment at the `/docs` endpoint
(e.g. locally at http://localhost:8080/docs).


## Test Coverage

Jacoco is used to generate the coverage report. The report generation
and the coverage verification are automatically executed after tests.

The generated HTML report can be found under `jacoco-report/html/`

To generate the report run the command

```
./gradlew jacocoTestReport
```

To check the coverage run the command

```
./gradlew jacocoTestCoverageVerification
```

Currently the minimum is 80%

Files to be excluded from the coverage calculation can be set in
`gradle.properties` using a comma-separated list of files or directories
with possible wildcards as the value for the property `coverage_excludes`.
The files in `models` and `entities` should be excluded as long as they
don't have any logic. The services that are mocked in unit tests must be
excluded. Also their interfaces need to be excluded because they have a
`companion object` that is used to create those services. Files like
`Application.kt` which are tested or simulated indirectly for example
using `withTestApplication` should also be excluded.
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ public class CredentialController extends BaseController {
*/
@Operation(description = "Permission: **view_wallets** OR **view_wallet** (The BPN of holderIdentifier must equal BPN of caller)\n\n Search verifiable credentials with filter criteria", summary = "Query Verifiable Credentials")
@GetMapping(path = RestURI.CREDENTIALS, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<VerifiableCredential>> getCredentials(@RequestParam(required = false) String id,
public ResponseEntity<List<VerifiableCredential>> getCredentials(@RequestParam(required = false) String credentialId,
@RequestParam(required = false) String issuerIdentifier,
@RequestParam(required = false) List<String> type,
@RequestParam(required = false, defaultValue = "createdAt") String sortColumn,
@RequestParam(required = false, defaultValue = "desc") String sortTpe, Principal principal) {
return ResponseEntity.status(HttpStatus.OK).body(service.getCredentials(id, issuerIdentifier, type, sortColumn, sortTpe, getBPNFromToken(principal)));
return ResponseEntity.status(HttpStatus.OK).body(service.getCredentials(credentialId, issuerIdentifier, type, sortColumn, sortTpe, getBPNFromToken(principal)));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,7 @@ public class Credential extends MIWBaseEntity {
@Column(nullable = false)
@Convert(converter = StringToCredentialConverter.class)
private VerifiableCredential data;

@Column(nullable = false)
private String credentialId;
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ protected SpecificationUtil<Credential> getSpecificationUtil() {
/**
* Gets credentials.
*
* @param id the id
* @param credentialId the credentialId
* @param issuerIdentifier the issuer identifier
* @param type the type
* @param sortColumn the sort column
* @param sortType the sort type
* @param callerBPN the caller bpn
* @return the credentials
*/
public List<VerifiableCredential> getCredentials(String id, String issuerIdentifier, List<String> type, String sortColumn, String sortType, String callerBPN) {
public List<VerifiableCredential> getCredentials(String credentialId, String issuerIdentifier, List<String> type, String sortColumn, String sortType, String callerBPN) {
FilterRequest filterRequest = new FilterRequest();


Expand All @@ -107,6 +107,10 @@ public List<VerifiableCredential> getCredentials(String id, String issuerIdentif
filterRequest.appendNewCriteria("issuerDid", Operator.EQUALS, issuerWallet.getDid());
}

if (StringUtils.hasText(credentialId)) {
filterRequest.appendNewCriteria("credentialId", Operator.EQUALS, credentialId);
}

if (!CollectionUtils.isEmpty(type)) {
filterRequest.appendNewCriteria("type", Operator.IN, type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@
import org.eclipse.tractusx.ssi.lib.serialization.jwt.SerializedJwtPresentationFactoryImpl;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;

/**
* The type Presentation service.
Expand Down Expand Up @@ -127,16 +125,16 @@ public Map<String, Object> createPresentation(Map<String, Object> data, boolean
//Build JWT
SignedJWT presentation = presentationFactory.createPresentation(
issuerDid, verifiableCredentials, audience, walletKeyService.getEd25519Key(holderWallet.getId()));

response.put("vp", presentation);
response.put("vp", presentation.serialize());
} else {
VerifiablePresentationBuilder verifiablePresentationBuilder =
new VerifiablePresentationBuilder();

// Build VP
VerifiablePresentation verifiablePresentation =
verifiablePresentationBuilder
.id(issuerDid.toUri())
.id(URI.create(UUID.randomUUID().toString()))
.type(List.of(VerifiablePresentationType.VERIFIABLE_PRESENTATION))
.verifiableCredentials(verifiableCredentials)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ public Map<String, String> storeCredential(Map<String, Object> data, String iden
.issuerDid(URLDecoder.decode(verifiableCredential.getIssuer().toString(), Charset.defaultCharset()))
.type(verifiableCredential.getTypes().get(0))
.data(verifiableCredential)
.credentialId(verifiableCredential.getId().toString())
.build());
return Map.of("message", String.format("Credential with id %s has been successfully stored", verifiableCredential.getId()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public static Credential getCredential(Map<String, Object> subject, String type,
.holderDid(holderDid)
.issuerDid(issuerDid)
.type(type)
.credentialId(verifiableCredential.getId().toString())
.data(verifiableCredential)
.build();
}
Expand Down
10 changes: 5 additions & 5 deletions src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
server:
port: ${APPLICATION_PORT:8087}
port: ${APPLICATION_PORT:8080}
shutdown: graceful
compression:
enabled: true
spring:
profiles:
active: ${APPLICATION_ENVIRONMENT:dev}
active: ${APPLICATION_ENVIRONMENT:local}
liquibase:
change-log: classpath:/db/changelog/changelog-master.xml
application:
name: ${APPLICATION_NAME:miw}
name: miw
datasource:
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5433}/${DB_NAME:miw}?useSSL=${USE_SSL:false}
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:miw}?useSSL=${USE_SSL:false}
username: ${DB_USER_NAME:root}
password: ${DB_PASSWORD:smart}
initialization-mode: always
Expand Down Expand Up @@ -60,7 +60,7 @@ management:
enabled: true

miw:
host: ${HOST_NAME:localhost}
host: ${MIW_HOST_NAME:localhost}
encryptionKey: ${ENCRYPTION_KEY:Woh9waid4Ei5eez0aitieghoow9so4oe}
authorityWalletBpn: ${AUTHORITY_WALLET_BPN:BPNL000000000000}
authorityWalletName: ${AUTHORITY_WALLET_NAME:Catena-X}
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/db/changelog/changes/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ CREATE TABLE public.credential (
id bigserial NOT NULL,
holder_did varchar(255) NOT NULL,
issuer_did varchar(255) NOT NULL,
credential_id varchar(255) NOT NULL,
"data" text NOT NULL,
"type" varchar(255) NULL,
created_at timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
Expand Down

0 comments on commit e654a57

Please sign in to comment.