From 78fe064cf0a942488961f6d7b2c17f3237c2bb2c Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Thu, 7 Jan 2016 17:25:47 -0500 Subject: [PATCH] 2213 --- .../admin/resources/js/controllers/clients.js | 29 +--- .../resources/templates/kc-tabs-client.html | 2 +- model/sessions-infinispan/pom.xml | 12 ++ .../config/parsers/DeploymentBuilder.java | 26 ++- .../EntityDescriptorDescriptionConverter.java | 2 +- .../keycloak/protocol/saml/SamlClient.java | 17 ++ .../protocol/saml/SamlConfigAttributes.java | 2 + .../keycloak/protocol/saml/SamlProtocol.java | 1 - .../protocol/saml/SamlProtocolUtils.java | 2 +- .../KeycloakSamlClientInstallation.java | 161 ++++++++++++++++++ ...ycloak.protocol.ClientInstallationProvider | 1 + .../services/resources/RealmsResource.java | 4 + 12 files changed, 221 insertions(+), 38 deletions(-) create mode 100755 saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlClientInstallation.java create mode 100755 saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ClientInstallationProvider diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js index f80e57a3dd..9729c9cd90 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js @@ -709,33 +709,6 @@ module.controller('ClientInstallationCtrl', function($scope, realm, client, serv $scope.installation = installation; }) }; - - - /* - $scope.changeFormat = function() { - if ($scope.configFormat == "Keycloak JSON") { - $scope.filename = 'keycloak.json'; - - var url = ClientInstallation.url({ realm: $routeParams.realm, client: $routeParams.client }); - $http.get(url).success(function(data) { - var tmp = angular.fromJson(data); - $scope.installation = angular.toJson(tmp, true); - $scope.type = 'application/json'; - }) - } else if ($scope.configFormat == "Wildfly/EAP Subsystem XML") { - $scope.filename = 'keycloak.xml'; - - var url = ClientInstallationJBoss.url({ realm: $routeParams.realm, client: $routeParams.client }); - $http.get(url).success(function(data) { - $scope.installation = data; - $scope.type = 'text/xml'; - }) - } - - console.debug($scope.filename); - }; - */ - $scope.download = function() { saveAs(new Blob([$scope.installation], { type: $scope.configFormat.mediaType }), $scope.configFormat.filename); } @@ -1080,7 +1053,7 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, templates, module.controller('CreateClientCtrl', function($scope, realm, client, templates, $route, serverInfo, Client, ClientDescriptionConverter, $location, $modal, Dialog, Notifications) { $scope.protocols = ['openid-connect', 'saml'];//Object.keys(serverInfo.providers['login-protocol'].providers).sort(); - + $scope.create = true; $scope.templates = [ {name:'NONE'}]; for (var i = 0; i < templates.length; i++) { var template = templates[i]; diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html index 6f564673b2..58388ff64b 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html @@ -33,7 +33,7 @@
  • {{:: 'clustering' | translate}}
  • -
  • +
  • {{:: 'installation' | translate}} {{:: 'installation.tooltip' | translate}}
  • diff --git a/model/sessions-infinispan/pom.xml b/model/sessions-infinispan/pom.xml index c4f57b0333..553895cf81 100755 --- a/model/sessions-infinispan/pom.xml +++ b/model/sessions-infinispan/pom.xml @@ -36,4 +36,16 @@ test + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java index 5de2072350..e0564e926f 100755 --- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java +++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java @@ -98,12 +98,26 @@ public class DeploymentBuilder { } if (key.isEncryption()) { - KeyStore keyStore = loadKeystore(resourceLoader, key); - try { - PrivateKey privateKey = (PrivateKey) keyStore.getKey(key.getKeystore().getPrivateKeyAlias(), key.getKeystore().getPrivateKeyPassword().toCharArray()); - deployment.setDecryptionKey(privateKey); - } catch (Exception e) { - throw new RuntimeException(e); + if (key.getKeystore() != null) { + + KeyStore keyStore = loadKeystore(resourceLoader, key); + try { + PrivateKey privateKey = (PrivateKey) keyStore.getKey(key.getKeystore().getPrivateKeyAlias(), key.getKeystore().getPrivateKeyPassword().toCharArray()); + deployment.setDecryptionKey(privateKey); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + if (key.getPrivateKeyPem() == null) { + throw new RuntimeException("SP signing key must have a PrivateKey defined"); + } + try { + PrivateKey privateKey = PemUtils.decodePrivateKey(key.getPrivateKeyPem().trim()); + deployment.setDecryptionKey(privateKey); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorDescriptionConverter.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorDescriptionConverter.java index 20f78109f4..61ecbdcdc3 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorDescriptionConverter.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorDescriptionConverter.java @@ -116,7 +116,7 @@ public class EntityDescriptorDescriptionConverter implements ClientDescriptionCo attributes.put(SamlConfigAttributes.SAML_SIGNING_CERTIFICATE_ATTRIBUTE, certPem); } else if (keyDescriptor.getUse() == KeyTypes.ENCRYPTION) { attributes.put(SamlConfigAttributes.SAML_ENCRYPT, SamlProtocol.ATTRIBUTE_TRUE_VALUE); - attributes.put(SamlProtocol.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE, certPem); + attributes.put(SamlConfigAttributes.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE, certPem); } } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClient.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClient.java index d935f83e2a..3ac9892d2e 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClient.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClient.java @@ -121,4 +121,21 @@ public class SamlClient extends ClientConfigResolver { } + public String getClientEncryptingCertificate() { + return client.getAttribute(SamlConfigAttributes.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE); + } + + public void setClientEncryptingCertificate(String val) { + client.setAttribute(SamlConfigAttributes.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE, val); + + } + public String getClientEncryptingPrivateKey() { + return client.getAttribute(SamlConfigAttributes.SAML_ENCRYPTION_PRIVATE_KEY_ATTRIBUTE); + } + + public void setClientEncryptingPrivateKey(String val) { + client.setAttribute(SamlConfigAttributes.SAML_ENCRYPTION_PRIVATE_KEY_ATTRIBUTE, val); + + } + } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlConfigAttributes.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlConfigAttributes.java index eea258ac0b..c6bc60a607 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlConfigAttributes.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlConfigAttributes.java @@ -19,4 +19,6 @@ public interface SamlConfigAttributes { String SAML_ENCRYPT = "saml.encrypt"; String SAML_CLIENT_SIGNATURE_ATTRIBUTE = "saml.client.signature"; String SAML_SIGNING_CERTIFICATE_ATTRIBUTE = "saml.signing." + ClientAttributeCertificateResource.X509CERTIFICATE; + String SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE = "saml.encryption." + ClientAttributeCertificateResource.X509CERTIFICATE; + String SAML_ENCRYPTION_PRIVATE_KEY_ATTRIBUTE = "saml.encryption." + ClientAttributeCertificateResource.PRIVATE_KEY; } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java index e7bd3ebd4d..c76c853d74 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java @@ -70,7 +70,6 @@ public class SamlProtocol implements LoginProtocol { public static final String ATTRIBUTE_TRUE_VALUE = "true"; public static final String ATTRIBUTE_FALSE_VALUE = "false"; - public static final String SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE = "saml.encryption." + ClientAttributeCertificateResource.X509CERTIFICATE; public static final String SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE = "saml_assertion_consumer_url_post"; public static final String SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE = "saml_assertion_consumer_url_redirect"; public static final String SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE = "saml_single_logout_service_url_post"; diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java index 5742f7d1a3..3e03ed4201 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java @@ -49,7 +49,7 @@ public class SamlProtocolUtils { } public static PublicKey getEncryptionValidationKey(ClientModel client) throws VerificationException { - return getPublicKey(client, SamlProtocol.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE); + return getPublicKey(client, SamlConfigAttributes.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE); } public static PublicKey getPublicKey(ClientModel client, String attribute) throws VerificationException { diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlClientInstallation.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlClientInstallation.java new file mode 100755 index 0000000000..d3abddf054 --- /dev/null +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlClientInstallation.java @@ -0,0 +1,161 @@ +package org.keycloak.protocol.saml.installation; + +import org.keycloak.Config; +import org.keycloak.models.ClientModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.models.RealmModel; +import org.keycloak.protocol.ClientInstallationProvider; +import org.keycloak.protocol.saml.SamlClient; +import org.keycloak.protocol.saml.SamlProtocol; +import org.keycloak.services.resources.RealmsResource; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import java.net.URI; +import java.util.Map; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class KeycloakSamlClientInstallation implements ClientInstallationProvider { + + @Override + public Response generateInstallation(KeycloakSession session, RealmModel realm, ClientModel client, URI baseUri) { + SamlClient samlClient = new SamlClient(client); + StringBuffer buffer = new StringBuffer(); + buffer.append("\n"); + buffer.append(" \n"); + if (samlClient.requiresClientSignature() || samlClient.requiresEncryption()) { + buffer.append(" \n"); + if (samlClient.requiresClientSignature()) { + buffer.append(" \n"); + buffer.append(" \n"); + if (samlClient.getClientSigningPrivateKey() == null) { + buffer.append(" PRIVATE KEY NOT SET UP OR KNOWN\n"); + } else { + buffer.append(" ").append(samlClient.getClientSigningPrivateKey()).append("\n"); + } + buffer.append(" \n"); + buffer.append(" \n"); + if (samlClient.getClientSigningCertificate() == null) { + buffer.append(" YOU MUST CONFIGURE YOUR CLIENT's SIGNING CERTIFICATE\n"); + } else { + buffer.append(" ").append(samlClient.getClientSigningCertificate()).append("\n"); + } + buffer.append(" \n"); + buffer.append(" \n"); + } + if (samlClient.requiresEncryption()) { + buffer.append(" \n"); + buffer.append(" \n"); + if (samlClient.getClientEncryptingPrivateKey() == null) { + buffer.append(" PRIVATE KEY NOT SET UP OR KNOWN\n"); + } else { + buffer.append(" ").append(samlClient.getClientEncryptingPrivateKey()).append("\n"); + } + buffer.append(" \n"); + buffer.append(" \n"); + + } + buffer.append(" \n"); + } + buffer.append(" \n"); + buffer.append(" \n"); + + buffer.append(" \n"); + if (samlClient.requiresRealmSignature()) { + buffer.append(" \n"); + buffer.append(" \n"); + buffer.append(" \n"); + buffer.append(" ").append(realm.getCertificatePem()).append("\n"); + buffer.append(" \n"); + buffer.append(" \n"); + buffer.append(" \n"); + } + buffer.append(" \n"); + buffer.append(" \n"); + buffer.append("\n"); + return Response.ok(buffer.toString(), MediaType.TEXT_PLAIN_TYPE).build(); + } + + @Override + public String getProtocol() { + return SamlProtocol.LOGIN_PROTOCOL; + } + + @Override + public String getDisplayType() { + return "Keycloak SAML Adapter keycloak-saml.xml"; + } + + @Override + public String getHelpText() { + return "Keycloak SAML adapter configuration file. Put this in WEB-INF directory if your WAR."; + } + + @Override + public String getFilename() { + return "keycloak-saml.xml"; + } + + @Override + public String getMediaType() { + return MediaType.APPLICATION_XML; + } + + @Override + public boolean isDownloadOnly() { + return false; + } + + @Override + public void close() { + + } + + @Override + public ClientInstallationProvider create(KeycloakSession session) { + return this; + } + + @Override + public void init(Config.Scope config) { + + } + + @Override + public void postInit(KeycloakSessionFactory factory) { + + } + + @Override + public String getId() { + return "keycloak-saml"; + } +} diff --git a/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ClientInstallationProvider b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ClientInstallationProvider new file mode 100755 index 0000000000..f8e9df55e2 --- /dev/null +++ b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ClientInstallationProvider @@ -0,0 +1 @@ +org.keycloak.protocol.saml.installation.KeycloakSamlClientInstallation diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java index a1a3accb9d..e0ea2003e7 100755 --- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java @@ -57,6 +57,10 @@ public class RealmsResource { return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getProtocol"); } + public static UriBuilder protocolUrl(UriBuilder builder) { + return builder.path(RealmsResource.class).path(RealmsResource.class, "getProtocol"); + } + public static UriBuilder clientRegistrationUrl(UriInfo uriInfo) { return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getClientsService"); }