Support WSS4J subject cert constraints
See gh-1419
This commit is contained in:
committed by
Stéphane Nicoll
parent
4b13ab34fb
commit
8460ad8a94
@@ -22,6 +22,7 @@ import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
@@ -60,6 +61,8 @@ import org.springframework.ws.soap.security.callback.CallbackHandlerChain;
|
||||
import org.springframework.ws.soap.security.callback.CleanupCallback;
|
||||
import org.springframework.ws.soap.security.wss4j2.callback.UsernameTokenPrincipalCallback;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
/**
|
||||
* A WS-Security endpoint interceptor based on Apache's WSS4J. This interceptor supports
|
||||
* messages created by the
|
||||
@@ -208,6 +211,8 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
|
||||
// To maintain same behavior as default, this flag is set to true
|
||||
private boolean removeSecurityHeader = true;
|
||||
|
||||
private List<Pattern> signatureSubjectDnPatterns = emptyList();
|
||||
|
||||
/**
|
||||
* Create a {@link WSSecurityEngine} by default.
|
||||
*/
|
||||
@@ -239,6 +244,15 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
|
||||
this.handler.setOption(WSHandlerConstants.ACTOR, securementActor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines whether to use a single certificate or a whole certificate chain when
|
||||
* constructing a BinarySecurityToken used for direct reference in signature. The
|
||||
* default is "true", meaning that only a single certificate is used.
|
||||
*/
|
||||
public void setSecurementSignatureSingleCertificate(boolean useSingleCertificate) {
|
||||
handler.setOption(WSHandlerConstants.USE_SINGLE_CERTIFICATE, useSingleCertificate);
|
||||
}
|
||||
|
||||
public void setSecurementEncryptionCrypto(Crypto securementEncryptionCrypto) {
|
||||
this.handler.setSecurementEncryptionCrypto(securementEncryptionCrypto);
|
||||
}
|
||||
@@ -527,6 +541,19 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
|
||||
this.validationSignatureCrypto = signatureCrypto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Certificate constraints which will be applied to the subject DN of the certificate
|
||||
* used for signature validation, after trust verification of the certificate chain
|
||||
* associated with the certificate.
|
||||
* @param patterns A list of regex patterns which will be applied to the subject DN.
|
||||
*
|
||||
* @see <a href="https://ws.apache.org/wss4j/config.html">WSS4J configuration:
|
||||
* SIG_SUBJECT_CERT_CONSTRAINTS</a>
|
||||
*/
|
||||
public void setValidationSubjectDnConstraints(List<Pattern> patterns) {
|
||||
signatureSubjectDnPatterns = patterns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to enable signatureConfirmation or not. By default, signatureConfirmation
|
||||
* is enabled.
|
||||
@@ -741,6 +768,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
|
||||
// allow for qualified password types for .Net interoperability
|
||||
requestData.setAllowNamespaceQualifiedPasswordTypes(true);
|
||||
|
||||
requestData.setSubjectCertConstraints(signatureSubjectDnPatterns);
|
||||
return requestData;
|
||||
}
|
||||
|
||||
@@ -780,6 +808,8 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
|
||||
// allow for qualified password types for .Net interoperability
|
||||
requestData.setAllowNamespaceQualifiedPasswordTypes(true);
|
||||
|
||||
requestData.setSubjectCertConstraints(signatureSubjectDnPatterns);
|
||||
|
||||
return requestData;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package org.springframework.ws.soap.security.wss4j2;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.w3c.dom.Document;
|
||||
@@ -28,6 +30,8 @@ import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.security.wss4j2.support.CryptoFactoryBean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||
|
||||
public abstract class Wss4jMessageInterceptorSignTest extends Wss4jTest {
|
||||
|
||||
@@ -123,4 +127,36 @@ public abstract class Wss4jMessageInterceptorSignTest extends Wss4jTest {
|
||||
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/ds:Signature", document);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCertificateSubjectDnConstraintsShouldMatchSubject() throws Exception {
|
||||
SoapMessage message = createSignedTestSoapMessage();
|
||||
MessageContext messageContext = getSoap11MessageContext(createSignedTestSoapMessage());
|
||||
interceptor.secureMessage(message, messageContext);
|
||||
|
||||
interceptor.setValidationActions("Signature");
|
||||
interceptor.setValidationSubjectDnConstraints(List.of(Pattern.compile(".*")));
|
||||
assertThatCode(() -> interceptor.validateMessage(message, messageContext)).doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCertificateSubjectDnConstraintsShouldFailForNotMatchingSubject() throws Exception {
|
||||
SoapMessage message = createSignedTestSoapMessage();
|
||||
MessageContext messageContext = getSoap11MessageContext(createSignedTestSoapMessage());
|
||||
interceptor.secureMessage(message, messageContext);
|
||||
|
||||
interceptor.setValidationActions("Signature");
|
||||
interceptor.setValidationSubjectDnConstraints(List.of(Pattern.compile("O=Some Other Company")));
|
||||
Throwable catched = catchThrowable(() -> interceptor.validateMessage(message, messageContext));
|
||||
assertThat(catched).isInstanceOf(Wss4jSecurityValidationException.class);
|
||||
}
|
||||
|
||||
private SoapMessage createSignedTestSoapMessage() throws Exception {
|
||||
interceptor.setSecurementActions("Signature");
|
||||
interceptor.setSecurementSignatureKeyIdentifier("DirectReference");
|
||||
interceptor.setSecurementSignatureSingleCertificate(false);
|
||||
interceptor.setSecurementPassword("123456");
|
||||
interceptor.setSecurementUsername("testkey");
|
||||
return loadSoap11Message("empty-soap.xml");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user