Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS has been phased out. To see alternatives please check here

Skip to content
Snippets Groups Projects
Commit 9666b47e authored by Szymon Truszczyński's avatar Szymon Truszczyński
Browse files

Merge branch 'release' into 'main'

Release

See merge request !66
parents 00327e65 3e8706cd
No related branches found
No related tags found
1 merge request!66Release
Pipeline #289118 passed with warnings
Showing
with 136 additions and 568 deletions
| author name | ticket url | sprint number | comment | action: ADDED/UPDATED/REMOVED |
|------------------------------------------|--------------------------------------------------|---------------|------------------------------------|-------------------------------|
|------------------------------------------|---------------------------------------------------|---------------|------------------------------------|-------------------------------|
| Szymon Truszczyński | https://jira.simplprogramme.eu/browse/SIMPL-9498 | 11 | | |
| Alicja Nicieja | https://jira.simplprogramme.eu/browse/SIMPL-8048 | 9 | | |
| Aleksandra Beliankina | https://jira.simplprogramme.eu/browse/SIMPL-8350 | 9 | | |
......@@ -15,3 +15,7 @@
| Valerii Kalashnikov, Szymon Truszczyński | https://jira.simplprogramme.eu/browse/SIMPL-9494 | 12 | | UPDATED |
| Szymon Truszczyński | https://jira.simplprogramme.eu/browse/SIMPL-9106 | 12 | | UPDATED |
| Valerii Kalashnikov | https://jira.simplprogramme.eu/browse/SIMPL-9494 | 12 | add activation of remote debugging | ADDED |
| Daniel Witkowski | https://jira.simplprogramme.eu/browse/SIMPL-7905 | 12 | | ADDED |
| Valerii Kalashnikov | https://jira.simplprogramme.eu/browse/SIMPL-10547 | 13 | | UPDATED |
| Szymon Truszczyński | https://jira.simplprogramme.eu/browse/SIMPL-10140 | 13 | | ADDED |
| Szymon Truszczyński | https://jira.simplprogramme.eu/browse/SIMPL-9103 | 13 | | UPDATED |
......@@ -36,6 +36,8 @@ spec:
command: [ "/bin/sh" ]
args: [ "-c", "source /vault/secrets/config.txt && java -jar /connector.jar" ]
imagePullPolicy: {{ .Values.deployment.imagePullPolicy }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
env:
- name: web.http.port
value: "{{ .Values.service.apiPort | default "29191" }}"
......
......@@ -3,6 +3,19 @@ deployment:
tag: "${PROJECT_RELEASE_VERSION}"
imagePullPolicy: Always
resources:
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
limits:
cpu: 250m
memory: 1Gi
requests:
cpu: 250m
memory: 1Gi
ingress:
enabled: true
apiPath: /api
......
steps for launching connectors on docker environment:
1. Run step. please run below command in docker folder
`docker-compose up`
in terminal logs we should see that provider and consumer connector are up and running.
in provider connector LocationConstraintFunction.java is declared it overrides method called evaluate and return
boolean based on region fetched from claim and operator.
There is also PolicyFunctionsExtension.java where we 'register' our constraint function during initialization of porvider edc.
each of instances has his own set of properties defined in docker-compose where for example port numbers are set
One particular property called `edc.mock.region=us` set for consumer will be important for our presentation.
2. Create asset, policy and contract definition on provider side. To do so please execute following http calls
to create asset
```
curl --location 'http://localhost:19193/management/v3/assets' \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: password' \
--data-raw '{
"@context": {
"@vocab": "https://w3id.org/edc/v0.0.1/ns/"
},
"@id": "test-document",
"properties": {
"name": "product description",
"contenttype": "application/json"
},
"dataAddress": {
"type": "test"
}
}'
```
to create policy (important note: this policy allows access only for region=eu and we set us for our provider earlier in docker-compose)
```
curl --location 'http://localhost:19193/management/v3/policydefinitions' \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: password' \
--data-raw '{
"@context": {
"@vocab": "https://w3id.org/edc/v0.0.1/ns/"
},
"@id": "eu-policy",
"policy": {
"@context": "http://www.w3.org/ns/odrl.jsonld",
"@type": "Set",
"permission": [
{
"action": "use",
"constraint": {
"@type": "AtomicConstraint",
"leftOperand": "location",
"operator": {
"@id": "odrl:eq"
},
"rightOperand": "eu"
}
}
],
"prohibition": [],
"obligation": []
}
}'
```
to create contract definition (which binds given asset to policy)
```
curl --location 'http://localhost:19193/management/v3/contractdefinitions' \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: password' \
--data-raw '{
"@context": {
"@vocab": "https://w3id.org/edc/v0.0.1/ns/"
},
"@id": "1",
"accessPolicyId": "eu-policy",
"contractPolicyId": "eu-policy",
"assetsSelector": [{
"@type": "CriterionDto",
"operandLeft": "https://w3id.org/edc/v0.0.1/ns/id",
"operator": "=",
"operandRight": "test-document"
}]
}'
```
4. make request to query provider catalogue, and start negotiation between consumer and provider
to query provider catalogue by consumer
```
curl --location 'http://localhost:29193/management/v3/catalog/request' \
--header 'Content-Type: application/json' \
--header 'x-api-key: password' \
--data-raw '{
"@context": {
"@vocab": "https://w3id.org/edc/v0.0.1/ns/"
},
"counterPartyAddress": "http://provider:19194/protocol",
"protocol": "dataspace-protocol-http"
}'
```
we can see there previously created asset with attached policy. Keep
in mind that this action is allowed cause we registered function in PolicyFunctionExtension.java with negotiation scope.
that means that during next step which is to start negotiation call should be rejected because of policy that allows only
negotiation from eu region.
to start negotiation
```
curl --location 'http://localhost:29193/management/v3/contractnegotiations' \
--header 'Content-Type: application/json' \
--header 'x-api-key: password' \
--data-raw '{
"@context": {
"@vocab": "https://w3id.org/edc/v0.0.1/ns/"
},
"@type": "ContractRequest",
"counterPartyAddress": "http://provider:19194/protocol",
"protocol": "dataspace-protocol-http",
"policy": {
"@context": "http://www.w3.org/ns/odrl.jsonld",
"@id": "1:test-document:13dce0f1-52ed-4554-a194-e83e92733ee5",
"@type": "Offer",
"permission": [
{
"action": "use",
"target": "test-document",
"constraint": {
"@type": "AtomicConstraint",
"leftOperand": "location",
"operator": "eq",
"rightOperand": "eu"
}
}
],
"assigner": "provider",
"target": "test-document"
}
}'
```
Worth noting is fact that 'counterPartyAddress' changed in comparison to local execution from localhost to provider.
Reason is we created network for 2 containers via docker-compose so localhost need to be changed to the name of the service
defined in docker-compose.yml file. In this case service has been named as 'provider'
response is ok 200 cause this process is done async. but when we check consumer logs we can see something like
```
SEVERE 2024-09-12T12:28:50.782221 ContractNegotiation: ID 94db42da-b9b5-48dd-a0d0-5bba45bbbcb6.
Fatal error while [Consumer] send request. Error details: {"@type":"dspace:ContractNegotiationError",
"dspace:code":"400","dspace:reason":"Contract offer is not valid: Policy in scope contract.negotiation not
fulfilled for offer MQ==:dGVzdC1kb2N1bWVudA==:MTNkY2UwZjEtNTJlZC00NTU0LWExOTQtZTgzZTkyNzMzZWU1, policy evaluation
Permission constraints: [Constraint 'https://w3id.org/edc/v0.0.1/ns/location' EQ 'eu']",
"@context":{"@vocab":"https://w3id.org/edc/v0.0.1/ns/","edc":"https://w3id.org/edc/v0.0.1/ns/","dcat":"http://www.
w3.org/ns/dcat#","dct":"http://purl.org/dc/terms/","odrl":"http://www.w3.org/ns/odrl/2/","dspace":"https://w3id.org/dspace/v0.8/"}}
```
which states that due to policy was not fulfilled whole negotiation failed.
As another proof we can execute call to check contract negotiation status
```
curl --location 'http://localhost:29193/management/v3/contractnegotiations/94db42da-b9b5-48dd-a0d0-5bba45bbbcb6' \
--header 'x-api-key: password'
```
which will confirm what was previously written
\ No newline at end of file
version: '3.8'
services:
hashicorp-vault:
container_name: hashicorp-vault
image: vault:1.9.7
ports:
- "8200:8200"
environment:
VAULT_DEV_ROOT_TOKEN_ID: ${VAULT_TOKEN}
VAULT_ADDR: ${VAULT_ADDRESS}
cap_add:
- IPC_LOCK
healthcheck:
test: [ "CMD", "sh", "-c", "sleep 1 && apk add --no-cache curl && curl --fail http://localhost:8200/v1/sys/health || exit 1" ]
interval: 30s
timeout: 10s
retries: 5
consumer-db:
image: postgres:latest
container_name: consumer-db
ports:
- "5433:5432"
environment:
POSTGRES_USER: ${EDC_DATASOURCE_DEFAULT_USER}
POSTGRES_PASSWORD: ${EDC_DATASOURCE_DEFAULT_PASSWORD}
healthcheck:
test: pg_isready -d postgres -U postgres
interval: 10s
timeout: 5s
retries: 3
start_period: 5s
provider-db:
image: postgres:latest
container_name: provider-db
ports:
- "5432:5432"
environment:
POSTGRES_USER: ${EDC_DATASOURCE_DEFAULT_USER}
POSTGRES_PASSWORD: ${EDC_DATASOURCE_DEFAULT_PASSWORD}
healthcheck:
test: pg_isready -d postgres -U postgres
interval: 10s
timeout: 5s
retries: 3
start_period: 5s
provider-contract-manager-mock:
image: code.europa.eu:4567/simpl/simpl-open/development/gaia-x-edc/simpl-contract-negotiation-mockup:1.0.0
container_name: provContractManagerMock
ports:
- "8081:8080"
consumer-contract-manager-mock:
image: code.europa.eu:4567/simpl/simpl-open/development/gaia-x-edc/simpl-contract-negotiation-mockup:1.0.0
container_name: consContractManagerMock
ports:
- "8080:8080"
\ No newline at end of file
version: '3.8'
services:
hashicorp-vault:
container_name: hashicorp-vault
image: vault:1.9.7
ports:
- "8200:8200"
environment:
VAULT_DEV_ROOT_TOKEN_ID: ${VAULT_TOKEN}
VAULT_ADDR: ${VAULT_ADDRESS}
cap_add:
- IPC_LOCK
healthcheck:
test: [ "CMD", "sh", "-c", "sleep 1 && apk add --no-cache curl && curl --fail http://localhost:8200/v1/sys/health || exit 1" ]
interval: 30s
timeout: 10s
retries: 5
File added
File added
File added
......@@ -21,9 +21,9 @@ edc.datasource.default.user=postgres
edc.datasource.default.password=postgres
edc.datasource.default.url=jdbc:postgresql://localhost:5433/postgres
contractmanager.extension.enabled=true
contractmanager.extension.enabled=false
contractmanager.apikey=test
contractmanager.url=http://localhost:8080/contract/v1/
contractmanager.url=http://localhost:8080/contract/v1
edc.ionos.access.key=<value stored in hashicorp vault instance under kv/data/gaia-x/gaiax-edc-dev-provider-simpl-edc>
edc.ionos.endpoint=<value stored in hashicorp vault instance under kv/data/gaia-x/gaiax-edc-dev-provider-simpl-edc>
......
......@@ -29,9 +29,9 @@ edc.datasource.policy.url=jdbc:postgresql://localhost:5432/postgres
edc.component.id=provider
contractmanager.extension.enabled=true
contractmanager.extension.enabled=false
contractmanager.apikey=test
contractmanager.url=http://localhost:8081/contract/v1/
contractmanager.url=http://localhost:8081/contract/v1
edc.ionos.access.key=<value stored in hashicorp vault instance under kv/data/gaia-x/gaiax-edc-dev-provider-simpl-edc>
edc.ionos.endpoint=<value stored in hashicorp vault instance under kv/data/gaia-x/gaiax-edc-dev-provider-simpl-edc>
......
PROJECT_VERSION_NUMBER="1.0.3"
PROJECT_VERSION_NUMBER="1.0.4"
......@@ -210,21 +210,21 @@
<artifactId>provision-ionos-s3</artifactId>
<version>{ionosVersion}</version>
<scope>system</scope>
<systemPath>${basedir}/libs/provision-ionos-s3-v3.1.1.jar</systemPath>
<systemPath>${basedir}/libs/provision-ionos-s3-v3.1.2.jar</systemPath>
</dependency>
<dependency>
<groupId>com.ionoscloud.edc</groupId>
<artifactId>core-ionos-s3</artifactId>
<version>{ionosVersion}</version>
<scope>system</scope>
<systemPath>${basedir}/libs/core-ionos-s3-v3.1.1.jar</systemPath>
<systemPath>${basedir}/libs/core-ionos-s3-v3.1.2.jar</systemPath>
</dependency>
<dependency>
<groupId>com.ionoscloud.edc</groupId>
<artifactId>data-plane-ionos-s3</artifactId>
<version>{ionosVersion}</version>
<scope>system</scope>
<systemPath>${basedir}/libs/data-plane-ionos-s3-v3.1.1.jar</systemPath>
<systemPath>${basedir}/libs/data-plane-ionos-s3-v3.1.2.jar</systemPath>
</dependency>
<!-- dependencies required for infrastructure deployment -->
......
{
"openapi": "3.0.3",
"info": {
"title": "EDC Contract Manager Extension ",
"description": "EDC Contract Manager Callback HTTP APIs for interaction with the Contract Manager.",
"version": "1.0"
},
"servers": [
{
"url": "http://localhost:29191",
"description": "EDC Contract Manager Callback"
}
],
"paths": {
"/api/health": {
"get": {
"tags": [
"health"
],
"summary": "health check endpoint",
"description": "Health check endpoint",
"operationId": "health#Liveness",
"responses": {
"200": {
"description": "OK response.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HealthResponse"
}
}
}
}
}
}
},
"/api/signed/{contractNegotiationId}/{signed}": {
"post": {
"tags": [
"signed"
],
"summary": "callback contract is signed",
"description": "reset Pending Guard to continue with contract negotiation process.",
"operationId": "contractNegotiation#Continue",
"parameters": [
{
"name": "x-api-key",
"in": "header",
"description": "Authorization",
"required": true,
"schema": {
"type": "string",
"description": "credentials for api request"
},
"example": "b9c1991b-d6f0-4c88-9291-172c3209b291"
},
{
"name": "contractAgreementId",
"in": "path",
"description": "Contract Negotiation Id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"example": "0ec61c92-677b-4e97-aef1-ed542e37183b"
},
{
"name": "signed",
"in": "path",
"description": "Flag whether contract is signed or rejected",
"required": true,
"schema": {
"type": "boolean",
"format": "true|false"
},
"example": "0ec61c92-677b-4e97-aef1-ed542e37183b"
}
],
"responses": {
"200": {
"description": "OK response.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Response"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json;charset=utf-8": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json;charset=utf-8": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json;charset=utf-8": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json;charset=utf-8": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"405": {
"description": "Method Not allowed",
"content": {
"application/json;charset=utf-8": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"409": {
"description": "Conflict",
"content": {
"application/json;charset=utf-8": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json;charset=utf-8": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Response": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "ID of contract negotiation",
"example": "677186f6-1179-4cf1-b845-68d1c00c185f."
},
"status": {
"type": "string",
"description": "Status of the contract negotiation process.",
"example": "AGREED"
}
},
"example": {
"id": "677186f6-1179-4cf1-b845-68d1c00c185f",
"status": "AGREED"
},
"required": [
"signature"
]
},
"HealthResponse": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Disclosed Credential",
"example": "UP",
"format": "binary"
}
},
"example": {
"status": "UP"
},
"required": [
"valid"
]
},
"Error": {
"required": [
"code",
"reason"
],
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Application relevant detail, defined in the API or a common list."
},
"reason": {
"type": "string",
"description": "Explanation of the reason for the error which can be shown to a client user."
},
"message": {
"type": "string",
"description": "More details and corrective actions related to the error which can be shown to a client user."
},
"status": {
"type": "string",
"description": "HTTP Error code extension"
},
"referenceError": {
"type": "string",
"description": "URI of documentation describing the error.",
"format": "uri"
},
"@baseType": {
"type": "string",
"description": "When sub-classing, this defines the super-class."
},
"@schemaLocation": {
"type": "string",
"description": "A URI to a JSON-Schema file that defines additional attributes and relationships",
"format": "uri"
},
"@type": {
"type": "string",
"description": "When sub-classing, this defines the sub-class entity name."
}
},
"description": "Used when an API throws an Error, typically with a HTTP error response-code (3xx, 4xx, 5xx)"
}
}
},
"tags": [
{
"name": "health",
"description": "Health service provides health check endpoints."
},
{
"name": "signed",
"description": "Callback continue with contract negotiation."
}
]
}
\ No newline at end of file
......@@ -60,7 +60,7 @@ public class ContractSignApiController {
*/
@POST
@Path("signed/{contractNegotiationId}/{signed}")
public Response callbackSigned(@PathParam("contractNegotiationId") @DefaultValue("id") String contractNegotiationId,
public Response notifyStateMachineAboutContractNegotiation(@PathParam("contractNegotiationId") @DefaultValue("id") String contractNegotiationId,
@PathParam("signed") @DefaultValue("true") boolean signed) {
monitor.info(format("%s :: Received a contract signed callback request for ", contractNegotiationId));
// get ContractNegotiation by ID
......
......@@ -3,12 +3,15 @@ package eu.europa.ec.simpl.iam.service;
import java.util.Objects;
import eu.europa.ec.simpl.client.core.adapters.EphemeralProofAdapter;
import lombok.Builder;
import lombok.Getter;
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.Provides;
import org.eclipse.edc.spi.iam.AudienceResolver;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.Result;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
......@@ -33,17 +36,29 @@ public class IamExtension implements ServiceExtension {
@Override
public void initialize(ServiceExtensionContext context) {
var region = context.getSetting("edc.mock.region", "eu");
var participantId = context.getParticipantId();
final var isGatewayDisabled = Objects.equals(context.getSetting("client.okhttp.type", ""), "OkHttpClient");
final var predefinedEphemeralProofToken = context.getSetting("ephemeral.proof.token", "");
final var iamExtensionContext = IamExtensionContext.builder()
.region(context.getSetting("edc.mock.region", "eu"))
.participantId(context.getParticipantId())
.isGatewayDisabled(Objects.equals(context.getSetting("client.okhttp.type", ""), "OkHttpClient"))
.predefinedEphemeralProofToken(context.getSetting("ephemeral.proof.token", ""))
.monitor(context.getMonitor())
.build();
context.registerService(IdentityService.class, new SimplIdentityService(typeManager, region, participantId,
ephemeralProofAdapter, isGatewayDisabled, predefinedEphemeralProofToken));
context.registerService(IdentityService.class, new SimplIdentityService(typeManager, ephemeralProofAdapter, iamExtensionContext));
}
@Provider
public AudienceResolver audienceResolver() {
return (msg) -> Result.success(msg.getCounterPartyAddress());
}
@Builder
@Getter
public static class IamExtensionContext {
final String region;
final String participantId;
final boolean isGatewayDisabled;
final String predefinedEphemeralProofToken;
final Monitor monitor;
}
}
......@@ -4,6 +4,7 @@ import eu.europa.ec.simpl.client.core.adapters.EphemeralProofAdapter;
import eu.europa.ec.simpl.iam.jwt.JwtTokenDecoder;
import eu.europa.ec.simpl.iam.jwt.IdentityAttribute;
import eu.europa.ec.simpl.iam.jwt.TokenInfo;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.IdentityService;
import org.eclipse.edc.spi.iam.TokenParameters;
......@@ -15,42 +16,38 @@ import org.eclipse.edc.spi.types.TypeManager;
import java.util.List;
import java.util.Optional;
@Slf4j
public class SimplIdentityService implements IdentityService {
private final String region;
private final String clientId;
private final TypeManager typeManager;
private final EphemeralProofAdapter ephemeralProofAdapter;
private final String predefinedEphemeralProofToken;
private final IamExtension.IamExtensionContext extensionContext;
private final boolean isGatewayDisabled;
public SimplIdentityService(TypeManager typeManager, String region, String clientId,
public SimplIdentityService(TypeManager typeManager,
EphemeralProofAdapter ephemeralProofAdapter,
boolean isGatewayDisabled,
final String predefinedEphemeralProofToken) {
IamExtension.IamExtensionContext extensionContext) {
this.typeManager = typeManager;
this.region = region;
this.clientId = clientId;
this.ephemeralProofAdapter = ephemeralProofAdapter;
this.isGatewayDisabled = isGatewayDisabled;
this.predefinedEphemeralProofToken = predefinedEphemeralProofToken;
this.extensionContext = extensionContext;
}
@Override
public Result<TokenRepresentation> obtainClientCredentials(TokenParameters parameters) {
var token = new Token();
final var ephemeralProof = this.isGatewayDisabled ? Optional.of(predefinedEphemeralProofToken)
final var ephemeralProof = extensionContext.isGatewayDisabled()
? Optional.of(extensionContext.getPredefinedEphemeralProofToken())
: ephemeralProofAdapter.loadEphemeralProof();
JwtTokenDecoder jwtTokenDecoder = new JwtTokenDecoder();
if (ephemeralProof.isPresent()) {
extensionContext.getMonitor().debug("SimplIdentityService::obtainClientCredentials -> ephemeral proof token = " + ephemeralProof.get());
TokenInfo tokenInfo = jwtTokenDecoder.getTokenInfo(ephemeralProof.get());
token.setIdentityAttributes(tokenInfo.getAttributes());
}
extensionContext.getMonitor().debug("SimplIdentityService::obtainClientCredentials -> aud claim = " + parameters.getStringClaim("aud"));
token.setAudience(parameters.getStringClaim("aud"));
token.setRegion(region);
token.setClientId(clientId);
token.setRegion(extensionContext.getRegion());
token.setClientId(extensionContext.getParticipantId());
return Result.success(TokenRepresentation.Builder.newInstance()
.token(typeManager.writeValueAsString(token))
.build());
......
......@@ -7,6 +7,7 @@ import org.eclipse.edc.connector.controlplane.contract.spi.negotiation.store.Con
import org.eclipse.edc.connector.controlplane.services.spi.contractnegotiation.ContractNegotiationService;
import org.eclipse.edc.http.spi.EdcHttpClient;
import org.eclipse.edc.spi.event.EventRouter;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.system.Hostname;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.spi.system.configuration.ConfigFactory;
......@@ -57,6 +58,9 @@ class ContractSignCallbackEndpointExtensionTest {
@Mock
private EventRouter eventRouter;
@Mock
private Monitor monitor;
@InjectMocks
private ContractSignCallbackEndpointExtension contractSignCallbackEndpointExtension;
......@@ -64,6 +68,8 @@ class ContractSignCallbackEndpointExtensionTest {
void initializeShouldBeSuccessfulExtensionEnabled() {
final var context = mock(ServiceExtensionContext.class);
when(context.getSetting(CONTRACT_MANAGER_EXTENSION_ENABLED, "false")).thenReturn("true");
when(context.getMonitor())
.thenReturn(monitor);
var config = new HashMap<String, String>();
config.put(CONTRACT_MANAGER_URL, "http://localhost:8080");
......@@ -76,6 +82,9 @@ class ContractSignCallbackEndpointExtensionTest {
@Test
void initializeShouldBeSuccessfulExtensionDisabled() {
final var context = mock(ServiceExtensionContext.class);
when(context.getMonitor())
.thenReturn(monitor);
when(context.getSetting(CONTRACT_MANAGER_EXTENSION_ENABLED, "false")).thenReturn("false");
assertDoesNotThrow(() -> contractSignCallbackEndpointExtension.initialize(context));
}
......
......@@ -11,9 +11,7 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class IamExtensionTest {
......@@ -30,9 +28,6 @@ class IamExtensionTest {
@Test
void initializeShouldNotThrowException() {
final var context = mock(ServiceExtensionContext.class);
when(context.getSetting(anyString(), anyString()))
.thenReturn("region");
when(context.getParticipantId()).thenReturn("participantId");
assertThatCode(() -> iamExtension.initialize(context))
.doesNotThrowAnyException();
......
......@@ -8,7 +8,9 @@ import org.eclipse.edc.json.JacksonTypeManager;
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.iam.TokenParameters;
import org.eclipse.edc.spi.iam.TokenRepresentation;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.Result;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
......@@ -22,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
......@@ -35,10 +38,18 @@ class SimplIdentityServiceTest {
@Mock
private TokenParameters tokenParameters;
@Mock
private ServiceExtensionContext context;
@Mock
private Monitor monitor;
@Test
void obtainClientCredentialTestShouldReturnCorrectTokenRepresentationFromEphemeralProofAdapter() {
// given
SimplIdentityService simplIdentityService = new SimplIdentityService(new JacksonTypeManager(), "eu", "clientId", ephemeralProofAdapter, false, "");
SimplIdentityService simplIdentityService = new SimplIdentityService(new JacksonTypeManager(),
ephemeralProofAdapter,
produceValidIamExtensionContextWithEnabledGateway());
// when
when(tokenParameters.getStringClaim("aud")).thenReturn("aud");
......@@ -54,10 +65,13 @@ class SimplIdentityServiceTest {
@Test
void obtainClientCredentialTestShouldReturnCorrectTokenRepresentationFromPredefinedToken() {
// given
SimplIdentityService simplIdentityService = new SimplIdentityService(new JacksonTypeManager(), "eu", "clientId", ephemeralProofAdapter, true, TokenUtil.getValidToken());
SimplIdentityService simplIdentityService = new SimplIdentityService(new JacksonTypeManager(),
ephemeralProofAdapter,
produceValidIamExtensionContextWithDisabledGateway());
// when
when(tokenParameters.getStringClaim("aud")).thenReturn("aud");
final var tokenRepresentationResult = simplIdentityService.obtainClientCredentials(tokenParameters);
// then
......@@ -70,7 +84,9 @@ class SimplIdentityServiceTest {
@Test
void obtainClientCredentialShouldThrowEdcTokenParseException() {
// given
SimplIdentityService simplIdentityService = new SimplIdentityService(new JacksonTypeManager(), "eu", "clientId", ephemeralProofAdapter, false, "");
SimplIdentityService simplIdentityService = new SimplIdentityService(new JacksonTypeManager(),
ephemeralProofAdapter,
produceValidIamExtensionContextWithEnabledGateway());
// when
when(ephemeralProofAdapter.loadEphemeralProof()).thenReturn(Optional.of("6.8.9"));
......@@ -85,10 +101,13 @@ class SimplIdentityServiceTest {
@Test
void obtainClientCredentialShouldThrowIllegalArgumentException() {
// given
SimplIdentityService simplIdentityService = new SimplIdentityService(new JacksonTypeManager(), "eu", "clientId", ephemeralProofAdapter, false, "");
SimplIdentityService simplIdentityService = new SimplIdentityService(new JacksonTypeManager(),
ephemeralProofAdapter,
produceValidIamExtensionContextWithEnabledGateway());
// when
when(ephemeralProofAdapter.loadEphemeralProof()).thenReturn(Optional.of(TokenUtil.getValidTokenWithDifferentAttributes()));
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
() -> simplIdentityService.obtainClientCredentials(tokenParameters));
......@@ -99,19 +118,42 @@ class SimplIdentityServiceTest {
@Test
void verifyJwtTokenShouldReturnCorrectClaim() {
// given
SimplIdentityService simplIdentityService = new SimplIdentityService(new JacksonTypeManager(), "eu", "clientId", ephemeralProofAdapter, false, "");
SimplIdentityService simplIdentityService = new SimplIdentityService(new JacksonTypeManager(),
ephemeralProofAdapter,
produceValidIamExtensionContextWithEnabledGateway());
// when
when(tokenParameters.getStringClaim("aud")).thenReturn("aud");
when(ephemeralProofAdapter.loadEphemeralProof()).thenReturn(Optional.of(TokenUtil.getValidToken()));
Result<TokenRepresentation> tokenRepresentationResult = simplIdentityService.obtainClientCredentials(tokenParameters);
Result<ClaimToken> claimTokenResult = simplIdentityService.verifyJwtToken(tokenRepresentationResult.getContent(), null);
// then
Map<String, Object> claims = claimTokenResult.getContent().getClaims();
assertEquals(3, claims.size());
assertEquals("eu", claims.get("region"));
assertEquals("clientId", claims.get("client_id"));
assertEquals("region", claims.get("region"));
assertEquals("participantId", claims.get("client_id"));
assertEquals(4, ((List<IdentityAttribute>) claims.get("identity_attributes")).size());
}
private IamExtension.IamExtensionContext produceValidIamExtensionContextWithDisabledGateway() {
return IamExtension.IamExtensionContext.builder()
.region("region")
.participantId("participantId")
.isGatewayDisabled(true)
.predefinedEphemeralProofToken(TokenUtil.getValidToken())
.monitor(mock(Monitor.class))
.build();
}
private IamExtension.IamExtensionContext produceValidIamExtensionContextWithEnabledGateway() {
return IamExtension.IamExtensionContext.builder()
.region("region")
.participantId("participantId")
.isGatewayDisabled(false)
.predefinedEphemeralProofToken("")
.monitor(mock(Monitor.class))
.build();
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment