Skip to content

Commit 73ea306

Browse files
committed
Check & log pem and claims. Break if pem is not valid. Break if paths are not present or files do not exist.
1 parent 1c01b9b commit 73ea306

13 files changed

Lines changed: 146 additions & 22 deletions

File tree

iam-identity/src/main/java/org/eclipse/edc/identity/extension/FileParticipantIdentityLoader.java

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
import java.nio.file.Paths;
2626
import java.security.KeyFactory;
2727
import java.security.PrivateKey;
28+
import java.security.PublicKey;
2829
import java.security.Signature;
2930
import java.security.spec.PKCS8EncodedKeySpec;
31+
import java.security.spec.X509EncodedKeySpec;
3032
import java.util.Base64;
3133
import java.util.Map;
3234

@@ -79,10 +81,10 @@ public FileParticipantIdentityLoader(Monitor monitor, ObjectMapper mapper) {
7981
public Map<String, Object> loadClaims(String path) {
8082
var file = new File(path);
8183
try {
82-
monitor.debug("Trying to load claims from: " + file.getAbsolutePath());
84+
monitor.debug("Loading claims from: " + file.getAbsolutePath());
8385
return mapper.readValue(file, new TypeReference<Map<String, Object>>() {});
8486
} catch (Exception e) {
85-
monitor.warning("Error reading claims file: " + file.getAbsolutePath(), e);
87+
monitor.severe("Error reading claims from file: " + file.getAbsolutePath(), e);
8688
return Map.of();
8789
}
8890
}
@@ -113,7 +115,7 @@ public PrivateKey loadPrivateKey(String path) {
113115
return keyFactory.generatePrivate(spec);
114116
} catch (Exception e) {
115117
monitor.severe(String.format("Error loading private key from %s", filePath));
116-
return null;
118+
throw new RuntimeException(String.format("Error loading private key from %s", filePath));
117119
}
118120
}
119121

@@ -137,9 +139,61 @@ public String signClaims(Map<String, Object> claims, PrivateKey privateKey, Moni
137139
byte[] signedBytes = signature.sign();
138140
return Base64.getEncoder().encodeToString(signedBytes);
139141
} catch (Exception e) {
140-
monitor.warning("Claims could not be signed: " + e.getMessage(), e);
141-
return null;
142+
monitor.severe("Claims could not be signed: " + e.getMessage(), e);
143+
throw new RuntimeException("Claims could not be signed: " + e.getMessage(), e);
142144
}
143145
}
144146

147+
148+
@Override
149+
public PublicKey loadPublicKey(String path) {
150+
Path filePath = Paths.get(path);
151+
try {
152+
String content = new String(Files.readAllBytes(filePath));
153+
String pem = content
154+
.replaceAll("-+[A-Z ]+-+", "")
155+
.replaceAll("\\s", "");
156+
157+
byte[] keyBytes = Base64.getDecoder().decode(pem);
158+
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
159+
160+
KeyFactory keyFactory = KeyFactory.getInstance("Ed25519");
161+
return keyFactory.generatePublic(spec);
162+
163+
} catch (Exception e) {
164+
monitor.severe(String.format("Error loading public key from %s", filePath));
165+
throw new RuntimeException(String.format("Error loading public key from %s", filePath), e);
166+
}
167+
}
168+
169+
public boolean publicKeyMatchesPrivateKey(PublicKey publicKey, PrivateKey privateKey) {
170+
try {
171+
byte[] message = "key-validation".getBytes(StandardCharsets.UTF_8);
172+
173+
Signature signer = Signature.getInstance("Ed25519");
174+
signer.initSign(privateKey);
175+
signer.update(message);
176+
byte[] signature = signer.sign();
177+
178+
Signature verifier = Signature.getInstance("Ed25519");
179+
verifier.initVerify(publicKey);
180+
verifier.update(message);
181+
182+
if (!verifier.verify(signature)) {
183+
throw new RuntimeException("Public key does not match the provided private key");
184+
}
185+
186+
return true;
187+
188+
} catch (Exception e) {
189+
monitor.severe("Error validating public/private key pair");
190+
throw new RuntimeException("Error validating public/private key pair", e);
191+
}
192+
}
193+
194+
195+
196+
197+
198+
145199
}

iam-identity/src/main/java/org/eclipse/edc/identity/extension/IamIdentityExtension.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import org.eclipse.edc.spi.types.TypeManager;
2727

2828
import java.security.PrivateKey;
29+
import java.security.PublicKey;
30+
import java.util.Base64;
2931

3032
/**
3133
* The {@code IamIdentityExtension} class is a service extension that integrates an IAM-based
@@ -67,16 +69,32 @@ public String name() {
6769
@Override
6870
public void initialize(ServiceExtensionContext context) {
6971
var monitor = context.getMonitor();
70-
monitor.info("Initializing claims IAM Extension");
72+
monitor.info("Initializing iam-identity extension");
7173

72-
var claimsPath = context.getConfig().getString("edc.participant.claims", "creds.json");
73-
var participantPrivateKeyPath = context.getConfig().getString("edc.participant.private.key", "ed25519_private.pem");
74+
var claimsPath = context.getConfig().getString("edc.participant.claims");
75+
var participantPrivateKeyPath = context.getConfig().getString("edc.participant.private.key");
76+
var participantPublicKeyPath = context.getConfig().getString("edc.participant.public.key");
77+
var participantRegistryUrl = context.getConfig().getString("edc.participant.registry.url");
7478
var participantId = context.getParticipantId();
7579

7680
ParticipantIdentityLoader loader = new FileParticipantIdentityLoader(monitor, typeManager.getMapper());
7781
var claims = loader.loadClaims(claimsPath);
82+
83+
7884
PrivateKey participantPrivateKey = loader.loadPrivateKey(participantPrivateKeyPath);
85+
PublicKey participantPublicKey = loader.loadPublicKey(participantPublicKeyPath);
86+
String base64PublicKey = Base64.getEncoder().encodeToString(participantPublicKey.getEncoded());
7987
String signedClaims = loader.signClaims(claims, participantPrivateKey, monitor);
88+
boolean publicKeyMatchesPrivateKey = loader.publicKeyMatchesPrivateKey(participantPublicKey, participantPrivateKey);
89+
90+
if (publicKeyMatchesPrivateKey) {
91+
monitor.info("Private && Public keys has been successfully validated!");
92+
monitor.info("Claims has been successfully signed: " + signedClaims);
93+
monitor.info("Claims: " + claims);
94+
monitor.info("Public key: " + base64PublicKey);
95+
monitor.info("Participant registry url: " + participantRegistryUrl);
96+
}
97+
8098

8199
context.registerService(
82100
IdentityService.class,

iam-identity/src/main/java/org/eclipse/edc/identity/extension/ParticipantIdentityLoader.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.eclipse.edc.spi.monitor.Monitor;
1818

1919
import java.security.PrivateKey;
20+
import java.security.PublicKey;
2021
import java.util.Map;
2122

2223
/**
@@ -43,6 +44,25 @@ public interface ParticipantIdentityLoader {
4344
*/
4445
PrivateKey loadPrivateKey(String path);
4546

47+
48+
/**
49+
* Loads a public key from the specified file path.
50+
*
51+
* @param path the file path to the public key file
52+
* @return the loaded public key
53+
*/
54+
PublicKey loadPublicKey(String path);
55+
56+
/**
57+
* Verifies whether the provided public key corresponds to the provided private key.
58+
* This method is used to ensure the keys form a cryptographic pair and belong together.
59+
*
60+
* @param publicKey the public key to be verified
61+
* @param privateKey the private key to be matched with the public key
62+
* @return true if the public key matches the private key, false otherwise
63+
*/
64+
boolean publicKeyMatchesPrivateKey(PublicKey publicKey, PrivateKey privateKey);
65+
4666
/**
4767
* Signs the provided claims using the given private key and generates a signed representation.
4868
*
@@ -53,4 +73,6 @@ public interface ParticipantIdentityLoader {
5373
*/
5474
String signClaims(Map<String, Object> claims, PrivateKey privateKey, Monitor monitor);
5575

76+
77+
5678
}

providers/provider-base/resources/configuration/provider-base-configuration.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ edc.heleade.service.dataservice.credentials.default={\"description\": \"Default.
4040
# identity
4141
edc.participant.registry.url=http://localhost:39191/api/
4242
edc.participant.claims=providers/provider-base/resources/identity/claims.json
43-
edc.participant.private.key=providers/provider-base/resources/identity/ed25519_private.pem
43+
edc.participant.private.key=providers/provider-base/resources/identity/ed25519_private.pem
44+
edc.participant.public.key=providers/provider-base/resources/identity/ed25519_public.pem

providers/provider-base/resources/configuration/provider-base-docker-configuration.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ edc.heleade.service.dataservice.credentials.default={\"description\": \"Default.
4040
# identity
4141
edc.participant.registry.url=http://federated-catalog:39191/api/
4242
edc.participant.claims=identity/claims.json
43-
edc.participant.private.key=identity/ed25519_private.pem
43+
edc.participant.private.key=identity/ed25519_private.pem
44+
edc.participant.public.key=identity/ed25519_public.pem

providers/provider-ebird/resources/configuration/provider-ebird-configuration.properties

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,6 @@ edc.datasource.default.url=jdbc:postgresql://localhost:5432/edc_ebird
3535

3636

3737
edc.participant.registry.url=http://localhost:39191/api/
38-
edc.participant.claims=deployment/assets/provider/creds.json
39-
edc.participant.private.key=deployment/assets/provider/ed25519_private.pem
38+
edc.participant.claims=providers/provider-ebird/resources/identity/claims.json
39+
edc.participant.private.key=providers/provider-ebird/resources/identity/ed25519_private.pem
40+
edc.participant.public.key=providers/provider-ebird/resources/identity/ed25519_public.pem

providers/provider-ebird/resources/identity/creds.json renamed to providers/provider-ebird/resources/identity/claims.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"location": "eu",
33
"entity_type": "public"
4-
}
4+
}
5+

system-tests/src/test/java/org/eclipse/edc/heleade/common/PolicyCommon.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,22 @@ public class PolicyCommon {
5757

5858

5959
public static void generateKeys(String keyPath, String nodeDirectoryPath) throws Exception {
60-
ProcessBuilder pb = new ProcessBuilder(
61-
"bash",
62-
"src/test/resources/keys/generate-keys.sh",
63-
keyPath,
64-
nodeDirectoryPath
65-
);
60+
ProcessBuilder pb;
61+
62+
if (nodeDirectoryPath == null || nodeDirectoryPath.isBlank()) {
63+
pb = new ProcessBuilder(
64+
"bash",
65+
"src/test/resources/keys/generate-keys.sh",
66+
keyPath
67+
);
68+
} else {
69+
pb = new ProcessBuilder(
70+
"bash",
71+
"src/test/resources/keys/generate-keys.sh",
72+
keyPath,
73+
nodeDirectoryPath
74+
);
75+
}
6676

6777
pb.inheritIO();
6878

@@ -73,6 +83,7 @@ public static void generateKeys(String keyPath, String nodeDirectoryPath) throws
7383
}
7484

7585

86+
7687
public static boolean checkPolicyById(String policyId) {
7788
String response = get(PrerequisitesCommon.PROVIDER_MANAGEMENT_URL + V2_POLICY_DEFINITIONS_PATH + "/" + policyId, ID);
7889
return response != null && response.equals(policyId);

system-tests/src/test/java/org/eclipse/edc/heleade/policy/Policy01BasicTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public class Policy01BasicTest {
5151
private static final String CONSUMER_NODE_DIRECTORY_PATH = RESOURCES_FOLDER + "/consumer-participant-directory.json";
5252
private static final String CONSUMER_KEY_PATH = "src/test/resources/keys/consumer";
5353
private static final String PROVIDER_KEY_PATH = "src/test/resources/keys/provider";
54+
private static final String FC_KEY_PATH = "src/test/resources/keys/fc";
5455
private static final String CONSUMER_NODE_RELATIVE_PATH = "src/test/resources/policy/consumer-participant-directory.json";
5556
private static final String PROVIDER_NODE_RELATIVE_PATH = "src/test/resources/policy/provider-participant-directory.json";
5657
private static final String CATALOG_REQUEST_FILE_PATH = RESOURCES_FOLDER + "/catalog-request.json";
@@ -105,6 +106,7 @@ public class Policy01BasicTest {
105106
try {
106107
generateKeys(CONSUMER_KEY_PATH, CONSUMER_NODE_RELATIVE_PATH);
107108
generateKeys(PROVIDER_KEY_PATH, PROVIDER_NODE_RELATIVE_PATH);
109+
generateKeys(FC_KEY_PATH, "");
108110
} catch (Exception e) {
109111
throw new RuntimeException(e);
110112
}

system-tests/src/test/resources/consumer-test-configuration.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,7 @@ web.http.control.port=39192
1414
web.http.control.path=/control
1515
web.http.version.port=39195
1616
web.http.version.path=/version
17+
edc.participant.registry.url=http://localhost:59191/api/
1718
edc.participant.claims=src/test/resources/policy/claims.json
18-
edc.participant.private.key=src/test/resources/keys/consumer/ed25519_private.pem
19+
edc.participant.private.key=src/test/resources/keys/consumer/ed25519_private.pem
20+
edc.participant.public.key=src/test/resources/keys/consumer/ed25519_public.pem

0 commit comments

Comments
 (0)