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

feat: implement Admin API Credentials vertical #556

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 .github/workflows/verify.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ jobs:
docker run -d --rm --name issuer-service \
-e "EDC_STS_ACCOUNT_API_URL=https://sts.com" \
-e "EDC_STS_ACCOUNTS_API_AUTH_HEADER_VALUE=auth-header" \
-e "EDC_ISSUER_STATUSLIST_SIGNING_KEY_ALIAS=foo-alias" \
issuer-service:latest

- name: 'Wait for Issuer-Service to be healthy'
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

plugins {
`java-library`

}

val edcScmConnection: String by project
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ plugins {

dependencies {
api(project(":spi:verifiable-credential-spi"))
api(project(":spi:issuerservice:credential-revocation-spi"))
api(project(":spi:issuerservice:issuerservice-credential-spi"))
implementation(libs.edc.lib.token)
implementation(libs.nimbus.jwt)


implementation(libs.edc.spi.transaction)
implementation(libs.edc.lib.store)
testImplementation(project(":core:identity-hub-core"))
testImplementation(libs.edc.junit)
testImplementation(testFixtures(project(":spi:issuerservice:issuerservice-participant-spi")))

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,31 @@
*
*/

package org.eclipse.edc.issuerservice.statuslist;
package org.eclipse.edc.issuerservice.credentials;

import org.eclipse.edc.identityhub.spi.verifiablecredentials.store.CredentialStore;
import org.eclipse.edc.issuerservice.spi.statuslist.StatusListInfoFactoryRegistry;
import org.eclipse.edc.issuerservice.spi.statuslist.StatusListService;
import org.eclipse.edc.issuerservice.statuslist.bitstring.BitstringStatusListFactory;
import org.eclipse.edc.issuerservice.credentials.statuslist.StatusListInfoFactoryRegistryImpl;
import org.eclipse.edc.issuerservice.credentials.statuslist.bitstring.BitstringStatusListFactory;
import org.eclipse.edc.issuerservice.spi.credentials.CredentialService;
import org.eclipse.edc.issuerservice.spi.credentials.statuslist.StatusListInfoFactoryRegistry;
import org.eclipse.edc.jwt.signer.spi.JwsSignerProvider;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Provider;
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.spi.types.TypeManager;
import org.eclipse.edc.token.spi.TokenGenerationService;
import org.eclipse.edc.token.JwtGenerationService;
import org.eclipse.edc.transaction.spi.TransactionContext;

import static org.eclipse.edc.issuerservice.statuslist.StatusListServiceExtension.NAME;
import static org.eclipse.edc.issuerservice.credentials.CredentialServiceExtension.NAME;
import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD;

@Extension(value = NAME)
public class StatusListServiceExtension implements ServiceExtension {
public static final String NAME = "Status List Service Extension";
public class CredentialServiceExtension implements ServiceExtension {
public static final String NAME = "Issuer Service Credential Service Extension";
public static final String BITSTRING_STATUS_LIST_ENTRY = "BitstringStatusListEntry";

@Setting(description = "Alias for the private key that is intended for signing status list credentials", key = "edc.issuer.statuslist.signing.key.alias")
private String privateKeyAlias;
Expand All @@ -44,17 +47,19 @@ public class StatusListServiceExtension implements ServiceExtension {
@Inject
private TypeManager typeManager;
@Inject
private TokenGenerationService tokenGenerationService;
private JwsSignerProvider jwsSignerProvider;

private StatusListInfoFactoryRegistry factory;

@Provider
public StatusListService getStatusListService(ServiceExtensionContext context) {
public CredentialService getStatusListService(ServiceExtensionContext context) {
var fact = getFactory();

// Bitstring StatusList is provided by default. others can be added via extensions
fact.register("BitStringStatusListEntry", new BitstringStatusListFactory(store, typeManager.getMapper()));
fact.register(BITSTRING_STATUS_LIST_ENTRY, new BitstringStatusListFactory(store));

return new StatusListServiceImpl(store, transactionContext, typeManager.getMapper(JSON_LD), context.getMonitor(), tokenGenerationService,
var tokenGenerationService = new JwtGenerationService(jwsSignerProvider);
return new CredentialServiceImpl(store, transactionContext, typeManager.getMapper(JSON_LD), context.getMonitor(), tokenGenerationService,
() -> privateKeyAlias, fact);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,27 @@
*
*/

package org.eclipse.edc.issuerservice.statuslist;
package org.eclipse.edc.issuerservice.credentials;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.jose.JOSEException;
import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredentialContainer;
import org.eclipse.edc.identityhub.spi.participantcontext.model.IdentityResource;
import org.eclipse.edc.identityhub.spi.verifiablecredentials.model.VerifiableCredentialResource;
import org.eclipse.edc.identityhub.spi.verifiablecredentials.store.CredentialStore;
import org.eclipse.edc.issuerservice.spi.statuslist.StatusListInfo;
import org.eclipse.edc.issuerservice.spi.statuslist.StatusListInfoFactoryRegistry;
import org.eclipse.edc.issuerservice.spi.statuslist.StatusListService;
import org.eclipse.edc.issuerservice.spi.credentials.CredentialService;
import org.eclipse.edc.issuerservice.spi.credentials.statuslist.StatusListInfo;
import org.eclipse.edc.issuerservice.spi.credentials.statuslist.StatusListInfoFactoryRegistry;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.spi.result.ServiceResult;
import org.eclipse.edc.token.spi.TokenGenerationService;
import org.eclipse.edc.transaction.spi.TransactionContext;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;

Expand All @@ -40,7 +43,7 @@
import static org.eclipse.edc.spi.result.ServiceResult.success;
import static org.eclipse.edc.spi.result.ServiceResult.unexpected;

public class StatusListServiceImpl implements StatusListService {
public class CredentialServiceImpl implements CredentialService {
public static final TypeReference<Map<String, Object>> MAP_REF = new TypeReference<>() {
};
private static final String REVOCATION = "revocation";
Expand All @@ -52,7 +55,7 @@ public class StatusListServiceImpl implements StatusListService {
private final Supplier<String> privateKeyAlias;
private final StatusListInfoFactoryRegistry statusListInfoFactoryRegistry;

public StatusListServiceImpl(CredentialStore credentialStore,
public CredentialServiceImpl(CredentialStore credentialStore,
TransactionContext transactionContext,
ObjectMapper objectMapper,
Monitor monitor,
Expand Down Expand Up @@ -134,6 +137,17 @@ public ServiceResult<String> getCredentialStatus(String credentialId) {
.compose(r -> from(r.getStatus())));
}

@Override
public ServiceResult<Collection<VerifiableCredentialResource>> getCredentialForParticipant(String participantId) {
var query = IdentityResource.queryByParticipantContextId(participantId).build();
return queryCredentials(query);
}

@Override
public ServiceResult<Collection<VerifiableCredentialResource>> queryCredentials(QuerySpec query) {
return ServiceResult.from(credentialStore.query(query));
}

private ServiceResult<VerifiableCredentialResource> getCredential(String credentialId) {
// credential not found -> error
var credentialResult = credentialStore.findById(credentialId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
*
*/

package org.eclipse.edc.issuerservice.statuslist;
package org.eclipse.edc.issuerservice.credentials.statuslist;

import org.eclipse.edc.issuerservice.spi.statuslist.StatusListInfoFactory;
import org.eclipse.edc.issuerservice.spi.statuslist.StatusListInfoFactoryRegistry;
import org.eclipse.edc.issuerservice.spi.credentials.statuslist.StatusListInfoFactory;
import org.eclipse.edc.issuerservice.spi.credentials.statuslist.StatusListInfoFactoryRegistry;

import java.util.HashMap;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
*
*/

package org.eclipse.edc.issuerservice.statuslist.bitstring;
package org.eclipse.edc.issuerservice.credentials.statuslist.bitstring;

import org.eclipse.edc.iam.verifiablecredentials.spi.model.revocation.BitString;
import org.eclipse.edc.iam.verifiablecredentials.spi.model.revocation.bitstringstatuslist.BitstringStatusListCredential;
import org.eclipse.edc.identityhub.spi.verifiablecredentials.model.VerifiableCredentialResource;
import org.eclipse.edc.issuerservice.spi.statuslist.StatusListInfo;
import org.eclipse.edc.issuerservice.spi.credentials.statuslist.StatusListInfo;
import org.eclipse.edc.spi.result.Result;

import java.util.Base64;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
*
*/

package org.eclipse.edc.issuerservice.statuslist.bitstring;
package org.eclipse.edc.issuerservice.credentials.statuslist.bitstring;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.eclipse.edc.iam.verifiablecredentials.spi.model.CredentialStatus;
import org.eclipse.edc.identityhub.spi.verifiablecredentials.store.CredentialStore;
import org.eclipse.edc.issuerservice.spi.statuslist.StatusListInfo;
import org.eclipse.edc.issuerservice.spi.statuslist.StatusListInfoFactory;
import org.eclipse.edc.issuerservice.spi.credentials.statuslist.StatusListInfo;
import org.eclipse.edc.issuerservice.spi.credentials.statuslist.StatusListInfoFactory;
import org.eclipse.edc.spi.result.ServiceResult;

import static org.eclipse.edc.iam.verifiablecredentials.spi.VcConstants.BITSTRING_STATUS_LIST_PREFIX;
Expand All @@ -28,11 +27,9 @@

public class BitstringStatusListFactory implements StatusListInfoFactory {
private final CredentialStore credentialStore;
private final ObjectMapper objectMapper;

public BitstringStatusListFactory(CredentialStore credentialStore, ObjectMapper objectMapper) {
public BitstringStatusListFactory(CredentialStore credentialStore) {
this.credentialStore = credentialStore;
this.objectMapper = objectMapper;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
# Cofinity-X - initial API and implementation
#
#
org.eclipse.edc.issuerservice.statuslist.StatusListServiceExtension
org.eclipse.edc.issuerservice.credentials.CredentialServiceExtension
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
*/

package org.eclipse.edc.issuerservice.statuslist;
package org.eclipse.edc.issuerservice.credentials;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
Expand All @@ -33,7 +33,8 @@
import org.eclipse.edc.identityhub.spi.verifiablecredentials.model.VcStatus;
import org.eclipse.edc.identityhub.spi.verifiablecredentials.model.VerifiableCredentialResource;
import org.eclipse.edc.identityhub.spi.verifiablecredentials.store.CredentialStore;
import org.eclipse.edc.issuerservice.statuslist.bitstring.BitstringStatusListFactory;
import org.eclipse.edc.issuerservice.credentials.statuslist.StatusListInfoFactoryRegistryImpl;
import org.eclipse.edc.issuerservice.credentials.statuslist.bitstring.BitstringStatusListFactory;
import org.eclipse.edc.json.JacksonTypeManager;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.monitor.Monitor;
Expand All @@ -51,12 +52,12 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.eclipse.edc.issuerservice.statuslist.TestData.EXAMPLE_CREDENTIAL;
import static org.eclipse.edc.issuerservice.statuslist.TestData.EXAMPLE_CREDENTIAL_JWT;
import static org.eclipse.edc.issuerservice.statuslist.TestData.EXAMPLE_REVOCATION_CREDENTIAL;
import static org.eclipse.edc.issuerservice.statuslist.TestData.EXAMPLE_REVOCATION_CREDENTIAL_JWT;
import static org.eclipse.edc.issuerservice.statuslist.TestData.EXAMPLE_REVOCATION_CREDENTIAL_JWT_WITH_STATUS_BIT_SET;
import static org.eclipse.edc.issuerservice.statuslist.TestData.EXAMPLE_REVOCATION_CREDENTIAL_WITH_STATUS_BIT_SET;
import static org.eclipse.edc.issuerservice.credentials.statuslist.TestData.EXAMPLE_CREDENTIAL;
import static org.eclipse.edc.issuerservice.credentials.statuslist.TestData.EXAMPLE_CREDENTIAL_JWT;
import static org.eclipse.edc.issuerservice.credentials.statuslist.TestData.EXAMPLE_REVOCATION_CREDENTIAL;
import static org.eclipse.edc.issuerservice.credentials.statuslist.TestData.EXAMPLE_REVOCATION_CREDENTIAL_JWT;
import static org.eclipse.edc.issuerservice.credentials.statuslist.TestData.EXAMPLE_REVOCATION_CREDENTIAL_JWT_WITH_STATUS_BIT_SET;
import static org.eclipse.edc.issuerservice.credentials.statuslist.TestData.EXAMPLE_REVOCATION_CREDENTIAL_WITH_STATUS_BIT_SET;
import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat;
import static org.eclipse.edc.spi.result.ServiceFailure.Reason.BAD_REQUEST;
import static org.eclipse.edc.spi.result.ServiceFailure.Reason.NOT_FOUND;
Expand All @@ -73,7 +74,7 @@
import static org.mockito.Mockito.when;

@SuppressWarnings("unchecked")
class StatusListServiceImplTest {
class CredentialServiceImplTest {

public static final TypeReference<Map<String, Object>> MAP_REF = new TypeReference<>() {
};
Expand All @@ -83,7 +84,7 @@ class StatusListServiceImplTest {
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
private final CredentialStore credentialStore = mock();
private StatusListServiceImpl revocationService;
private CredentialServiceImpl revocationService;
private TokenGenerationService tokenGenerationService;
private Monitor monitor;
private ECKey signingKey;
Expand All @@ -95,8 +96,8 @@ void setUp() throws JOSEException {
when(tokenGenerationService.generate(any(), any())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("new-token").build()));
monitor = mock();
var reg = new StatusListInfoFactoryRegistryImpl();
reg.register("BitstringStatusListEntry", new BitstringStatusListFactory(credentialStore, objectMapper));
revocationService = new StatusListServiceImpl(credentialStore, new NoopTransactionContext(), objectMapper,
reg.register("BitstringStatusListEntry", new BitstringStatusListFactory(credentialStore));
revocationService = new CredentialServiceImpl(credentialStore, new NoopTransactionContext(), objectMapper,
monitor, tokenGenerationService, () -> "some-private-key", reg);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
*/

package org.eclipse.edc.issuerservice.statuslist;
package org.eclipse.edc.issuerservice.credentials.statuslist;

public class TestData {
public static final String EXAMPLE_CREDENTIAL = """
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
*
*/

package org.eclipse.edc.issuerservice.statuslist.bitstring;
package org.eclipse.edc.issuerservice.credentials.statuslist.bitstring;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.eclipse.edc.iam.verifiablecredentials.spi.model.CredentialStatus;
import org.eclipse.edc.identityhub.spi.verifiablecredentials.store.CredentialStore;
import org.eclipse.edc.spi.result.StoreResult;
Expand All @@ -31,8 +30,7 @@
class BitstringStatusListFactoryTest {

private final CredentialStore credentialStore = mock();
private final ObjectMapper objectMapper = new ObjectMapper();
private final BitstringStatusListFactory factory = new BitstringStatusListFactory(credentialStore, objectMapper);
private final BitstringStatusListFactory factory = new BitstringStatusListFactory(credentialStore);


@Test
Expand Down
1 change: 1 addition & 0 deletions dist/bom/issuerservice-base-bom/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ dependencies {
runtimeOnly(project(":core:identity-hub-keypairs"))
runtimeOnly(project(":core:issuerservice:issuerservice-core"))
runtimeOnly(project(":core:issuerservice:issuerservice-participants"))
runtimeOnly(project(":core:issuerservice:issuerservice-credentials"))
runtimeOnly(project(":extensions:did:local-did-publisher"))
// API modules
runtimeOnly(project(":extensions:protocols:dcp:dcp-issuer:dcp-issuer-api"))
Expand Down
5 changes: 1 addition & 4 deletions e2e-tests/admin-api-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,20 @@ dependencies {
testImplementation(project(":core:identity-hub-participants"))
testImplementation(project(":extensions:api:issuer-admin-api:participant-api")) // for the DTOs
testImplementation(project(":spi:issuerservice:issuerservice-participant-spi"))
testImplementation(project(":spi:issuerservice:issuerservice-credential-spi"))
testImplementation(libs.edc.junit)
testImplementation(libs.restAssured)
testImplementation(libs.awaitility)
testImplementation(libs.testcontainers.junit)
testImplementation(libs.testcontainers.postgres)

// needed for the Participant
testImplementation(testFixtures(libs.edc.testfixtures.managementapi))
testImplementation(testFixtures(libs.edc.sql.test.fixtures))
testImplementation(libs.edc.transaction.local)
testImplementation(libs.nimbus.jwt)
testImplementation(libs.jakarta.rsApi)
testImplementation(libs.edc.sts.spi)
testImplementation(testFixtures(project(":e2e-tests:fixtures")))

testCompileOnly(project(":dist:bom:identityhub-with-sts-bom"))
testCompileOnly(project(":dist:bom:identityhub-feature-sql-bom"))
}

edcBuild {
Expand Down
Loading