Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 30c9bf2
Author: Foorack / Max Faxälv <max@foorack.com>
Date:   Tue Apr 2 10:32:48 2024 +0200

    inherit `repository` in identity_verification (#1348)

commit 1e9c9a3
Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Date:   Wed Mar 27 15:35:29 2024 +0100

    Release wasm-v1.2.0 (#1345)

commit 84a630d
Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Date:   Wed Mar 27 15:32:19 2024 +0100

    Release v1.2.0 (#1347)

commit 1aba4b5
Author: Eike Haß <eike-hass@web.de>
Date:   Wed Mar 27 13:13:27 2024 +0100

    removed dev_dep version

commit 0352b84
Author: Enrico Marconi <31142849+UMR1352@users.noreply.github.com>
Date:   Wed Mar 27 10:44:43 2024 +0100

    Support %-encoded characters in DID method id (#1303)

commit e68538f
Author: Enrico Marconi <31142849+UMR1352@users.noreply.github.com>
Date:   Tue Mar 26 11:58:35 2024 +0100

    gRPC bindings (#1264)

commit e53561e
Author: Enrico Marconi <31142849+UMR1352@users.noreply.github.com>
Date:   Tue Mar 26 11:18:14 2024 +0100

    allow large result err variants (#1342)

commit 4a144a3
Author: Eike Haß <eike-hass@web.de>
Date:   Tue Mar 19 09:51:52 2024 +0100

    fix readme links (#1336)

commit 0af29fc
Author: Enrico Marconi <31142849+UMR1352@users.noreply.github.com>
Date:   Mon Mar 18 17:16:57 2024 +0100

    Feat/custom verification method (#1334)

    * Add support for arbitrary (custom) verification method data

    * wasm bindings

    * custom method type + wasm

    * workaround serde's issue

    * Update bindings/wasm/src/verification/wasm_method_data.rs

    Co-authored-by: Abdulrahim Al Methiab <31316147+abdulmth@users.noreply.github.com>

    * review comments

    * fmt

    * review comment

    ---------

    Co-authored-by: Abdulrahim Al Methiab <31316147+abdulmth@users.noreply.github.com>

commit edb9150
Author: Enrico Marconi <31142849+UMR1352@users.noreply.github.com>
Date:   Tue Mar 12 14:45:04 2024 +0100

    use latest release of sd-jwt-payload (#1333)

    * use latest release of sd-jwt-payload

    * make clippy happy

commit 0794379
Author: Abdulrahim Al Methiab <31316147+abdulmth@users.noreply.github.com>
Date:   Wed Mar 6 14:16:00 2024 +0100

    Wasm bindings for `BlockChainAccountId` verification method. (#1326)

commit 59d38f7
Author: Abdulrahim Al Methiab <31316147+abdulmth@users.noreply.github.com>
Date:   Wed Mar 6 10:56:23 2024 +0100

    Add constructor for VerificationMethod in TS (#1321)
  • Loading branch information
UMR1352 committed Apr 25, 2024
1 parent 4a152d0 commit be022b0
Show file tree
Hide file tree
Showing 69 changed files with 3,327 additions and 103 deletions.
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
target/
bindings/wasm/
bindings/grpc/target/
41 changes: 41 additions & 0 deletions .github/workflows/build-and-test-grpc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Build and run grpc tests

on:
push:
branches:
- main
pull_request:
types: [ opened, synchronize, reopened, ready_for_review ]
branches:
- main
- 'epic/**'
- 'support/**'
paths:
- '.github/workflows/build-and-test.yml'
- '.github/actions/**'
- '**.rs'
- '**.toml'
- 'bindings/grpc/**'

jobs:
check-for-run-condition:
runs-on: ubuntu-latest
outputs:
should-run: ${{ !github.event.pull_request || github.event.pull_request.draft == false }}
steps:
- run: |
# this run step does nothing, but is needed to get the job output
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v4

- name: Build Docker image
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: .
file: bindings/grpc/Dockerfile
push: false
labels: iotaledger/identity-grpc:latest
52 changes: 52 additions & 0 deletions .github/workflows/grpc-publish-to-dockerhub.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: gRPC publish to dockerhub

on:
workflow_dispatch:
inputs:
tag:
description: 'Tag to publish under, defaults to latest'
required: false
default: latest
branch:
description: 'Branch to run publish from'
required: true
dry-run:
description: 'Run in dry-run mode'
type: boolean
required: false
default: true

jobs:
push_to_registry:
environment: release
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch }}

- name: Log in to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
with:
username: ${{ secrets.IOTALEDGER_DOCKER_USERNAME }}
password: ${{ secrets.IOTALEDGER_DOCKER_PASSWORD }}

- name: Build and push Docker image
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: .
file: bindings/grpc/Dockerfile
push: ${{ !inputs.dry-run }}
labels: iotaledger/identity-grpc:${{ inputs.tag }}

- name: Docker Hub Description
uses: peter-evans/dockerhub-description@e98e4d1628a5f3be2be7c231e50981aee98723ae
with:
username: ${{ secrets.IOTALEDGER_DOCKER_USERNAME }}
password: ${{ secrets.IOTALEDGER_DOCKER_PASSWORD }}
repository: iotaledger/identity-grpc
readme-filepath: ./bindigns/grpc/README.md
short-description: ${{ github.event.repository.description }}

24 changes: 19 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
# Changelog

## [v1.2.0](https://github.com/iotaledger/identity.rs/tree/v1.2.0) (2024-03-27)

[Full Changelog](https://github.com/iotaledger/identity.rs/compare/v1.1.1...v1.2.0)

### Added
- Add `get_public_key` for `StrongholdStorage` [\#1311](https://github.com/iotaledger/identity.rs/pull/1311)
- Support multiple IOTA networks in the Resolver [\#1304](https://github.com/iotaledger/identity.rs/pull/1304)
- Allow setting additional controllers for `IotaDocument` [\#1314](https://github.com/iotaledger/identity.rs/pull/1314)
- use latest release of sd-jwt-payload `IotaDocument` [\#1333](https://github.com/iotaledger/identity.rs/pull/1333)
- Allow arbitrary verification methods [\#1334](https://github.com/iotaledger/identity.rs/pull/1334)

### Patch
- Support %-encoded characters in DID method id [\#1303](https://github.com/iotaledger/identity.rs/pull/1303)

## [v1.1.1](https://github.com/iotaledger/identity.rs/tree/v1.1.1) (2024-02-19)

[Full Changelog](https://github.com/iotaledger/identity.rs/compare/v1.1.0...v1.1.1)

### Patch

- Fix compilation error caused by the roaring crate [\#1306](https://github.com/iotaledger/identity.rs/pull/1306)
- Fix compilation error caused by the `roaring` crate [\#1306](https://github.com/iotaledger/identity.rs/pull/1306)

## [v1.1.0](https://github.com/iotaledger/identity.rs/tree/v1.1.0) (2024-02-07)

[Full Changelog](https://github.com/iotaledger/identity.rs/compare/v1.0.0...v1.1.0)

### Added

- Support Selective Disclosure SD-JWT [\#1268](https://github.com/iotaledger/identity.rs/pull/1268)
- Update `sd-jwt-payload` dependency [\#1296](https://github.com/iotaledger/identity.rs/pull/1296)
- Add support for StatusList2021 [\#1273](https://github.com/iotaledger/identity.rs/pull/1273)
- Update sd-jwt-payload dependency [\#1296](https://github.com/iotaledger/identity.rs/pull/1296)
- Support Selective Disclosure SD-JWT [\#1268](https://github.com/iotaledger/identity.rs/pull/1268)

### Patch

- Validate domain-linkage URL making sure they only include an origin [\#1267](https://github.com/iotaledger/identity.rs/pull/1267)
- Credentials cannot be unrevoked with StatusList2021 [\#1284](https://github.com/iotaledger/identity.rs/pull/1284)
- Fix RevocationBitmap2022 encoding bug [\#1292](https://github.com/iotaledger/identity.rs/pull/1292)
- Credentials cannot be unrevoked with StatusList2021 [\#1284](https://github.com/iotaledger/identity.rs/pull/1284)
- Validate domain-linkage URL making sure they only include an origin [\#1267](https://github.com/iotaledger/identity.rs/pull/1267)

## [v1.0.0](https://github.com/iotaledger/identity.rs/tree/v1.0.0) (2023-11-02)

Expand Down
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ members = [
"examples",
]

exclude = ["bindings/wasm"]
exclude = ["bindings/wasm", "bindings/grpc"]

[workspace.dependencies]
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
Expand All @@ -35,4 +35,7 @@ repository = "https://github.com/iotaledger/identity.rs"
rust-version = "1.65"

[patch.crates-io]
iota_stronghold = {git = "https://github.com/tensor-programming/stronghold.rs.git", branch = "feat/expose_runner"}
iota_stronghold = {git = "https://github.com/tensor-programming/stronghold.rs.git", branch = "feat/expose_runner"}

[workspace.lints.clippy]
result_large_err = "allow"
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ IOTA Identity is a [Rust](https://www.rust-lang.org/) implementation of decentra

- [Web Assembly](https://github.com/iotaledger/identity.rs/blob/HEAD/bindings/wasm/) (JavaScript/TypeScript)

## gRPC

We provide a collection of experimental [gRPC services](https://github.com/iotaledger/identity.rs/blob/HEAD/bindings/grpc/)
## Documentation and Resources

- API References:
Expand All @@ -51,7 +54,7 @@ If you want to include IOTA Identity in your project, simply add it as a depende

```toml
[dependencies]
identity_iota = { version = "1.1.1" }
identity_iota = { version = "1.2.0" }
```

To try out the [examples](https://github.com/iotaledger/identity.rs/blob/HEAD/examples), you can also do this:
Expand Down Expand Up @@ -85,7 +88,7 @@ version = "1.0.0"
edition = "2021"

[dependencies]
identity_iota = { version = "1.1.1", features = ["memstore"] }
identity_iota = { version = "1.2.0", features = ["memstore"] }
iota-sdk = { version = "1.0.2", default-features = true, features = ["tls", "client", "stronghold"] }
tokio = { version = "1", features = ["full"] }
anyhow = "1.0.62"
Expand Down
43 changes: 43 additions & 0 deletions bindings/grpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[package]
name = "identity-grpc"
version = "0.1.0"
authors = ["IOTA Stiftung"]
edition = "2021"
homepage = "https://www.iota.org"
license = "Apache-2.0"
repository = "https://github.com/iotaledger/identity.rs"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
path = "src/lib.rs"

[[bin]]
name = "identity-grpc"
path = "src/main.rs"

[dependencies]
anyhow = "1.0.75"
futures = { version = "0.3" }
identity_eddsa_verifier = { path = "../../identity_eddsa_verifier" }
identity_iota = { path = "../../identity_iota", features = ["resolver", "sd-jwt", "domain-linkage", "domain-linkage-fetch", "status-list-2021"] }
identity_stronghold = { path = "../../identity_stronghold", features = ["send-sync-storage"] }
iota-sdk = { version = "1.1.2", features = ["stronghold"] }
openssl = { version = "0.10", features = ["vendored"] }
prost = "0.12"
rand = "0.8.5"
serde = { version = "1.0.193", features = ["derive", "alloc"] }
serde_json = { version = "1.0.108", features = ["alloc"] }
thiserror = "1.0.50"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
tokio-stream = { version = "0.1.14", features = ["net"] }
tonic = "0.10"
tracing = { version = "0.1.40", features = ["async-await"] }
tracing-subscriber = "0.3.18"
url = { version = "2.5", default-features = false }

[dev-dependencies]
identity_storage = { path = "../../identity_storage", features = ["memstore"] }

[build-dependencies]
tonic-build = "0.10"
20 changes: 20 additions & 0 deletions bindings/grpc/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM rust:bookworm as builder

# install protobuf
RUN apt-get update && apt-get install -y protobuf-compiler libprotobuf-dev musl-tools

COPY . /usr/src/app/
WORKDIR /usr/src/app/bindings/grpc
RUN rustup target add x86_64-unknown-linux-musl
RUN cargo build --target x86_64-unknown-linux-musl --release --bin identity-grpc

FROM gcr.io/distroless/static-debian11 as runner

# get binary
COPY --from=builder /usr/src/app/bindings/grpc/target/x86_64-unknown-linux-musl/release/identity-grpc /

# set run env
EXPOSE 50051

# run it
CMD ["/identity-grpc"]
130 changes: 130 additions & 0 deletions bindings/grpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Identity.rs gRPC Bindings
This project provides the functionalities of [Identity.rs](https://github.com/iotaledger/identity.rs) in a language-agnostic way through a [gRPC](https://grpc.io) server.

The server can easily be run with docker using [this dockerfile](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/Dockerfile).

## Build
Run `docker build -f bindings/grpc/Dockerfile -t iotaleger/identity-grpc .` from the project root.

### Dockerimage env variables and volume binds
The provided docker image requires the following variables to be set in order to properly work:
- `API_ENDPOINT`: IOTA node address.
- `STRONGHOLD_PWD`: Stronghold password.
- `SNAPSHOT_PATH`: Stronghold's snapshot location.

Make sure to provide a valid stronghold snapshot at the provided `SNAPSHOT_PATH` prefilled with all the needed key material.

### Available services
| Service description | Service Id | Proto File |
| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------|
| Credential Revocation Checking | `credentials/CredentialRevocation.check` | [credentials.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/credentials.proto) |
| SD-JWT Validation | `sd_jwt/Verification.verify` | [sd_jwt.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/sd_jwt.proto) |
| Credential JWT creation | `credentials/Jwt.create` | [credentials.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/credentials.proto) |
| Credential JWT validation | `credentials/VcValidation.validate` | [credentials.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/credentials.proto) |
| DID Document Creation | `document/DocumentService.create` | [document.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/document.proto) |
| Domain Linkage - validate domain, let server fetch did-configuration | `domain_linkage/DomainLinkage.validate_domain` | [domain_linkage.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/domain_linkage.proto) |
| Domain Linkage - validate domain, pass did-configuration to service | `domain_linkage/DomainLinkage.validate_domain_against_did_configuration` | [domain_linkage.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/domain_linkage.proto) |
| Domain Linkage - validate endpoints in DID, let server fetch did-configuration | `domain_linkage/DomainLinkage.validate_did` | [domain_linkage.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/domain_linkage.proto) |
| Domain Linkage - validate endpoints in DID, pass did-configuration to service | `domain_linkage/DomainLinkage.validate_did_against_did_configurations` | [domain_linkage.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/domain_linkage.proto) |
| `StatusList2021Credential` creation | `status_list_2021/StatusList2021Svc.create` | [status_list_2021.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/status_list_2021.proto) |
| `StatusList2021Credential` update | `status_list_2021/StatusList2021Svc.update` | [status_list_2021.proto](https://github.com/iotaledger/identity.rs/blob/grpc-bindings/bindings/grpc/proto/status_list_2021.proto) |

## Testing

### Domain Linkage

#### Http server
In order to test domain linkage, you need access to a server that is reachable via HTTPS. If you already have one, you can ignore the server setup steps here and and provide the `did-configuration.json` on your server.

1. create a folder with did configuration in it, e.g. (you can also use the template in `./tooling/domain-linkage-test-server`)
```raw
test-server/
└── .well-known
└── did-configuration.json
```

the `did-configuration` should look like this for now:

```json
{
"@context": "https://identity.foundation/.well-known/did-configuration/v1",
"linked_dids": [
"add your domain linkage credential here"
]
}
```
1. start a server that will serve this folder, e.g. with a NodeJs "http-server": `http-server ./test-server/`, in this example the server should now be running on local port 8080
1. tunnel your server's port (here 8080) to a public domain with https, e.g. with ngrok:
`ngrok http http://127.0.0.1:8080`
the output should now have a line like
`Forwarding https://0d40-2003-d3-2710-e200-485f-e8bb-7431-79a7.ngrok-free.app -> http://127.0.0.1:8080`
check that the https url is reachable, this will be used in the next step. You can also start ngrok with a static domain, which means you don't have to update credentials after each http server restart
1. for convenience, you can find a script to start the HTTP server, that you can adjust in `tooling/start-http-server.sh`, don't forget to insert your static domain or to remove the `--domain` parameter

#### Domain linkage credential
1. copy the public url and insert it into [6_domain_linkage.rs](../../examples/1_advanced/6_domain_linkage.rs) as domain 1, e.g. `let domain_1: Url = Url::parse("https://0d40-2003-d3-2710-e200-485f-e8bb-7431-79a7.ngrok-free.app")?;`
.1 run the example with `cargo run --release --example 6_domain_linkage`

#### GRPC server
1. grab the configuration resource from the log and replace the contents of your `did-configuration.json` with it
1. you now have a publicly reachable (sub)domain, that serves a `did-configuration` file containing a credential pointing to your DID
1. to verify this, run the server via Docker or with the following command, remember to replace the placeholders ;) `API_ENDPOINT=replace_me STRONGHOLD_PWD=replace_me SNAPSHOT_PATH=replace_me cargo run --release`
The arguments can be taken from examples, e.g. after running a `6_domain_linkage.rs`, which also logs snapshot path passed to secret manager (`let snapshot_path = random_stronghold_path(); dbg!(&snapshot_path.to_str());`), for example
- API_ENDPOINT: `"http://localhost"`
- STRONGHOLD_PWD: `"secure_password"`
- SNAPSHOT_PATH: `"/var/folders/41/s1sm86jx0xl4x435t81j81440000gn/T/test_strongholds/8o2Nyiv5ENBi7Ik3dEDq9gNzSrqeUdqi.stronghold"`
1. for convenience, you can find a script to start the GRPC server, that you can adjust in `tooling/start-rpc-server.sh`, don't forget to insert the env variables as described above

#### Calling the endpoints
1. call the `validate_domain` endpoint with your domain, e.g with:

```json
{
"domain": "https://0d40-2003-d3-2710-e200-485f-e8bb-7431-79a7.ngrok-free.app"
}
```

you should now receive a response like this:

```json
{
"linked_dids": [
{
"document": "... (compact JWT domain linkage credential)",
"status": "ok"
}
]
}
```

1. to call the `validate_did` endpoint, you need a DID to check, you can find a testable in you domain linkage credential. for this just decode it (e.g. on jwt.io) and get the `iss` value, then you can submit as "did" like following

```json
{
"did": "did:iota:snd:0x967bf8f0c7487f61378611b6a1c6a59cb99e65b839681ee70be691b09a024ab9"
}
```

you should not receive a response like this:

```json
{
"service": [
{
"service_endpoint": [
{
"valid": true,
"document": "eyJraWQiOiJkaWQ6aW90YTpzbmQ6MHg5NjdiZjhmMGM3NDg3ZjYxMzc4NjExYjZhMWM2YTU5Y2I5OWU2NWI4Mzk2ODFlZTcwYmU2OTFiMDlhMDI0YWI5IzA3QjVWRkxBa0FabkRhaC1OTnYwYUN3TzJ5ZnRzX09ZZ0YzNFNudUloMlUiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJleHAiOjE3NDE2NzgyNzUsImlzcyI6ImRpZDppb3RhOnNuZDoweDk2N2JmOGYwYzc0ODdmNjEzNzg2MTFiNmExYzZhNTljYjk5ZTY1YjgzOTY4MWVlNzBiZTY5MWIwOWEwMjRhYjkiLCJuYmYiOjE3MTAxNDIyNzUsInN1YiI6ImRpZDppb3RhOnNuZDoweDk2N2JmOGYwYzc0ODdmNjEzNzg2MTFiNmExYzZhNTljYjk5ZTY1YjgzOTY4MWVlNzBiZTY5MWIwOWEwMjRhYjkiLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vaWRlbnRpdHkuZm91bmRhdGlvbi8ud2VsbC1rbm93bi9kaWQtY29uZmlndXJhdGlvbi92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRG9tYWluTGlua2FnZUNyZWRlbnRpYWwiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsib3JpZ2luIjoiaHR0cHM6Ly9ob3QtYnVsbGRvZy1wcm9mb3VuZC5uZ3Jvay1mcmVlLmFwcC8ifX19.69e7T0DbRw9Kz7eEQ96P9E5HWbEo5F1fLuMjyQN6_Oa1lwBdbfj0wLlhS1j_d8AuNmvu60lMdLVixjMZJLQ5AA"
},
{
"valid": false,
"error": "domain linkage error: error sending request for url (https://bar.example.com/.well-known/did-configuration.json): error trying to connect: dns error: failed to lookup address information: nodename nor servname provided, or not known"
}
],
"id": "did:iota:snd:0x967bf8f0c7487f61378611b6a1c6a59cb99e65b839681ee70be691b09a024ab9"
}
]
}
```

Which tells us that it found a DID document with one matching service with a serviceEndpoint, that contains two domains. Out of these domains one links back to the given DID, the other domain could not be resolved.
Loading

0 comments on commit be022b0

Please sign in to comment.