8000 [26.6] Fix of getting client keystore without private pem. by lhanusov · Pull Request #55050 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ private void updateCertFromRequest(CertificateRepresentation info) {
}

/**
* Get a keystore file for the client, containing private key and public certificate
* Get a keystore file for the client, containing the public certificate
*
* @param config Keystore configuration as JSON
* @return
Expand All @@ -192,28 +192,23 @@ private void updateCertFromRequest(CertificateRepresentation info) {
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = KeycloakOpenAPI.Admin.Tags.CLIENT_ATTRIBUTE_CERTIFICATE)
@Operation( summary = "Get a keystore file for the client, containing private key and public certificate")
@Operation( summary = "Get a keystore file for the client, containing the public certificate")
public byte[] getKeystore(@Parameter(description = "Keystore configuration as JSON") final KeyStoreConfig config) {
auth.clients().requireView(client);

checkKeystoreFormat(config);

CertificateRepresentation info = CertificateInfoHelper.getCertificateFromClient(client, attributePrefix);
String privatePem = info.getPrivateKey();
String certPem = info.getCertificate();

if (privatePem == null && certPem == null) {
if (certPem == null) {
throw new NotFoundException("keypair not generated for client");
}
if (privatePem != null && config.getKeyPassword() == null) {
throw new ErrorResponseException("password-missing", "Need to specify a key password for jks download", Response.Status.BAD_REQUEST);
}
if (config.getStorePassword() == null) {
throw new ErrorResponseException("password-missing", "Need to specify a store password for jks download", Response.Status.BAD_REQUEST);
}

byte[] rtn = getKeystore(config, privatePem, certPem);
return rtn;
return getKeystore(config, null, certPem);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;

Expand Down Expand Up @@ -66,6 +67,7 @@
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
*
Expand Down Expand Up @@ -233,27 +235,27 @@ public void testDownloadKeystore() throws Exception {

// generate a key pair first
CertificateRepresentation certrep = certRsc.generate();
assertNotNull(certrep.getPrivateKey(), "Private key generated before downloading the certificate");

KeystoreUtil.KeystoreFormat preferredKeystoreType = KeystoreUtil.KeystoreFormat.valueOf(adminClient.serverInfo().getInfo().getCryptoInfo().getSupportedKeystoreTypes().get(0));

// download the key and certificate
// Download only the certificate without a key password, even when a private key is stored for the client
KeyStoreConfig config = new KeyStoreConfig();
config.setFormat(preferredKeystoreType.toString());
config.setKeyAlias("alias");
config.setKeyPassword("keyPass");
config.setStorePassword("storePass");
byte[] result = certRsc.getKeystore(config);

KeyStore keyStore = CryptoIntegration.getProvider().getKeyStore(preferredKeystoreType);
keyStore.load(new ByteArrayInputStream(result), "storePass".toCharArray());
Key key = keyStore.getKey("alias", "keyPass".toCharArray());
Key key = keyStore.getKey("alias", null);
Certificate cert = keyStore.getCertificate("alias");

assertInstanceOf(X509Certificate.class, cert, "Certificat is X509");
String keyPem = KeycloakModelUtils.getPemFromKey(key);
String certPem = KeycloakModelUtils.getPemFromCertificate((X509Certificate) cert);

assertEquals(certrep.getPrivateKey(), keyPem, "key match");
assertNull(key, "Downloaded keystore must not contain a private key");
assertTrue(keyStore.isCertificateEntry("alias"), "Downloaded entry is a certificate");
assertEquals(certrep.getCertificate(), certPem, "cert match");
}

Expand All @@ -279,6 +281,7 @@ public void testGenerateAndDownloadKeystore() throws Exception {
Key key = keyStore.getKey("alias", "keyPass".toCharArray());
Certificate cert = keyStore.getCertificate("alias");

assertInstanceOf(PrivateKey.class, key, "Generated keystore contains the private key");
assertInstanceOf(X509Certificate.class, cert, "Certificat is X509");
String keyPem = KeycloakModelUtils.getPemFromKey(key);
String certPem = KeycloakModelUtils.getPemFromCertificate((X509Certificate) cert);
Expand Down
Loading
0