Skip to content

Commit

Permalink
feature(jans-keycloak-integration): sync trust relationship configura…
Browse files Browse the repository at this point in the history
…tion between config-api and keycloak #8008 (#8229)

* feat(keycloak-integration):  job scheduler #8008
* added saml metadata parsing library

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(keycloak-integration): sync sp configuration between config-api and kc #8008
* fixed typo in saml metadata parser

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(jans-keycloak-integration): sync trust relationship configuration between config-api and keycloak #8008
* added enum for SAML Bindings support
* added helper methods to access some metadata objects

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(keycloak-integration): sync trust relationship config between config-api and kc #8008
* fix bugs in parser(temporary)

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(jans-keycloak-integration): sync tr config between config-api and kc #8000
* added authentication browser flow configuration

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(jans-keycloak-integration): sync tr config between config-api and kc #8008
* refactor trustrelationship sync job (delete non-existing trust relationships)
* added code to sync new trust relationships

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(jans-keycloak-integration): sync tr config between config-api and kc #8008
* modifed saxutils to optimize re-use of sax parsing objects

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(jans-keycloak-integration): sync tr config between config-api and kc #8008
* added call to saxutils init to scheduler startup
* additional changes to kc and config api

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(jans-keycloak-integration): sync tr config between config-api and kc #8008
* modifications to the logging configuration template
* modifications to the application configuration template

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(jans-keycloak-integration): sync tr config between config-api and kc #8008
*added method to fetch released user attributes for a tr

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(jans-keycloak-integration): sync tr config between config api and kc #8008
* added protocol mapper api methods (will be used to update released attributes)

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(jans-keycloak-integration: sync tr between config-api and kc #8008
* added saml user attribute mapper configuration

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(jans-keycloak-integration): sync tr config between config-api and kc #8008
* made fixes to the createManagedSamlClient keycloak API wrapper method
* completed implementation of released attributes sync

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

* feat(keycloak-integration): sync tr config between config-api and kc #8008
* added error support to the jans config api
* fixed a bug related to saml encryption certificate configuration in keycloak

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>

---------

Signed-off-by: Rolain Djeumen <uprightech@gmail.com>
Co-authored-by: Mohammad Abudayyeh <47318409+moabu@users.noreply.github.com>
Co-authored-by: YuriyZ <yzabrovarniy@gmail.com>
  • Loading branch information
3 people committed Apr 4, 2024
1 parent 5d35fd0 commit 3bf5f6d
Show file tree
Hide file tree
Showing 30 changed files with 1,437 additions and 124 deletions.
2 changes: 2 additions & 0 deletions jans-core/saml/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
<include>**/*.xsd</include>
<include>**/*.dtd</include>
<include>**/services/*</include>
<include>**/*.properties</include>
</includes>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.jans.saml.metadata.builder;

import io.jans.saml.metadata.model.SAMLBinding;
import io.jans.saml.metadata.model.Endpoint;

public class EndpointBuilder {
Expand All @@ -11,7 +12,7 @@ public EndpointBuilder(final Endpoint endpoint) {
this.endpoint = endpoint;
}

public EndpointBuilder binding(final String binding) {
public EndpointBuilder binding(final SAMLBinding binding) {

this.endpoint.setBinding(binding);
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public SPSSODescriptorBuilder wantAssertionsSigned(final Boolean wantAssertionsS
return this;
}

public IndexedEndpointBuilder assersionConsumerService() {
public IndexedEndpointBuilder assertionConsumerService() {

IndexedEndpoint endpoint = new IndexedEndpoint();
spssoDescriptor().addAssertionConsumerService(endpoint);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public class Endpoint {

private String binding;
private SAMLBinding binding;
private String location;
private String responseLocation;

Expand All @@ -13,12 +13,12 @@ public Endpoint() {
this.responseLocation = null;
}

public String getBinding() {
public SAMLBinding getBinding() {

return this.binding;
}

public void setBinding(final String binding) {
public void setBinding(final SAMLBinding binding) {

this.binding = binding;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ public List<SPSSODescriptor> getSpssoDescriptors() {
return this.spssoDescriptors;
}

public SPSSODescriptor getFirstSpssoDescriptor() {

if(!this.spssoDescriptors.isEmpty()) {
return this.spssoDescriptors.get(0);
}
return null;
}

public void addSpssoDescriptor(final SPSSODescriptor descriptor) {

this.spssoDescriptors.add(descriptor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ public String getUse() {
return this.use;
}

public boolean isEncryptionKey() {

return "encryption".equalsIgnoreCase(use);
}

public boolean isSigningKey() {

return "signing".equalsIgnoreCase(use);
}

public void setUse(final String use) {

this.use = use;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,22 @@ public List<KeyDescriptor> getKeyDescriptors() {
return this.keyDescriptors;
}

public List<KeyDescriptor> getEncryptionKeys() {

return keyDescriptors
.stream()
.filter((k) -> { return k.isEncryptionKey();})
.toList();
}

public List<KeyDescriptor> getSigningKeys() {

return keyDescriptors
.stream()
.filter((k)-> { return k.isSigningKey();})
.toList();
}

public void addKeyDescriptor(final KeyDescriptor keyDescriptor) {

this.keyDescriptors.add(keyDescriptor);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.jans.saml.metadata.model;

public enum SAMLBinding {
SOAP("urn:oasis:names:tc:SAML:2.0:bindings:SOAP"),
REVERSE_SOAP("urn:oasis:names:tc:SAML:2.0:bindings:PAOS"),
HTTP_REDIRECT("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"),
HTTP_POST("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"),
HTTP_ARTIFACT("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"),
URI("urn:oasis:names:tc:SAML:2.0:bindings:URI"),
UNKNOWN("");

private final String value;

private SAMLBinding(final String value) {
this.value = value;
}

public String value() {

return this.value;
}

public static SAMLBinding fromString(final String value) {

for(SAMLBinding binding: SAMLBinding.values()) {
if(binding.value.equals(value)) {
return binding;
}
}
return UNKNOWN;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.jans.saml.metadata.model;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class SAMLMetadata {

Expand All @@ -15,4 +17,21 @@ public final List<EntityDescriptor> getEntityDescriptors() {

return this.entityDescriptors;
}


public final EntityDescriptor getEntityDescriptorByEntityId(final String entityId) {

Optional<EntityDescriptor> ret = entityDescriptors.stream()
.filter((e) -> {return e.getEntityId().equals(entityId);})
.findFirst();

return (ret.isEmpty()? null : ret.get());
}

public final List<String> getEntityDescriptorIds() {

return entityDescriptors.stream()
.map((e) -> {return e.getEntityId();})
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@ public List<IndexedEndpoint> getAssertionConsumerServices() {
return this.assertionConsumerServices;
}

public List<IndexedEndpoint> getAssertionConsumerServices(SAMLBinding binding) {

return assertionConsumerServices.stream()
.filter((e) -> { return e.getBinding() == binding; })
.toList();
}

public List<String> getAssertionConsumerServicesLocations(SAMLBinding binding) {

return assertionConsumerServices.stream()
.filter((e) -> { return e.getBinding() == binding;})
.map((e) -> { return e.getLocation();})
.toList();
}

public void addAssertionConsumerService(final IndexedEndpoint service) {

this.assertionConsumerServices.add(service);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ public List<String> getX509Certificates() {
return this.x509certificates;
}

public String getFirstX509Certificate() {

if(!x509certificates.isEmpty()) {
return x509certificates.get(0);
}
return null;
}

public void addX509Certificate(final String x509certificate) {

this.x509certificates.add(x509certificate);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public SAMLMetadata parse(File metadatafile) {
validator.validate(new StreamSource(metadatafile));

final DocumentBuilderFactory docbuilderfactory = DocumentBuilderFactory.newInstance();
docbuilderfactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
docbuilderfactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",false);
docbuilderfactory.setSchema(schema);
docbuilderfactory.setNamespaceAware(true);
final DocumentBuilder docbuilder = docbuilderfactory.newDocumentBuilder();
Expand Down Expand Up @@ -126,7 +126,7 @@ private final void parseSPSSODescriptor(final XPath xpath,

NodeList assertionconsumerservicelist = XPathUtils.assertionConsumerServiceListFromParentNode(xpath, node);
for(int i=0; i < assertionconsumerservicelist.getLength(); i++) {
parseIndexedEndpoint(xpath,assertionconsumerservicelist.item(i),builder.assersionConsumerService());
parseIndexedEndpoint(xpath,assertionconsumerservicelist.item(i),builder.assertionConsumerService());
}
}

Expand Down Expand Up @@ -242,8 +242,8 @@ private final void parseX509Data(final XPath xpath, final Node node,final X509Da
}

private final void parseEndpoint(final XPath xpath, final Node node, final EndpointBuilder builder) throws XPathExpressionException {

builder.binding(XPathUtils.bindingAttributeValue(xpath, node))
builder.binding(SAMLBinding.fromString(XPathUtils.bindingAttributeValue(xpath, node)))
.location(XPathUtils.locationAttributeValue(xpath, node))
.responseLocation(XPathUtils.responseLocationAttributeValue(xpath, node));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ public class LSResourceResolverImpl implements LSResourceResolver {

static {
namespacemap = new HashMap<>();
namespacemap.put("http://www.w3.org/XML/1998/namespace","/schema/www.w3.org/xml.xsd");
namespacemap.put("urn:oasis:names:tc:SAML:2.0:assertion","/schema/saml/saml-schema-assertion-2.0.xsd");
namespacemap.put("http://www.w3.org/2000/09/xmldsig#","/schema/www.w3.org/xmldsig-core-schema.xsd");
namespacemap.put("http://www.w3.org/2001/04/xmlenc#","/schema/www.w3.org/xenc-schema.xsd");
namespacemap.put("http://www.w3.org/XML/1998/namespace","/META-INF/xml.schemas/xml.xsd");
namespacemap.put("urn:oasis:names:tc:SAML:2.0:assertion","/META-INF/saml.schemas/saml-schema-assertion-2.0.xsd");
namespacemap.put("http://www.w3.org/2000/09/xmldsig#","/META-INF/xml.schemas/xmldsig-core-schema.xsd");
namespacemap.put("http://www.w3.org/2001/04/xmlenc#","/META-INF/xml.schemas/xenc-schema.xsd");

publicidmap = new HashMap<>();
publicidmap.put("-//W3C//DTD XMLSchema 200102//EN","/schema/www.w3.org/XMLSchema.dtd");
publicidmap.put("datatypes","/schema/www.w3.org/datatypes.dtd");
publicidmap.put("-//W3C//DTD XMLSchema 200102//EN","/META-INF/xml.schemas/XMLSchema.dtd");
publicidmap.put("datatypes","/META-INF/xml.schemas/datatypes.dtd");
}

@Override
Expand All @@ -33,7 +33,7 @@ public LSInput resolveResource(String type, String nameSpaceURI, String publicId
if(nameSpaceURI != null) {
String resourcepath = namespacemap.get(nameSpaceURI);
if(resourcepath!=null) {

return new LSInputImpl(getClass().getResourceAsStream(resourcepath));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,46 @@

import org.xml.sax.SAXException;

import io.jans.saml.metadata.parser.ParserCreateError;

public class SAXUtils {

private static final Source [] schemasources = new Source [] {
new StreamSource(SAXUtils.class.getResourceAsStream("/schema/saml/saml-schema-metadata-2.0.xsd"))
new StreamSource(SAXUtils.class.getResourceAsStream("/META-INF/saml.schemas/saml-schema-metadata-2.0.xsd"))
};

private static SAXParserFactory parserfactory = null;

private SAXUtils() {

}

public static void init() throws ParserConfigurationException, SAXException {
if(parserfactory == null) {
parserfactory = SAXParserFactory.newInstance();
parserfactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
parserfactory.setSchema(newSchemaFactory().newSchema(schemasources)) ;
parserfactory.setNamespaceAware(true);
}
}


public static final SAXParser createParser() throws ParserConfigurationException, SAXException {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
factory.setSchema(newSchemaFactory().newSchema(schemasources));
factory.setNamespaceAware(true);
return factory.newSAXParser();

if(parserfactory == null) {
throw new ParserCreateError("Please call SAXParser.init() first");
}
return parserfactory.newSAXParser();
}

private static final SchemaFactory newSchemaFactory() throws SAXException {

final SchemaFactory schemafactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
schemafactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
schemafactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",false);
schemafactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA,"");
schemafactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
schemafactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,true);
schemafactory.setResourceResolver(new LSResourceResolverImpl());
return schemafactory;
}

private SAXUtils() {

}
}
14 changes: 14 additions & 0 deletions jans-keycloak-integration/job-scheduler/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@
<scope>compile</scope>
</dependency>
<!-- end jakarta ws-rs dependencies -->

<!-- jakarta annotation-api dependencies -->
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>${jakarta.annotation-api.version}</version>
<scope>compile</scope>
</dependency>
<!-- end jakarta annotation-api dependencies -->

<!-- jboss logging dependencies -->
<dependency>
Expand All @@ -81,6 +90,11 @@
<scope>compile</scope>
</dependency>
<!-- end jboss logging dependencies-->

<dependency>
<groupId>io.jans</groupId>
<artifactId>jans-core-saml</artifactId>
</dependency>

</dependencies>

Expand Down
Loading

0 comments on commit 3bf5f6d

Please sign in to comment.