Skip to content

Commit

Permalink
[ELY-2320] Add integrity support to FileSystemSecurityRealm
Browse files Browse the repository at this point in the history
  • Loading branch information
Ashpan committed Jul 26, 2022
1 parent 20504d9 commit 8545a08
Show file tree
Hide file tree
Showing 9 changed files with 1,175 additions and 445 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,19 @@ interface ElytronMessages extends BasicLogger {
@Message(id = 13006, value = "Filesystem-backed realm unable to encrypt identity")
RealmUnavailableException fileSystemRealmEncryptionFailed(@Cause Throwable cause);

@Message(id = 13007, value = "Filesystem-backed realm found an incompatible identity version. Requires at least version: %s")
RealmUnavailableException fileSystemRealmIncompatibleIdentityVersion(String expectedVersion);
@Message(id = 13007, value = "Signature for the following identity is invalid: %s.")
IntegrityException invalidIdentitySignature(String s);

@Message(id = 13008, value = "Unable to create a signature for the file: %s.")
RealmUnavailableException unableToGenerateSignature(String s);

@Message(id = 13009, value = "Unable to locate the signature element for the file: %s")
RealmUnavailableException cannotFindSignature(String s);

@Message(id = 13010, value = "Both PrivateKey and PublicKey must be defined for realm at: %s")
IllegalArgumentException invalidKeyPairArgument(String s);

@Message(id = 13011, value = "Integrity has not been enabled for the realm at: %s")
IllegalArgumentException integrityNotEnabled(String s);

}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.util.function.Supplier;

import javax.crypto.SecretKey;
Expand All @@ -44,6 +46,8 @@ public class FileSystemSecurityRealmBuilder {
private Charset hashCharset;
private Encoding hashEncoding;
private SecretKey secretKey;
private PrivateKey privateKey;
private PublicKey publicKey;
private Supplier<Provider[]> providers;

FileSystemSecurityRealmBuilder() {
Expand Down Expand Up @@ -132,12 +136,42 @@ public FileSystemSecurityRealmBuilder setSecretKey(final SecretKey secretKey) {
return this;
}

/**
* Set the providers to be used by the realm.
*
* @param providers the provider to be used (must not be {@code null})
* @return this builder.
*/
public FileSystemSecurityRealmBuilder setProviders(final Supplier<Provider[]> providers) {
Assert.checkNotNullParam("providers", providers);
this.providers = providers;
return this;
}

/**
* Set the PrivateKey to be used by the realm.
*
* @param privateKey the asymmetric PrivateKey used to sign the identity files used for file integrity (must not be {@code null})
* @return this builder.
*/
public FileSystemSecurityRealmBuilder setPrivateKey(final PrivateKey privateKey) {
Assert.checkNotNullParam("privateKey", privateKey);
this.privateKey = privateKey;
return this;
}

/**
* Set the PublicKey to be used by the realm.
*
* @param publicKey the asymmetric PublicKey used to verify the identity files used for file integrity (must not be {@code null})
* @return this builder.
*/
public FileSystemSecurityRealmBuilder setPublicKey(final PublicKey publicKey) {
Assert.checkNotNullParam("publicKey", publicKey);
this.publicKey = publicKey;
return this;
}

/**
* Builds a new {@link FileSystemSecurityRealm} instance based on configuration defined for this {@link FileSystemSecurityRealmBuilder} instance.
*
Expand All @@ -154,6 +188,10 @@ public FileSystemSecurityRealm build() {
if (hashCharset == null) {
hashCharset = StandardCharsets.UTF_8;
}
return new FileSystemSecurityRealm(root, nameRewriter, levels, encoded, hashEncoding, hashCharset, providers, secretKey);
if (privateKey == null ^ publicKey == null) {
throw ElytronMessages.log.invalidKeyPairArgument(root.toString());
}

return new FileSystemSecurityRealm(root, nameRewriter, levels, encoded, hashEncoding, hashCharset, providers, secretKey, privateKey, publicKey);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2022 Red Hat, Inc., and individual 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.wildfly.security.auth.realm;

import java.io.IOException;

/**
* Exception to indicate a general failure related to the Integrity Verification of the Filesystem Realm.
*
* @author <a href="mailto:[email protected]">Ashpan Raskar</a>
*/
public class IntegrityException extends IOException {


private static final long serialVersionUID = 8889252552074803941L;

/**
* Constructs a new {@code IntegrityException} instance. The message is left blank ({@code null}), and no
* cause is specified.
*/
public IntegrityException() {
}

/**
* Constructs a new {@code IntegrityException} instance with an initial message. No cause is specified.
*
* @param msg the message
*/
public IntegrityException(final String msg) {
super(msg);
}

/**
* Constructs a new {@code IntegrityException} instance with an initial cause. If a non-{@code null} cause
* is specified, its message is used to initialize the message of this {@code IntegrityException}; otherwise
* the message is left blank ({@code null}).
*
* @param cause the cause
*/
public IntegrityException(final Throwable cause) {
super(cause);
}

/**
* Constructs a new {@code IntegrityException} instance with an initial message and cause.
*
* @param msg the message
* @param cause the cause
*/
public IntegrityException(final String msg, final Throwable cause) {
super(msg, cause);
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,22 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:elytron:identity:1.2"
xmlns="urn:elytron:identity:1.2"
xmlns:xmldsig="http://www.w3.org/2000/09/xmldsig#"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="1.2">

<!-- File-backed realm elements -->

<xsd:element name="identity" type="identity-type"/>
<xsd:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="https://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd" />

<xsd:complexType name="identity-type">
<xsd:all minOccurs="1" maxOccurs="1">
<xsd:element name="principal" type="name-type" minOccurs="0" maxOccurs="1"/>
<xsd:element name="credentials" type="credentials-type" minOccurs="0" maxOccurs="1"/>
<xsd:element name="attributes" type="attributes-type" minOccurs="0" maxOccurs="1"/>
<xsd:element name="Signature" type="xmldsig:SignatureType" minOccurs="0" maxOccurs="1"/>
</xsd:all>
</xsd:complexType>

Expand Down Expand Up @@ -144,4 +148,5 @@
</xsd:sequence>
</xsd:complexType>


</xsd:schema>
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
<version.org.keycloak>17.0.0</version.org.keycloak>
<version.io.rest-assured>4.3.3</version.io.rest-assured>
<version.net.sourceforge.htmlunit.htmlunit>2.40.0</version.net.sourceforge.htmlunit.htmlunit>
<version.org.apache.santuario>2.3.0</version.org.apache.santuario>

<test.level>INFO</test.level>
<!-- Checkstyle configuration -->
Expand Down Expand Up @@ -1048,7 +1049,6 @@
<version>${version.org.bitbucket.b_c.jose4j}</version>
</dependency>


<!--
Test Scope Only
-->
Expand Down
Loading

0 comments on commit 8545a08

Please sign in to comment.