Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1c6c0ea
Migrate to Wildfly 26.1.3.Final
lbschanno Apr 14, 2026
619537a
Replace left/right brackets with html tags in Javadoc
lbschanno Apr 14, 2026
e78b22b
Verify keystore/truststore type is not null
lbschanno Apr 14, 2026
d83bb1c
Fix Javadoc causing errors
lbschanno Apr 14, 2026
5e3186c
Separate DnUtils from any configuration concerns
lbschanno Apr 15, 2026
cadf406
Fix service loader issues and update usages of DnUtils
lbschanno Apr 16, 2026
acd0295
Merge branch 'integration' into task/wildfly-update
lbschanno Apr 16, 2026
6d18742
Update usage of ProxiedEntityUtils
lbschanno Apr 16, 2026
01547f4
Fix issues with ClientLoginExampleBean
lbschanno Apr 17, 2026
8895f89
Move datawave JBOSS modules from webservices to webservice
lbschanno Apr 17, 2026
d250949
Use SSLStores in WiredQueryExecutorBeanTest
lbschanno Apr 18, 2026
fda2b34
Remove SSLStores.getCertificate() method
lbschanno Apr 18, 2026
1eae800
Load system properties first in DnUtils
lbschanno Apr 21, 2026
51b4825
Make commons/security follow main versioning
lbschanno Apr 21, 2026
b49729f
Add back injection of DnUtils (DnProperties)
lbschanno Apr 21, 2026
702647c
Merge branch 'integration' into task/wildfly-update
lbschanno Apr 21, 2026
970c587
Use intermediate commons/security release for microservices
lbschanno Apr 21, 2026
0cbee4f
Undo change to commons/security pom
lbschanno Apr 21, 2026
376a187
Merge branch 'integration' into task/wildfly-update
lbschanno May 4, 2026
82f0108
Update pom versions
lbschanno May 4, 2026
a12a690
Remove picketbox imports again
lbschanno May 5, 2026
a969ea1
Fix arquillian dependency issues
lbschanno May 26, 2026
9dd70ba
Delete unneccessary dependency
lbschanno May 26, 2026
38fabd7
Merge branch 'integration' into task/wildfly-update
lbschanno May 26, 2026
050aa49
Update pom versions
lbschanno May 26, 2026
9fea5e4
Code formatting
lbschanno May 26, 2026
4bfbfb9
Make bean definitions discoverable by microservices
lbschanno May 26, 2026
0c66c63
Use RC versions for microservice CI tests
lbschanno May 26, 2026
faa654c
Fix microservice pom versions
lbschanno May 26, 2026
9fed2cf
Explicitly define RC version of commons-security for compose tests
lbschanno May 26, 2026
fb9c55e
Improve wording of pom comment
lbschanno May 26, 2026
e7235d4
Trigger CI workflow
lbschanno May 26, 2026
e6e45f7
Code formatting
lbschanno May 26, 2026
ee8cb96
Use RC of authorization-api with explicit version for commons-security
lbschanno May 27, 2026
3c65ab2
Set microservice poms to SNAPSHOT versions
lbschanno May 27, 2026
8c52709
Update RC dependency used
lbschanno May 27, 2026
5d9614f
Remove unecessary property overrides
lbschanno May 27, 2026
924c74a
Remove auhorizations-api dependency from accumulo-utils
lbschanno May 27, 2026
3e3021d
Merge branch 'integration' into task/wildfly-update
lbschanno Jun 1, 2026
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
18 changes: 18 additions & 0 deletions commons/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>gov.nsa.datawave</groupId>
<artifactId>datawave-parent</artifactId>
<version>7.40.0-SNAPSHOT</version>
</parent>

<groupId>gov.nsa.datawave.commons</groupId>
<artifactId>datawave-commons-parent</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>

<modules>
<module>security</module>
</modules>
</project>
6 changes: 6 additions & 0 deletions commons/security/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Overview

This project contains security-related classes that are commonly used between the main Datawave project and the microservices. It is expected that this project will be configured and deployed as a JBOSS module via the [Wildfly assembly](../../web-services/deploy/application) project to make it available to the Datawave EAR deployment.

## Note:
Any compile dependencies here are expected to be imported into the Datawave webservices projects with scope `provided`, and provided via JBOSS modules. This is required to avoid classloader conflicts between the JBOSS modules and the Datawave EAR deployment. See the [Wildfly assembly README](../../web-services/deploy/application/README.md) for more details.
61 changes: 61 additions & 0 deletions commons/security/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>gov.nsa.datawave.commons</groupId>
<artifactId>datawave-commons-parent</artifactId>
<version>7.40.0-SNAPSHOT</version>
</parent>

<artifactId>datawave-commons-security</artifactId>
<name>${project.artifactId}</name>

<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${version.jackson}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${version.jackson}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${version.jjwt}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${version.jjwt}</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>${version.jakarta}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.junit-pioneer</groupId>
<artifactId>junit-pioneer</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import javax.xml.bind.annotation.XmlType;

import datawave.security.authorization.DatawaveUser.UserType;
import datawave.security.util.ProxiedEntityUtils;
import datawave.security.util.DnUtils;

/**
* A {@link Principal} that represents a set of proxied {@link DatawaveUser}s. For example, this proxied user could represent a GUI server acting on behalf of a
Expand Down Expand Up @@ -103,8 +103,8 @@ static protected List<DatawaveUser> orderProxiedUsers(List<DatawaveUser> datawav
if (position >= 0) {
users.add(datawaveUsers.get(position));
if (datawaveUsers.size() > 1) {
datawaveUsers.stream().limit(position).forEach(u -> users.add(u));
datawaveUsers.stream().skip(position + 1).forEach(u -> users.add(u));
datawaveUsers.stream().limit(position).forEach(users::add);
datawaveUsers.stream().skip(position + 1).forEach(users::add);
}
}
return users;
Expand Down Expand Up @@ -152,7 +152,7 @@ public String getName() {

@Override
public String getShortName() {
return ProxiedEntityUtils.getShortName(getPrimaryUser().getName());
return DnUtils.getShortName(getPrimaryUser().getName());
}

public SubjectIssuerDNPair getUserDN() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,22 @@
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;

import datawave.security.util.ProxiedEntityUtils;
import datawave.security.util.DnUtils;

/**
* A user of a DATAWAVE service. Typically, one or more of these users (a chain where a user called an intermediate service which in turn called us) is
* represented with a DatawavePrincipal.
*/
public class DatawaveUser implements Serializable {

private static final long serialVersionUID = -6676807246749142999L;

public enum UserType {
USER, SERVER
}

public static final DatawaveUser ANONYMOUS_USER = new DatawaveUser(SubjectIssuerDNPair.of("ANONYMOUS"), UserType.USER, null, null, null, null, -1L);

private final String name;
private final String commonName;
private final String email;
Expand Down Expand Up @@ -58,8 +60,8 @@ public DatawaveUser(@JsonProperty(value = "dn", required = true) SubjectIssuerDN
@JsonProperty(value = "creationTime", defaultValue = "-1L") long creationTime,
@JsonProperty(value = "expirationTime", defaultValue = "-1L") long expirationTime) {
this.name = dn.toString();
this.commonName = ProxiedEntityUtils.getCommonName(dn.subjectDN());
this.login = ProxiedEntityUtils.getShortName(dn.subjectDN());
this.commonName = DnUtils.getCommonName(dn.subjectDN());
this.login = DnUtils.getShortName(dn.subjectDN());
this.email = email;
this.dn = dn;
this.userType = userType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public Collection<DatawaveUser> createUsersFromToken(String token, String claimN
return principalsClaim.stream().map(obj -> objectMapper.convertValue(obj, DatawaveUser.class)).collect(Collectors.toList());
}

private class CustomJWTBuilder extends DefaultJwtBuilder {
private static class CustomJWTBuilder extends DefaultJwtBuilder {
private final ObjectMapper objectMapper;

private CustomJWTBuilder(ObjectMapper objectMapper) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;

import datawave.security.util.ProxiedEntityUtils;
import datawave.security.util.DnUtils;

/**
* A simple pair containing a subject and (optional) issuer DN. The supplied DN values are normalized into a lower-case form with the CN portion first.
*
* @see ProxiedEntityUtils#normalizeDN(String)
* @see DnUtils#normalizeDN(String)
*/
public class SubjectIssuerDNPair implements Serializable {

Expand Down Expand Up @@ -61,7 +61,7 @@ public static SubjectIssuerDNPair of(@JsonProperty("subjectDN") String subjectDN
* if DNs cannot be parsed from the argument, or if exactly two DNs are not parsed
*/
public static SubjectIssuerDNPair parse(String value) {
String[] dns = ProxiedEntityUtils.splitProxiedSubjectIssuerDNs(value);
String[] dns = DnUtils.splitProxiedSubjectIssuerDNs(value);
if (dns.length != 2) {
throw new IllegalArgumentException("'" + value + "' must contain a single subject and issuer DN");
}
Expand All @@ -70,9 +70,9 @@ public static SubjectIssuerDNPair parse(String value) {

protected SubjectIssuerDNPair(String subjectDN, String issuerDN) {
Preconditions.checkNotNull(subjectDN, "Parameter subjectDN must not be null");
this.subjectDN = ProxiedEntityUtils.normalizeDN(subjectDN);
this.subjectDN = DnUtils.normalizeDN(subjectDN);
if (issuerDN != null) {
this.issuerDN = ProxiedEntityUtils.normalizeDN(issuerDN);
this.issuerDN = DnUtils.normalizeDN(issuerDN);
} else {
this.issuerDN = null;
}
Expand All @@ -90,7 +90,7 @@ public String issuerDN() {

@Override
public String toString() {
return issuerDN == null ? subjectDN + "<>" : ProxiedEntityUtils.buildProxiedDN(subjectDN, issuerDN);
return issuerDN == null ? subjectDN + "<>" : DnUtils.buildProxiedDN(subjectDN, issuerDN);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package datawave.security.cert;

import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.Objects;

import org.slf4j.Logger;

/**
* A Datawave-specific {@link X509CertificateVerifier} implementation.
*/
public class DatawaveCertVerifier implements X509CertificateVerifier {

public enum OcspLevel {
OFF, OPTIONAL, REQUIRED
}

protected Logger log;
protected boolean trace;
protected OcspLevel ocspLevel = OcspLevel.OFF;

/**
* Verify the given certificate
*
* @param cert
* the X509Certificate to verify
* @param alias
* the certificate alias
* @param keystore
* the keystore for the cert
* @param truststore
* the truststore for the cert
* @return whether the certificate is considered valid
*/
@Override
public boolean verify(X509Certificate cert, String alias, KeyStore keystore, KeyStore truststore) {
boolean validity = false;
try {
cert.checkValidity();
validity = checkOCSP(cert, alias, truststore);
} catch (Exception e) {
if (trace)
log.trace("Validity exception", e);
}
return validity;

}

/**
* Handle OSCP initialization.
*/
protected void initOcsp() {}

/**
* Return the OSCP level set for this verifier is supported for the given certificate.
*
* @param cert
* the certificate
* @param alias
* the certificate alias
* @param truststore
* the truststore
* @return true if the OSCP level is supported, or false otherwise
*/
protected boolean checkOCSP(X509Certificate cert, String alias, KeyStore truststore) {
if (Objects.requireNonNull(ocspLevel) == OcspLevel.OFF) {
return true;
} else {
log.error("OCSP level {} is not supported!", ocspLevel);
throw new IllegalArgumentException("OCSP level " + ocspLevel + " is not supported!");
}
}

/**
* Return whether the given issuer is supported.
*
* @param issuerSubjectDn
* the issuer DN
* @param trustStore
* the truststore
* @return true if the issuer is supported, or false otherwise
*/
public boolean isIssuerSupported(String issuerSubjectDn, KeyStore trustStore) {
return true;
Comment thread
lbschanno marked this conversation as resolved.
}

/**
* Set the delegate logger for this {@link DatawaveCertVerifier}.
*
* @param log
* the logger
*/
public void setLogger(Logger log) {
this.log = log;
this.trace = log.isTraceEnabled();
}

/**
* Return the OSCP level.
*
* @return the OSCP level
*/
public OcspLevel getOcspLevel() {
return ocspLevel;
}

/**
* Set the OSCP level.
*
* @param level
* the OSCP level
*/
public void setOcspLevel(String level) {
ocspLevel = OcspLevel.valueOf(level.toUpperCase());
switch (ocspLevel) {
case REQUIRED:
case OPTIONAL:
initOcsp();
break;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package datawave.security.cert;

import java.security.KeyStore;

import javax.net.ssl.KeyManager;
import javax.net.ssl.TrustManager;

/**
* Represents a key store/trust store pair.
*/
public interface SSLStores {

/**
* Return the key store
*
* @return the keystore
*/
default KeyStore getKeyStore() {
return null;
}

/**
* Return the key managers
*
* @return the key managers
*/
default KeyManager[] getKeyManagers() {
return new KeyManager[0];
}

/**
* Return the trust store
*
* @return the truststore
*/
default KeyStore getTrustStore() {
return null;
}

/**
* Return the trust managers
*
* @return the trust managers
*/
default TrustManager[] getTrustManagers() {
return new TrustManager[0];
}

}
Loading
Loading