KEYCLOAK-905 More testing
This commit is contained in:
parent
d2cae0f8c3
commit
4e245d428c
7 changed files with 449 additions and 13 deletions
|
@ -53,10 +53,8 @@ public class JavaKeystoreKeyProvider extends AbstractRsaKeyProvider {
|
|||
|
||||
KeyPair keyPair = new KeyPair(publicKey, privateKey);
|
||||
|
||||
X509Certificate certificate;
|
||||
if (model.contains(JavaKeystoreKeyProviderFactory.CERTIFICATE_ALIAS_KEY)) {
|
||||
certificate = (X509Certificate) keyStore.getCertificate(model.get(JavaKeystoreKeyProviderFactory.CERTIFICATE_ALIAS_KEY));
|
||||
} else {
|
||||
X509Certificate certificate = (X509Certificate) keyStore.getCertificate(model.get(JavaKeystoreKeyProviderFactory.KEY_ALIAS_KEY));
|
||||
if (certificate == null) {
|
||||
certificate = CertificateUtils.generateV1SelfSignedCertificate(keyPair, realm.getName());
|
||||
}
|
||||
|
||||
|
|
|
@ -48,9 +48,6 @@ public class JavaKeystoreKeyProviderFactory extends AbstractRsaKeyProviderFactor
|
|||
public static String KEY_PASSWORD_KEY = "keyPassword";
|
||||
public static ProviderConfigProperty KEY_PASSWORD_PROPERTY = new ProviderConfigProperty(KEY_PASSWORD_KEY, "Private Key password", "Password for the private key", STRING_TYPE, null, true);
|
||||
|
||||
public static String CERTIFICATE_ALIAS_KEY = "certificateAlias";
|
||||
public static ProviderConfigProperty CERTIFICATE_ALIAS_PROPERTY = new ProviderConfigProperty(CERTIFICATE_ALIAS_KEY, "Certificate Alias", "Alias for the certificate", STRING_TYPE, null);
|
||||
|
||||
private static final String HELP_TEXT = "Loads keys from a Java keys file";
|
||||
|
||||
private static final List<ProviderConfigProperty> CONFIG_PROPERTIES = AbstractRsaKeyProviderFactory.configurationBuilder()
|
||||
|
@ -58,7 +55,6 @@ public class JavaKeystoreKeyProviderFactory extends AbstractRsaKeyProviderFactor
|
|||
.property(KEYSTORE_PASSWORD_PROPERTY)
|
||||
.property(KEY_ALIAS_PROPERTY)
|
||||
.property(KEY_PASSWORD_PROPERTY)
|
||||
.property(CERTIFICATE_ALIAS_PROPERTY)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
|
@ -74,8 +70,7 @@ public class JavaKeystoreKeyProviderFactory extends AbstractRsaKeyProviderFactor
|
|||
.checkSingle(KEYSTORE_PROPERTY, true)
|
||||
.checkSingle(KEYSTORE_PASSWORD_PROPERTY, true)
|
||||
.checkSingle(KEY_ALIAS_PROPERTY, true)
|
||||
.checkSingle(KEY_PASSWORD_PROPERTY, true)
|
||||
.checkSingle(CERTIFICATE_ALIAS_PROPERTY, false);
|
||||
.checkSingle(KEY_PASSWORD_PROPERTY, true);
|
||||
|
||||
try {
|
||||
new JavaKeystoreKeyProvider(session.getContext().getRealm(), model)
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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 License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.keys;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.keycloak.common.util.KeyUtils;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.keys.Attributes;
|
||||
import org.keycloak.keys.GeneratedRsaKeyProviderFactory;
|
||||
import org.keycloak.keys.JavaKeystoreKeyProviderFactory;
|
||||
import org.keycloak.keys.KeyMetadata;
|
||||
import org.keycloak.keys.KeyProvider;
|
||||
import org.keycloak.keys.RsaKeyProviderFactory;
|
||||
import org.keycloak.representations.idm.ComponentRepresentation;
|
||||
import org.keycloak.representations.idm.ErrorRepresentation;
|
||||
import org.keycloak.representations.idm.KeysMetadataRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.pages.AppPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyPair;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class JavaKeystoreKeyProviderTest extends AbstractKeycloakTest {
|
||||
|
||||
private static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsPAJ/X39oNRkoS+baWVhAghfO86ZPfkSHm4evmMDhbA0KqW1/hg55qUJoT91ytGozIsIxoCLKzQvZTluRpt0AMp7cmfaGWBQ8cBtb8/BL+5FkUucigmOcTrfPq9/xR9g4AMSXRItjLRsJPy2Bnjau64DVQ3N5NVbWAMw7/1XjuobEyPnw0RLqEr/TxWMteuaiV1n8amIAiT91xZ8UFyPv3urCkAz+r+iyVvdJcZwn2tUL6KLM7qX/HSX8SUtPrIMB8EdW1yNt5McO8Ro5GxwiyXimDKbY9ur2WP8/wrdk/0TkoUYeI1UsnFyoJcqqg2+1T+dNAMtJhF7uDhURVQ33QIDAQAB";
|
||||
private static final String CERTIFICATE = "MIIDeTCCAmGgAwIBAgIEbhSauDANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMCAXDTE2MTAxMzE4MjUxNFoYDzIyOTAwNzI4MTgyNTE0WjBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsPAJ/X39oNRkoS+baWVhAghfO86ZPfkSHm4evmMDhbA0KqW1/hg55qUJoT91ytGozIsIxoCLKzQvZTluRpt0AMp7cmfaGWBQ8cBtb8/BL+5FkUucigmOcTrfPq9/xR9g4AMSXRItjLRsJPy2Bnjau64DVQ3N5NVbWAMw7/1XjuobEyPnw0RLqEr/TxWMteuaiV1n8amIAiT91xZ8UFyPv3urCkAz+r+iyVvdJcZwn2tUL6KLM7qX/HSX8SUtPrIMB8EdW1yNt5McO8Ro5GxwiyXimDKbY9ur2WP8/wrdk/0TkoUYeI1UsnFyoJcqqg2+1T+dNAMtJhF7uDhURVQ33QIDAQABoyEwHzAdBgNVHQ4EFgQUgz0ABmkImZUEO2/w0shoH4rp6pwwDQYJKoZIhvcNAQELBQADggEBAK+syjqfFXmv7942+ZfmJfb4i/JilhwSyA2G1VvGR39dLW1nPmKMMUY6kKgJ2NZgaCGvJ4jxDhfNJ1jPG7rcO/eQuF3cx9r+nHiTcJ5PNLqG2q4dNNFshJ8aGuIaTQEB7S1OlGsEj0rd0YlJ+LTrFfEHsnsJvpvDRLdVMklib5fPk4W8ziuQ3rr6T/a+be3zfAqmFZx8j6E46jz9QO841uwqdzcR9kfSHS/76TNGZv8OB6jheyHrUdBygR85iizHgMqats/0zWmKEAvSp/DhAfyIFp8zZHvPjmpBl+mfmAqnrYY0oJRb5rRXmL8DKq5plc7jgO1H6aHh5mV6slXQDEw=";
|
||||
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder folder = new TemporaryFolder();
|
||||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(this);
|
||||
|
||||
@Page
|
||||
protected AppPage appPage;
|
||||
|
||||
@Page
|
||||
protected LoginPage loginPage;
|
||||
private File file;
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation realm = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
|
||||
testRealms.add(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeAbstractKeycloakTest() throws Exception {
|
||||
super.beforeAbstractKeycloakTest();
|
||||
|
||||
file = folder.newFile("keystore.jsk");
|
||||
|
||||
InputStream resourceAsStream = JavaKeystoreKeyProviderTest.class.getResourceAsStream("keystore.jks");
|
||||
IOUtils.copy(resourceAsStream, new FileOutputStream(file));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() throws Exception {
|
||||
long priority = System.currentTimeMillis();
|
||||
|
||||
ComponentRepresentation rep = createRep("valid", priority);
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
String id = ApiUtil.getCreatedId(response);
|
||||
|
||||
ComponentRepresentation createdRep = adminClient.realm("test").components().component(id).toRepresentation();
|
||||
assertEquals(5, createdRep.getConfig().size());
|
||||
assertEquals(Long.toString(priority), createdRep.getConfig().getFirst("priority"));
|
||||
assertEquals(ComponentRepresentation.SECRET_VALUE, createdRep.getConfig().getFirst("keystorePassword"));
|
||||
assertEquals(ComponentRepresentation.SECRET_VALUE, createdRep.getConfig().getFirst("keyPassword"));
|
||||
|
||||
KeysMetadataRepresentation keys = adminClient.realm("test").keys().getKeyMetadata();
|
||||
|
||||
KeysMetadataRepresentation.KeyMetadataRepresentation key = keys.getKeys().get(0);
|
||||
|
||||
assertEquals(id, key.getProviderId());
|
||||
assertEquals(KeyMetadata.Type.RSA.name(), key.getType());
|
||||
assertEquals(priority, key.getProviderPriority());
|
||||
assertEquals(PUBLIC_KEY, key.getPublicKey());
|
||||
assertEquals(CERTIFICATE, key.getCertificate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidKeystore() throws Exception {
|
||||
ComponentRepresentation rep = createRep("valid", System.currentTimeMillis());
|
||||
rep.getConfig().putSingle("keystore", "/nosuchfile");
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
assertErrror(response, "Failed to load keys");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidKeystorePassword() throws Exception {
|
||||
ComponentRepresentation rep = createRep("valid", System.currentTimeMillis());
|
||||
rep.getConfig().putSingle("keystore", "invalid");
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
assertErrror(response, "Failed to load keys");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidKeyAlias() throws Exception {
|
||||
ComponentRepresentation rep = createRep("valid", System.currentTimeMillis());
|
||||
rep.getConfig().putSingle("keyAlias", "invalid");
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
assertErrror(response, "Failed to load keys");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidKeyPassword() throws Exception {
|
||||
ComponentRepresentation rep = createRep("valid", System.currentTimeMillis());
|
||||
rep.getConfig().putSingle("keyPassword", "invalid");
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
assertErrror(response, "Failed to load keys");
|
||||
}
|
||||
|
||||
protected void assertErrror(Response response, String error) {
|
||||
if (!response.hasEntity()) {
|
||||
fail("No error message set");
|
||||
}
|
||||
|
||||
ErrorRepresentation errorRepresentation = response.readEntity(ErrorRepresentation.class);
|
||||
assertEquals(error, errorRepresentation.getErrorMessage());
|
||||
}
|
||||
|
||||
protected ComponentRepresentation createRep(String name, long priority) {
|
||||
ComponentRepresentation rep = new ComponentRepresentation();
|
||||
rep.setName(name);
|
||||
rep.setParentId("test");
|
||||
rep.setProviderId(JavaKeystoreKeyProviderFactory.ID);
|
||||
rep.setProviderType(KeyProvider.class.getName());
|
||||
rep.setConfig(new MultivaluedHashMap<>());
|
||||
rep.getConfig().putSingle("priority", Long.toString(priority));
|
||||
rep.getConfig().putSingle("keystore", file.getAbsolutePath());
|
||||
rep.getConfig().putSingle("keystorePassword", "password");
|
||||
rep.getConfig().putSingle("keyAlias", "selfsigned");
|
||||
rep.getConfig().putSingle("keyPassword", "password");
|
||||
return rep;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package org.keycloak.testsuite.keys;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
@ -28,6 +30,8 @@ import org.keycloak.common.util.PemUtils;
|
|||
import org.keycloak.keys.Attributes;
|
||||
import org.keycloak.keys.KeyProvider;
|
||||
import org.keycloak.keys.RsaKeyProviderFactory;
|
||||
import org.keycloak.representations.UserInfo;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.ComponentRepresentation;
|
||||
import org.keycloak.representations.idm.KeysMetadataRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
@ -37,9 +41,13 @@ import org.keycloak.testsuite.AssertEvents;
|
|||
import org.keycloak.testsuite.pages.AppPage;
|
||||
import org.keycloak.testsuite.pages.AppPage.RequestType;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.util.KeycloakModelUtils;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
import org.keycloak.testsuite.util.UserInfoClientUtil;
|
||||
|
||||
import javax.ws.rs.client.ClientBuilder;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PublicKey;
|
||||
import java.util.List;
|
||||
|
@ -65,6 +73,10 @@ public class KeyRotationTest extends AbstractKeycloakTest {
|
|||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation realm = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
|
||||
testRealms.add(realm);
|
||||
|
||||
ClientRepresentation confApp = KeycloakModelUtils.createClient(realm, "confidential-cli");
|
||||
confApp.setSecret("secret1");
|
||||
confApp.setServiceAccountsEnabled(Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -114,6 +126,12 @@ public class KeyRotationTest extends AbstractKeycloakTest {
|
|||
assertTokenSignature(key1, response.getAccessToken());
|
||||
assertTokenSignature(key1, response.getRefreshToken());
|
||||
|
||||
// Userinfo with keys #1
|
||||
assertUserInfo(response.getAccessToken(), 200);
|
||||
|
||||
// Token introspection with keys #1
|
||||
assertTokenIntrospection(response.getAccessToken(), true);
|
||||
|
||||
// Create keys #2
|
||||
PublicKey key2 = createKeys2();
|
||||
|
||||
|
@ -123,6 +141,12 @@ public class KeyRotationTest extends AbstractKeycloakTest {
|
|||
assertTokenSignature(key2, response.getAccessToken());
|
||||
assertTokenSignature(key2, response.getRefreshToken());
|
||||
|
||||
// Userinfo with keys #2
|
||||
assertUserInfo(response.getAccessToken(), 200);
|
||||
|
||||
// Token introspection with keys #2
|
||||
assertTokenIntrospection(response.getAccessToken(), true);
|
||||
|
||||
// Drop key #1
|
||||
dropKeys1();
|
||||
|
||||
|
@ -131,9 +155,21 @@ public class KeyRotationTest extends AbstractKeycloakTest {
|
|||
assertTokenSignature(key2, response.getAccessToken());
|
||||
assertTokenSignature(key2, response.getRefreshToken());
|
||||
|
||||
// Userinfo with keys #1 dropped
|
||||
assertUserInfo(response.getAccessToken(), 200);
|
||||
|
||||
// Token introspection with keys #1 dropped
|
||||
assertTokenIntrospection(response.getAccessToken(), true);
|
||||
|
||||
// Drop key #2
|
||||
dropKeys2();
|
||||
|
||||
// Userinfo with keys #2 dropped
|
||||
assertUserInfo(response.getAccessToken(), 401);
|
||||
|
||||
// Token introspection with keys #2 dropped
|
||||
assertTokenIntrospection(response.getAccessToken(), false);
|
||||
|
||||
// Refresh token with keys #2 dropped - should fail as refresh token is signed with key #2
|
||||
response = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
|
||||
assertEquals(400, response.getStatusCode());
|
||||
|
@ -232,5 +268,23 @@ public class KeyRotationTest extends AbstractKeycloakTest {
|
|||
throw new RuntimeException("Failed to find keys1");
|
||||
}
|
||||
|
||||
private void assertUserInfo(String token, int expectedStatus) {
|
||||
Response userInfoResponse = UserInfoClientUtil.executeUserInfoRequest_getMethod(ClientBuilder.newClient(), token);
|
||||
assertEquals(expectedStatus, userInfoResponse.getStatus());
|
||||
userInfoResponse.close();
|
||||
}
|
||||
|
||||
private void assertTokenIntrospection(String token, boolean expectActive) {
|
||||
try {
|
||||
String tokenResponse = oauth.introspectAccessTokenWithClientCredential("confidential-cli", "secret1", token);
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode jsonNode = objectMapper.readTree(tokenResponse);
|
||||
assertEquals(expectActive, jsonNode.get("active").asBoolean());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed 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 License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.keys;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.keys.GeneratedRsaKeyProviderFactory;
|
||||
import org.keycloak.keys.KeyMetadata;
|
||||
import org.keycloak.keys.KeyProvider;
|
||||
import org.keycloak.representations.idm.ComponentRepresentation;
|
||||
import org.keycloak.representations.idm.ErrorRepresentation;
|
||||
import org.keycloak.representations.idm.KeysMetadataRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.pages.AppPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class RsaGeneratedKeyProviderTest extends AbstractKeycloakTest {
|
||||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(this);
|
||||
|
||||
@Page
|
||||
protected AppPage appPage;
|
||||
|
||||
@Page
|
||||
protected LoginPage loginPage;
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation realm = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
|
||||
testRealms.add(realm);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultKeysize() throws Exception {
|
||||
long priority = System.currentTimeMillis();
|
||||
|
||||
ComponentRepresentation rep = createRep("valid", GeneratedRsaKeyProviderFactory.ID);
|
||||
rep.setConfig(new MultivaluedHashMap<>());
|
||||
rep.getConfig().putSingle("priority", Long.toString(priority));
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
String id = ApiUtil.getCreatedId(response);
|
||||
|
||||
ComponentRepresentation createdRep = adminClient.realm("test").components().component(id).toRepresentation();
|
||||
assertEquals(2, createdRep.getConfig().size());
|
||||
assertEquals(Long.toString(priority), createdRep.getConfig().getFirst("priority"));
|
||||
assertEquals("2048", createdRep.getConfig().getFirst("keySize"));
|
||||
|
||||
KeysMetadataRepresentation keys = adminClient.realm("test").keys().getKeyMetadata();
|
||||
|
||||
KeysMetadataRepresentation.KeyMetadataRepresentation key = keys.getKeys().get(0);
|
||||
|
||||
assertEquals(id, key.getProviderId());
|
||||
assertEquals(KeyMetadata.Type.RSA.name(), key.getType());
|
||||
assertEquals(priority, key.getProviderPriority());
|
||||
assertEquals(2048, ((RSAPublicKey) PemUtils.decodePublicKey(keys.getKeys().get(0).getPublicKey())).getModulus().bitLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void largeKeysize() throws Exception {
|
||||
long priority = System.currentTimeMillis();
|
||||
|
||||
ComponentRepresentation rep = createRep("valid", GeneratedRsaKeyProviderFactory.ID);
|
||||
rep.setConfig(new MultivaluedHashMap<>());
|
||||
rep.getConfig().putSingle("priority", Long.toString(priority));
|
||||
rep.getConfig().putSingle("keySize", "4096");
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
String id = ApiUtil.getCreatedId(response);
|
||||
|
||||
ComponentRepresentation createdRep = adminClient.realm("test").components().component(id).toRepresentation();
|
||||
assertEquals(2, createdRep.getConfig().size());
|
||||
assertEquals("4096", createdRep.getConfig().getFirst("keySize"));
|
||||
|
||||
KeysMetadataRepresentation keys = adminClient.realm("test").keys().getKeyMetadata();
|
||||
|
||||
KeysMetadataRepresentation.KeyMetadataRepresentation key = keys.getKeys().get(0);
|
||||
|
||||
assertEquals(id, key.getProviderId());
|
||||
assertEquals(KeyMetadata.Type.RSA.name(), key.getType());
|
||||
assertEquals(priority, key.getProviderPriority());
|
||||
assertEquals(4096, ((RSAPublicKey) PemUtils.decodePublicKey(keys.getKeys().get(0).getPublicKey())).getModulus().bitLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePriority() throws Exception {
|
||||
long priority = System.currentTimeMillis();
|
||||
|
||||
ComponentRepresentation rep = createRep("valid", GeneratedRsaKeyProviderFactory.ID);
|
||||
rep.setConfig(new MultivaluedHashMap<>());
|
||||
rep.getConfig().putSingle("priority", Long.toString(priority));
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
String id = ApiUtil.getCreatedId(response);
|
||||
|
||||
KeysMetadataRepresentation keys = adminClient.realm("test").keys().getKeyMetadata();
|
||||
|
||||
String publicKey = keys.getKeys().get(0).getPublicKey();
|
||||
|
||||
ComponentRepresentation createdRep = adminClient.realm("test").components().component(id).toRepresentation();
|
||||
|
||||
priority += 1000;
|
||||
|
||||
createdRep.getConfig().putSingle("priority", Long.toString(priority));
|
||||
adminClient.realm("test").components().component(id).update(createdRep);
|
||||
|
||||
keys = adminClient.realm("test").keys().getKeyMetadata();
|
||||
|
||||
String publicKey2 = keys.getKeys().get(0).getPublicKey();
|
||||
|
||||
assertEquals(publicKey, publicKey2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateKeysize() throws Exception {
|
||||
long priority = System.currentTimeMillis();
|
||||
|
||||
ComponentRepresentation rep = createRep("valid", GeneratedRsaKeyProviderFactory.ID);
|
||||
rep.setConfig(new MultivaluedHashMap<>());
|
||||
rep.getConfig().putSingle("priority", Long.toString(priority));
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
String id = ApiUtil.getCreatedId(response);
|
||||
|
||||
KeysMetadataRepresentation keys = adminClient.realm("test").keys().getKeyMetadata();
|
||||
|
||||
String publicKey = keys.getKeys().get(0).getPublicKey();
|
||||
|
||||
ComponentRepresentation createdRep = adminClient.realm("test").components().component(id).toRepresentation();
|
||||
createdRep.getConfig().putSingle("keySize", "4096");
|
||||
adminClient.realm("test").components().component(id).update(createdRep);
|
||||
|
||||
keys = adminClient.realm("test").keys().getKeyMetadata();
|
||||
|
||||
String publicKey2 = keys.getKeys().get(0).getPublicKey();
|
||||
|
||||
assertNotEquals(publicKey, publicKey2);
|
||||
assertEquals(2048, ((RSAPublicKey) PemUtils.decodePublicKey(publicKey)).getModulus().bitLength());
|
||||
assertEquals(4096, ((RSAPublicKey) PemUtils.decodePublicKey(publicKey2)).getModulus().bitLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidKeysize() throws Exception {
|
||||
ComponentRepresentation rep = createRep("invalid", GeneratedRsaKeyProviderFactory.ID);
|
||||
rep.getConfig().putSingle("keySize", "1234");
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
assertErrror(response, "Keysize should be 1024, 2048 or 4096");
|
||||
}
|
||||
|
||||
protected void assertErrror(Response response, String error) {
|
||||
if (!response.hasEntity()) {
|
||||
fail("No error message set");
|
||||
}
|
||||
|
||||
ErrorRepresentation errorRepresentation = response.readEntity(ErrorRepresentation.class);
|
||||
assertEquals(error, errorRepresentation.getErrorMessage());
|
||||
}
|
||||
|
||||
protected ComponentRepresentation createRep(String name, String providerId) {
|
||||
ComponentRepresentation rep = new ComponentRepresentation();
|
||||
rep.setName(name);
|
||||
rep.setParentId("test");
|
||||
rep.setProviderId(providerId);
|
||||
rep.setProviderType(KeyProvider.class.getName());
|
||||
rep.setConfig(new MultivaluedHashMap<>());
|
||||
return rep;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ import org.keycloak.common.util.KeyUtils;
|
|||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.keys.Attributes;
|
||||
import org.keycloak.keys.GeneratedRsaKeyProviderFactory;
|
||||
import org.keycloak.keys.KeyMetadata;
|
||||
import org.keycloak.keys.KeyProvider;
|
||||
import org.keycloak.keys.RsaKeyProvider;
|
||||
|
@ -76,12 +77,14 @@ public class RsaKeyProviderTest extends AbstractKeycloakTest {
|
|||
|
||||
@Test
|
||||
public void privateKeyOnly() throws Exception {
|
||||
long priority = System.currentTimeMillis();
|
||||
|
||||
KeyPair keyPair = KeyUtils.generateRsaKeyPair(2048);
|
||||
String kid = KeyUtils.createKeyId(keyPair.getPublic());
|
||||
|
||||
ComponentRepresentation rep = createRep("valid", RsaKeyProviderFactory.ID);
|
||||
rep.getConfig().putSingle(Attributes.PRIVATE_KEY_KEY, PemUtils.encodeKey(keyPair.getPrivate()));
|
||||
rep.getConfig().putSingle(Attributes.PRIORITY_KEY, "1000");
|
||||
rep.getConfig().putSingle(Attributes.PRIORITY_KEY, Long.toString(priority));
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
String id = ApiUtil.getCreatedId(response);
|
||||
|
@ -100,7 +103,7 @@ public class RsaKeyProviderTest extends AbstractKeycloakTest {
|
|||
|
||||
assertEquals(id, key.getProviderId());
|
||||
assertEquals(KeyMetadata.Type.RSA.name(), key.getType());
|
||||
assertEquals(1000l, key.getProviderPriority());
|
||||
assertEquals(priority, key.getProviderPriority());
|
||||
assertEquals(kid, key.getKid());
|
||||
assertEquals(PemUtils.encodeKey(keyPair.getPublic()), keys.getKeys().get(0).getPublicKey());
|
||||
assertEquals(keyPair.getPublic(), PemUtils.decodeCertificate(key.getCertificate()).getPublicKey());
|
||||
|
@ -108,6 +111,8 @@ public class RsaKeyProviderTest extends AbstractKeycloakTest {
|
|||
|
||||
@Test
|
||||
public void keyAndCertificate() throws Exception {
|
||||
long priority = System.currentTimeMillis();
|
||||
|
||||
KeyPair keyPair = KeyUtils.generateRsaKeyPair(2048);
|
||||
Certificate certificate = CertificateUtils.generateV1SelfSignedCertificate(keyPair, "test");
|
||||
String certificatePem = PemUtils.encodeCertificate(certificate);
|
||||
|
@ -115,7 +120,7 @@ public class RsaKeyProviderTest extends AbstractKeycloakTest {
|
|||
ComponentRepresentation rep = createRep("valid", RsaKeyProviderFactory.ID);
|
||||
rep.getConfig().putSingle(Attributes.PRIVATE_KEY_KEY, PemUtils.encodeKey(keyPair.getPrivate()));
|
||||
rep.getConfig().putSingle(Attributes.CERTIFICATE_KEY, certificatePem);
|
||||
rep.getConfig().putSingle(Attributes.PRIORITY_KEY, "1000");
|
||||
rep.getConfig().putSingle(Attributes.PRIORITY_KEY, Long.toString(priority));
|
||||
|
||||
Response response = adminClient.realm("test").components().add(rep);
|
||||
String id = ApiUtil.getCreatedId(response);
|
||||
|
|
Binary file not shown.
Loading…
Reference in a new issue