Skip to content

Commit

Permalink
refactor: introduction of ProtocolTokenValidator (#3839)
Browse files Browse the repository at this point in the history
refactor: extracted BaseProtocolService into ProtocolTokenValidator
  • Loading branch information
wolf4ood committed Feb 9, 2024
1 parent 8bcbeeb commit 8193f3d
Show file tree
Hide file tree
Showing 16 changed files with 225 additions and 250 deletions.
Expand Up @@ -37,15 +37,14 @@
import org.eclipse.edc.connector.policy.spi.store.PolicyDefinitionStore;
import org.eclipse.edc.connector.service.contractnegotiation.ContractNegotiationProtocolServiceImpl;
import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationProtocolService;
import org.eclipse.edc.connector.spi.protocol.ProtocolTokenValidator;
import org.eclipse.edc.junit.annotations.ComponentTest;
import org.eclipse.edc.policy.model.Action;
import org.eclipse.edc.policy.model.Duty;
import org.eclipse.edc.policy.model.Policy;
import org.eclipse.edc.policy.model.PolicyType;
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.iam.VerificationContext;
import org.eclipse.edc.spi.message.RemoteMessageDispatcherRegistry;
import org.eclipse.edc.spi.monitor.ConsoleMonitor;
import org.eclipse.edc.spi.protocol.ProtocolWebhook;
Expand Down Expand Up @@ -117,7 +116,7 @@ class ContractNegotiationIntegrationTest {
private final ConsumerOfferResolver offerResolver = mock();
private final RemoteMessageDispatcherRegistry providerDispatcherRegistry = mock();
private final RemoteMessageDispatcherRegistry consumerDispatcherRegistry = mock();
private final IdentityService identityService = mock();
private final ProtocolTokenValidator protocolTokenValidator = mock();
private final ProtocolWebhook protocolWebhook = () -> "http://dummy";
protected ClaimToken token = ClaimToken.Builder.newInstance().build();
protected TokenRepresentation tokenRepresentation = TokenRepresentation.Builder.newInstance().build();
Expand Down Expand Up @@ -153,9 +152,9 @@ void init() {
.protocolWebhook(protocolWebhook)
.build();

when(identityService.verifyJwtToken(eq(tokenRepresentation), isA(VerificationContext.class))).thenReturn(Result.success(token));
consumerService = new ContractNegotiationProtocolServiceImpl(consumerStore, new NoopTransactionContext(), validationService, offerResolver, identityService, mock(), new ContractNegotiationObservableImpl(), monitor, mock());
providerService = new ContractNegotiationProtocolServiceImpl(providerStore, new NoopTransactionContext(), validationService, offerResolver, identityService, mock(), new ContractNegotiationObservableImpl(), monitor, mock());
when(protocolTokenValidator.verifyToken(eq(tokenRepresentation), any(), any())).thenReturn(ServiceResult.success(token));
consumerService = new ContractNegotiationProtocolServiceImpl(consumerStore, new NoopTransactionContext(), validationService, offerResolver, protocolTokenValidator, new ContractNegotiationObservableImpl(), monitor, mock());
providerService = new ContractNegotiationProtocolServiceImpl(providerStore, new NoopTransactionContext(), validationService, offerResolver, protocolTokenValidator, new ContractNegotiationObservableImpl(), monitor, mock());
}

@AfterEach
Expand Down
Expand Up @@ -37,6 +37,7 @@
import org.eclipse.edc.connector.service.contractnegotiation.ContractNegotiationServiceImpl;
import org.eclipse.edc.connector.service.policydefinition.PolicyDefinitionEventListener;
import org.eclipse.edc.connector.service.policydefinition.PolicyDefinitionServiceImpl;
import org.eclipse.edc.connector.service.protocol.ProtocolTokenValidatorImpl;
import org.eclipse.edc.connector.service.transferprocess.TransferProcessProtocolServiceImpl;
import org.eclipse.edc.connector.service.transferprocess.TransferProcessServiceImpl;
import org.eclipse.edc.connector.spi.asset.AssetService;
Expand All @@ -47,6 +48,7 @@
import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationProtocolService;
import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService;
import org.eclipse.edc.connector.spi.policydefinition.PolicyDefinitionService;
import org.eclipse.edc.connector.spi.protocol.ProtocolTokenValidator;
import org.eclipse.edc.connector.spi.transferprocess.TransferProcessProtocolService;
import org.eclipse.edc.connector.spi.transferprocess.TransferProcessService;
import org.eclipse.edc.connector.transfer.spi.TransferProcessManager;
Expand Down Expand Up @@ -148,6 +150,9 @@ public class ControlPlaneServicesExtension implements ServiceExtension {
@Inject
private PolicyEngine policyEngine;

@Inject(required = false)
private ProtocolTokenValidator protocolTokenValidator;

@Override
public String name() {
return NAME;
Expand All @@ -168,7 +173,7 @@ public CatalogService catalogService() {
@Provider
public CatalogProtocolService catalogProtocolService(ServiceExtensionContext context) {
return new CatalogProtocolServiceImpl(datasetResolver, participantAgentService, dataServiceRegistry,
identityService, policyEngine, monitor, context.getParticipantId(), transactionContext);
protocolTokenValidator(), context.getParticipantId(), transactionContext);
}

@Provider
Expand All @@ -191,7 +196,7 @@ public ContractNegotiationService contractNegotiationService() {
@Provider
public ContractNegotiationProtocolService contractNegotiationProtocolService() {
return new ContractNegotiationProtocolServiceImpl(contractNegotiationStore,
transactionContext, contractValidationService, consumerOfferResolver, identityService, policyEngine, contractNegotiationObservable,
transactionContext, contractValidationService, consumerOfferResolver, protocolTokenValidator(), contractNegotiationObservable,
monitor, telemetry);
}

Expand All @@ -211,6 +216,14 @@ public TransferProcessService transferProcessService() {
@Provider
public TransferProcessProtocolService transferProcessProtocolService() {
return new TransferProcessProtocolServiceImpl(transferProcessStore, transactionContext, contractNegotiationStore,
contractValidationService, identityService, policyEngine, dataAddressValidator, transferProcessObservable, clock, monitor, telemetry);
contractValidationService, protocolTokenValidator(), dataAddressValidator, transferProcessObservable, clock, monitor, telemetry);
}

@Provider
public ProtocolTokenValidator protocolTokenValidator() {
if (protocolTokenValidator == null) {
protocolTokenValidator = new ProtocolTokenValidatorImpl(identityService, policyEngine, monitor);
}
return protocolTokenValidator;
}
}
Expand Up @@ -19,21 +19,24 @@
import org.eclipse.edc.catalog.spi.DataServiceRegistry;
import org.eclipse.edc.catalog.spi.Dataset;
import org.eclipse.edc.catalog.spi.DatasetResolver;
import org.eclipse.edc.connector.service.protocol.BaseProtocolService;
import org.eclipse.edc.connector.spi.catalog.CatalogProtocolService;
import org.eclipse.edc.policy.engine.spi.PolicyEngine;
import org.eclipse.edc.connector.spi.protocol.ProtocolTokenValidator;
import org.eclipse.edc.policy.engine.spi.PolicyScope;
import org.eclipse.edc.policy.model.Policy;
import org.eclipse.edc.spi.agent.ParticipantAgentService;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.ServiceResult;
import org.eclipse.edc.transaction.spi.TransactionContext;
import org.jetbrains.annotations.NotNull;

import static java.lang.String.format;
import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE;

public class CatalogProtocolServiceImpl extends BaseProtocolService implements CatalogProtocolService {
public class CatalogProtocolServiceImpl implements CatalogProtocolService {

@PolicyScope
public static final String CATALOGING_REQUEST_SCOPE = "request.catalog";

private static final String PARTICIPANT_ID_PROPERTY_KEY = "participantId";

Expand All @@ -43,20 +46,18 @@ public class CatalogProtocolServiceImpl extends BaseProtocolService implements C
private final String participantId;
private final TransactionContext transactionContext;

private PolicyEngine policyEngine;
private final ProtocolTokenValidator protocolTokenValidator;

public CatalogProtocolServiceImpl(DatasetResolver datasetResolver,
ParticipantAgentService participantAgentService,
DataServiceRegistry dataServiceRegistry,
IdentityService identityService,
PolicyEngine policyEngine,
Monitor monitor,
ProtocolTokenValidator protocolTokenValidator,
String participantId,
TransactionContext transactionContext) {
super(identityService, policyEngine, monitor);
this.datasetResolver = datasetResolver;
this.participantAgentService = participantAgentService;
this.dataServiceRegistry = dataServiceRegistry;
this.protocolTokenValidator = protocolTokenValidator;
this.participantId = participantId;
this.transactionContext = transactionContext;
}
Expand Down Expand Up @@ -93,4 +94,9 @@ public ServiceResult<Catalog> getCatalog(CatalogRequestMessage message, TokenRep
return ServiceResult.success(dataset);
}));
}

private ServiceResult<ClaimToken> verifyToken(TokenRepresentation tokenRepresentation) {
return protocolTokenValidator.verifyToken(tokenRepresentation, CATALOGING_REQUEST_SCOPE, Policy.Builder.newInstance().build());
}
}

Expand Up @@ -30,13 +30,11 @@
import org.eclipse.edc.connector.contract.spi.validation.ContractValidationService;
import org.eclipse.edc.connector.contract.spi.validation.ValidatableConsumerOffer;
import org.eclipse.edc.connector.contract.spi.validation.ValidatedConsumerOffer;
import org.eclipse.edc.connector.service.protocol.BaseProtocolService;
import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationProtocolService;
import org.eclipse.edc.policy.engine.spi.PolicyEngine;
import org.eclipse.edc.connector.spi.protocol.ProtocolTokenValidator;
import org.eclipse.edc.policy.engine.spi.PolicyScope;
import org.eclipse.edc.policy.model.Policy;
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.ServiceResult;
Expand All @@ -51,15 +49,15 @@

import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation.Type.PROVIDER;

public class ContractNegotiationProtocolServiceImpl extends BaseProtocolService implements ContractNegotiationProtocolService {
public class ContractNegotiationProtocolServiceImpl implements ContractNegotiationProtocolService {

@PolicyScope
private static final String CONTRACT_NEGOTIATION_REQUEST_SCOPE = "request.contract.negotiation";
public static final String CONTRACT_NEGOTIATION_REQUEST_SCOPE = "request.contract.negotiation";
private final ContractNegotiationStore store;
private final TransactionContext transactionContext;
private final ContractValidationService validationService;
private final ConsumerOfferResolver consumerOfferResolver;

private final ProtocolTokenValidator protocolTokenValidator;
private final ContractNegotiationObservable observable;
private final Monitor monitor;
private final Telemetry telemetry;
Expand All @@ -68,15 +66,14 @@ public ContractNegotiationProtocolServiceImpl(ContractNegotiationStore store,
TransactionContext transactionContext,
ContractValidationService validationService,
ConsumerOfferResolver consumerOfferResolver,
IdentityService identityService,
PolicyEngine policyEngine,
ProtocolTokenValidator protocolTokenValidator,
ContractNegotiationObservable observable,
Monitor monitor, Telemetry telemetry) {
super(identityService, policyEngine, monitor);
this.store = store;
this.transactionContext = transactionContext;
this.validationService = validationService;
this.consumerOfferResolver = consumerOfferResolver;
this.protocolTokenValidator = protocolTokenValidator;
this.observable = observable;
this.monitor = monitor;
this.telemetry = telemetry;
Expand Down Expand Up @@ -326,7 +323,7 @@ private ServiceResult<ClaimTokenContext> verifyRequest(TokenRepresentation token
}

private ServiceResult<ClaimTokenContext> verifyRequest(TokenRepresentation tokenRepresentation, Policy policy, ContractNegotiation contractNegotiation) {
var result = verifyToken(tokenRepresentation, CONTRACT_NEGOTIATION_REQUEST_SCOPE, policy);
var result = protocolTokenValidator.verifyToken(tokenRepresentation, CONTRACT_NEGOTIATION_REQUEST_SCOPE, policy);
if (result.failed()) {
monitor.debug(() -> "Verification Failed: %s".formatted(result.getFailureDetail()));
return ServiceResult.notFound("Not found");
Expand Down
Expand Up @@ -14,6 +14,7 @@

package org.eclipse.edc.connector.service.protocol;

import org.eclipse.edc.connector.spi.protocol.ProtocolTokenValidator;
import org.eclipse.edc.policy.engine.spi.PolicyContextImpl;
import org.eclipse.edc.policy.engine.spi.PolicyEngine;
import org.eclipse.edc.policy.model.Policy;
Expand All @@ -25,21 +26,19 @@
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.ServiceResult;

import java.util.List;

/**
* Base class for all protocol service implementation. This will contain common logic such as validating the JWT token
* and extracting the {@link ClaimToken}
* Implementation of {@link ProtocolTokenValidator} which uses the {@link PolicyEngine} for extracting
* the scope from the {@link Policy} within a scope
*/
public abstract class BaseProtocolService {
public class ProtocolTokenValidatorImpl implements ProtocolTokenValidator {

private final IdentityService identityService;

private final PolicyEngine policyEngine;

private final Monitor monitor;

protected BaseProtocolService(IdentityService identityService, PolicyEngine policyEngine, Monitor monitor) {
public ProtocolTokenValidatorImpl(IdentityService identityService, PolicyEngine policyEngine, Monitor monitor) {
this.identityService = identityService;
this.monitor = monitor;
this.policyEngine = policyEngine;
Expand All @@ -49,21 +48,13 @@ protected BaseProtocolService(IdentityService identityService, PolicyEngine poli
* Validate and extract the {@link ClaimToken} from the input {@link TokenRepresentation} by using the {@link IdentityService}
*
* @param tokenRepresentation The input {@link TokenRepresentation}
* @param policyScope The policy scope
* @param policy The {@link Policy}
* @return The {@link ClaimToken} if success, failure otherwise
*/
//TODO remove once this lands https://github.com/eclipse-edc/Connector/issues/3819
protected ServiceResult<ClaimToken> verifyToken(TokenRepresentation tokenRepresentation) {
// TODO: since we are pushing here the invocation of the IdentityService we don't know the audience here
// The audience removal will be tackle next. IdentityService that relies on this parameter would not work
// for the time being.

// TODO: policy extractors will be handled next
var verificationContext = VerificationContext.Builder.newInstance()
.policy(Policy.Builder.newInstance().build())
.scopes(List.of())
.build();

return verifyToken(tokenRepresentation, verificationContext);
@Override
public ServiceResult<ClaimToken> verifyToken(TokenRepresentation tokenRepresentation, String policyScope, Policy policy) {
return verifyToken(tokenRepresentation, createVerificationContext(policyScope, policy));
}

protected ServiceResult<ClaimToken> verifyToken(TokenRepresentation tokenRepresentation, VerificationContext verificationContext) {
Expand All @@ -76,19 +67,6 @@ protected ServiceResult<ClaimToken> verifyToken(TokenRepresentation tokenReprese
return ServiceResult.success(result.getContent());
}


/**
* Validate and extract the {@link ClaimToken} from the input {@link TokenRepresentation} by using the {@link IdentityService}
*
* @param tokenRepresentation The input {@link TokenRepresentation}
* @param scope The policy scope
* @param policy The {@link Policy}
* @return The {@link ClaimToken} if success, failure otherwise
*/
protected ServiceResult<ClaimToken> verifyToken(TokenRepresentation tokenRepresentation, String scope, Policy policy) {
return verifyToken(tokenRepresentation, createVerificationContext(scope, policy));
}

private VerificationContext createVerificationContext(String scope, Policy policy) {
var requestScopeBuilder = RequestScope.Builder.newInstance();
var policyContext = PolicyContextImpl.Builder.newInstance()
Expand Down

0 comments on commit 8193f3d

Please sign in to comment.