-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
df5e38b
commit 9330e98
Showing
20 changed files
with
1,134 additions
and
170 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
...cision-records/2024-08-23-identity_hub_identity_write_credentials_api/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Identity Hub - Identity Write Credentials API | ||
|
||
## Decision | ||
|
||
Write endpoints (create/update) will be added to the Identity Hub identity API. | ||
|
||
## Rationale | ||
|
||
As of now the issuance of VCs into the Identity Hub is not defined as part of the DCP specification. Thus, it is | ||
impossible | ||
for now to add VCs within the Identity Hub at run time. | ||
|
||
To circumvent this issue, we will add write endpoints (create/update) to the Identity Hub identity API. | ||
|
||
> **_NOTE:_** It is strongly discouraged to expose these write endpoints public over the internet as they can be used | ||
> by malicious actors to compromise your VCs. The same warning applies for all identity APIs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
173 changes: 173 additions & 0 deletions
173
.../src/test/java/org/eclipse/edc/identityhub/tests/VerifiableCredentialApiEndToEndTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
/* | ||
* Copyright (c) 2024 Amadeus IT Group. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Apache License, Version 2.0 which is available at | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Contributors: | ||
* Amadeus IT Group - initial API and implementation | ||
* | ||
*/ | ||
|
||
package org.eclipse.edc.identityhub.tests; | ||
|
||
import io.restassured.http.Header; | ||
import org.eclipse.edc.iam.verifiablecredentials.spi.model.CredentialFormat; | ||
import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; | ||
import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredentialContainer; | ||
import org.eclipse.edc.identityhub.spi.participantcontext.ParticipantContextService; | ||
import org.eclipse.edc.identityhub.spi.verifiablecredentials.model.VerifiableCredentialManifest; | ||
import org.eclipse.edc.identityhub.tests.fixtures.IdentityHubEndToEndExtension; | ||
import org.eclipse.edc.identityhub.tests.fixtures.IdentityHubEndToEndTestContext; | ||
import org.eclipse.edc.junit.annotations.EndToEndTest; | ||
import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; | ||
import org.eclipse.edc.spi.EdcException; | ||
import org.eclipse.edc.spi.query.QuerySpec; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
|
||
import java.util.Arrays; | ||
import java.util.Base64; | ||
import java.util.UUID; | ||
|
||
import static io.restassured.http.ContentType.JSON; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.hamcrest.Matchers.notNullValue; | ||
|
||
public class VerifiableCredentialApiEndToEndTest { | ||
|
||
abstract static class Tests { | ||
|
||
@AfterEach | ||
void tearDown(ParticipantContextService store) { | ||
// purge all users | ||
store.query(QuerySpec.max()).getContent() | ||
.forEach(pc -> store.deleteParticipantContext(pc.getParticipantId()).getContent()); | ||
} | ||
|
||
@Test | ||
void findById(IdentityHubEndToEndTestContext context) { | ||
var superUserKey = context.createSuperUser(); | ||
var user = "user1"; | ||
var token = context.createParticipant(user); | ||
|
||
var credential = context.createCredential(); | ||
var resourceId = context.storeCredential(credential, user); | ||
|
||
assertThat(Arrays.asList(token, superUserKey)) | ||
.allSatisfy(t -> context.getIdentityApiEndpoint().baseRequest() | ||
.contentType(JSON) | ||
.header(new Header("x-api-key", t)) | ||
.get("/v1alpha/participants/%s/credentials/%s".formatted(toBase64(user), resourceId)) | ||
.then() | ||
.log().ifValidationFails() | ||
.statusCode(200) | ||
.body(notNullValue())); | ||
} | ||
|
||
@Test | ||
void create(IdentityHubEndToEndTestContext context) { | ||
var superUserKey = context.createSuperUser(); | ||
var user = "user1"; | ||
var token = context.createParticipant(user); | ||
|
||
assertThat(Arrays.asList(token, superUserKey)) | ||
.allSatisfy(t -> { | ||
var vc = context.createCredential(); | ||
var resourceId = UUID.randomUUID().toString(); | ||
var manifest = createManifest(user, vc).id(resourceId).build(); | ||
context.getIdentityApiEndpoint().baseRequest() | ||
.contentType(JSON) | ||
.header(new Header("x-api-key", t)) | ||
.body(manifest) | ||
.post("/v1alpha/participants/%s/credentials".formatted(toBase64(user))) | ||
.then() | ||
.log().ifValidationFails() | ||
.statusCode(204) | ||
.body(notNullValue()); | ||
|
||
var resource = context.getCredential(resourceId).orElseThrow(() -> new EdcException("Failed to credential with id %s".formatted(resourceId))); | ||
assertThat(resource.getVerifiableCredential().credential()).usingRecursiveComparison().isEqualTo(vc); | ||
}); | ||
} | ||
|
||
@Test | ||
void update(IdentityHubEndToEndTestContext context) { | ||
var superUserKey = context.createSuperUser(); | ||
var user = "user1"; | ||
var token = context.createParticipant(user); | ||
|
||
assertThat(Arrays.asList(token, superUserKey)) | ||
.allSatisfy(t -> { | ||
var credential1 = context.createCredential(); | ||
var credential2 = context.createCredential(); | ||
var resourceId1 = context.storeCredential(credential1, user); | ||
var manifest = createManifest(user, credential2).id(resourceId1).build(); | ||
context.getIdentityApiEndpoint().baseRequest() | ||
.contentType(JSON) | ||
.header(new Header("x-api-key", t)) | ||
.body(manifest) | ||
.put("/v1alpha/participants/%s/credentials".formatted(toBase64(user))) | ||
.then() | ||
.log().ifValidationFails() | ||
.statusCode(204) | ||
.body(notNullValue()); | ||
|
||
var resource = context.getCredential(resourceId1).orElseThrow(() -> new EdcException("Failed to retrieve credential with id %s".formatted(resourceId1))); | ||
assertThat(resource.getVerifiableCredential().credential()).usingRecursiveComparison().isEqualTo(credential2); | ||
}); | ||
} | ||
|
||
@Test | ||
void delete(IdentityHubEndToEndTestContext context) { | ||
var superUserKey = context.createSuperUser(); | ||
var user = "user1"; | ||
var token = context.createParticipant(user); | ||
|
||
assertThat(Arrays.asList(token, superUserKey)) | ||
.allSatisfy(t -> { | ||
var credential = context.createCredential(); | ||
var resourceId = context.storeCredential(credential, user); | ||
context.getIdentityApiEndpoint().baseRequest() | ||
.contentType(JSON) | ||
.header(new Header("x-api-key", t)) | ||
.delete("/v1alpha/participants/%s/credentials/%s".formatted(toBase64(user), resourceId)) | ||
.then() | ||
.log().ifValidationFails() | ||
.statusCode(204) | ||
.body(notNullValue()); | ||
|
||
var resource = context.getCredential(resourceId); | ||
assertThat(resource.isEmpty()).isTrue(); | ||
}); | ||
} | ||
|
||
private String toBase64(String s) { | ||
return Base64.getUrlEncoder().encodeToString(s.getBytes()); | ||
} | ||
|
||
private VerifiableCredentialManifest.Builder createManifest(String participantId, VerifiableCredential vc) { | ||
return VerifiableCredentialManifest.Builder.newInstance() | ||
.verifiableCredentialContainer(new VerifiableCredentialContainer("rawVc", CredentialFormat.JWT, vc)) | ||
.participantId(participantId); | ||
} | ||
|
||
} | ||
|
||
@Nested | ||
@EndToEndTest | ||
@ExtendWith(IdentityHubEndToEndExtension.InMemory.class) | ||
class InMemory extends Tests { | ||
} | ||
|
||
@Nested | ||
@PostgresqlIntegrationTest | ||
@ExtendWith(IdentityHubEndToEndExtension.Postgres.class) | ||
class Postgres extends Tests { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
extensions/api/identity-api/api-configuration/src/main/resources/identity-api-version.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.