You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by la...@apache.org on 2025/12/11 21:56:47 UTC
(airavata-custos) 02/04: generate test JWT tokens for testing
This is an automated email from the ASF dual-hosted git repository.
lahirujayathilake pushed a commit to branch custos-signer
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git
commit 9527c863fa80f038dbb183808920a68a30506771
Author: lahiruj <la...@gmail.com>
AuthorDate: Wed Dec 10 15:03:27 2025 -0500
generate test JWT tokens for testing
---
signer/signer-sdk-core/pom.xml | 5 +
.../signer/sdk/SshClientIntegrationTest.java | 12 ++-
.../signer/sdk/util/TestJwtTokenGenerator.java | 104 +++++++++++++++++++++
.../signer/service/ca/SshCertificateSigner.java | 2 +-
4 files changed, 118 insertions(+), 5 deletions(-)
diff --git a/signer/signer-sdk-core/pom.xml b/signer/signer-sdk-core/pom.xml
index 4bfbad373..adac60b1e 100644
--- a/signer/signer-sdk-core/pom.xml
+++ b/signer/signer-sdk-core/pom.xml
@@ -94,6 +94,11 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.nimbusds</groupId>
+ <artifactId>nimbus-jose-jwt</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/signer/signer-sdk-core/src/test/java/org/apache/custos/signer/sdk/SshClientIntegrationTest.java b/signer/signer-sdk-core/src/test/java/org/apache/custos/signer/sdk/SshClientIntegrationTest.java
index 1bb6b70b2..a29ee118f 100644
--- a/signer/signer-sdk-core/src/test/java/org/apache/custos/signer/sdk/SshClientIntegrationTest.java
+++ b/signer/signer-sdk-core/src/test/java/org/apache/custos/signer/sdk/SshClientIntegrationTest.java
@@ -20,6 +20,7 @@ package org.apache.custos.signer.sdk;
import org.apache.custos.signer.sdk.config.SdkConfiguration;
import org.apache.custos.signer.sdk.keystore.InMemoryKeyStore;
import org.apache.custos.signer.sdk.keystore.KeyStoreProvider;
+import org.apache.custos.signer.sdk.util.TestJwtTokenGenerator;
import org.apache.custos.signer.service.policy.KeyType;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
@@ -58,11 +59,14 @@ public class SshClientIntegrationTest {
try {
System.out.println("Requesting certificate materials (this will auto-generate CA key if first time) using keyType=" + keyType);
+ // Generate a valid JWT token for testing
+ String userToken = TestJwtTokenGenerator.generateTestToken("exouser");
+
CertificateMaterials materials = client.requestCertificateMaterials(
"test-client", // client alias
"exouser", // principal (SSH username)
3600, // TTL: 1 hour
- "test-token", // user token (for now, just a placeholder TODO)
+ userToken, // user token (valid JWT for testing)
keyType
);
@@ -74,7 +78,7 @@ public class SshClientIntegrationTest {
assertNotNull(materials.certBytes(), "Certificate bytes should not be null");
assertTrue(Objects.requireNonNull(materials.certBytes()).length > 0, "Certificate bytes should not be empty");
- System.out.println("✓ Certificate materials received successfully!");
+ System.out.println("Certificate materials received successfully!");
System.out.println(" Serial Number: " + materials.serial());
System.out.println(" CA Fingerprint: " + materials.caFingerprint());
System.out.println(" Target: " + materials.targetHost() + ":" + materials.targetPort());
@@ -87,8 +91,8 @@ public class SshClientIntegrationTest {
String certContent = materials.opensshCert().trim();
Files.write(Paths.get(certFile), certContent.getBytes());
- System.out.println("✓ Saved private key to: " + keyFile);
- System.out.println("✓ Saved certificate to: " + certFile);
+ System.out.println("Saved private key to: " + keyFile);
+ System.out.println("Saved certificate to: " + certFile);
System.out.println("\nNext steps:");
System.out.println("1. Extract CA public key from Vault:");
System.out.println(" vault kv get -field=public_key ssh-ca/nexus/test-client/current > /tmp/ca.pub");
diff --git a/signer/signer-sdk-core/src/test/java/org/apache/custos/signer/sdk/util/TestJwtTokenGenerator.java b/signer/signer-sdk-core/src/test/java/org/apache/custos/signer/sdk/util/TestJwtTokenGenerator.java
new file mode 100644
index 000000000..2a9a87421
--- /dev/null
+++ b/signer/signer-sdk-core/src/test/java/org/apache/custos/signer/sdk/util/TestJwtTokenGenerator.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.apache.custos.signer.sdk.util;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.JWSVerifier;
+import com.nimbusds.jose.crypto.MACSigner;
+import com.nimbusds.jose.crypto.MACVerifier;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.SignedJWT;
+
+import java.time.Instant;
+import java.util.Date;
+
+/**
+ * Utility class for generating test JWT tokens for integration tests.
+ */
+public class TestJwtTokenGenerator {
+
+ // Shared secret for signing (for testing only)
+ private static final String TEST_SECRET = "test-secret-key-for-jwt-signing-in-integration-tests-only";
+
+ /**
+ * Generate a test JWT token with the specified principal.
+ *
+ * @param principal The principal (username) to include in the token
+ * @return A signed JWT token string
+ */
+ public static String generateTestToken(String principal) {
+ return generateTestToken(principal, "custos-test-issuer", 3600);
+ }
+
+ /**
+ * Generate a test JWT token with custom claims.
+ *
+ * @param principal The principal (username) to include in the token
+ * @param issuer The issuer to include in the token
+ * @param ttlSeconds Token TTL in seconds
+ * @return A signed JWT token string
+ */
+ public static String generateTestToken(String principal, String issuer, int ttlSeconds) {
+ try {
+ Instant now = Instant.now();
+ Instant expiry = now.plusSeconds(ttlSeconds);
+
+ JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
+ .subject(principal)
+ .issuer(issuer)
+ .claim("preferred_username", principal)
+ .claim("email", principal + "@test.example.com")
+ .claim("sub", principal)
+ .issueTime(Date.from(now))
+ .expirationTime(Date.from(expiry))
+ .jwtID(java.util.UUID.randomUUID().toString())
+ .build();
+
+ JWSHeader header = new JWSHeader(JWSAlgorithm.HS256);
+ SignedJWT signedJWT = new SignedJWT(header, claimsSet);
+
+ JWSSigner signer = new MACSigner(TEST_SECRET);
+ signedJWT.sign(signer);
+
+ return signedJWT.serialize();
+
+ } catch (JOSEException e) {
+ throw new RuntimeException("Failed to generate test JWT token", e);
+ }
+ }
+
+ /**
+ * Verify a test JWT token (for testing the generator itself).
+ *
+ * @param token The JWT token to verify
+ * @return true if the token is valid
+ */
+ public static boolean verifyTestToken(String token) {
+ try {
+ SignedJWT signedJWT = SignedJWT.parse(token);
+ JWSVerifier verifier = new MACVerifier(TEST_SECRET);
+ return signedJWT.verify(verifier);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+}
+
diff --git a/signer/signer-service/src/main/java/org/apache/custos/signer/service/ca/SshCertificateSigner.java b/signer/signer-service/src/main/java/org/apache/custos/signer/service/ca/SshCertificateSigner.java
index 548f027b6..c054dfd7d 100644
--- a/signer/signer-service/src/main/java/org/apache/custos/signer/service/ca/SshCertificateSigner.java
+++ b/signer/signer-service/src/main/java/org/apache/custos/signer/service/ca/SshCertificateSigner.java
@@ -119,7 +119,7 @@ public class SshCertificateSigner {
} catch (Exception e) {
logger.error("Failed to sign SSH certificate for tenant: {}, client: {}, principal: {}",
tenantId, clientId, principal, e);
- throw new RuntimeException("Failed to sign SSH certificate", e);
+ throw new RuntimeException("Failed to sign SSH certificate: " + e.getMessage(), e);
}
}