Кто-нибудь успешно использовал Wss4jSecurityInterceptor для Spring.WS для безопасности SAML с SAMLCallbackHandler в приложении Spring Boot? - PullRequest
1 голос
/ 30 апреля 2020

Может ли кто-то с опытом использования Wss4jSecurityInterceptor помочь выяснить, делаем ли мы что-то неправильно в отношении SAMLCallbackHandler для предоставления подтверждения для заголовка безопасности вызова SOAP?

В частности: org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor

Контекст:

Мы создаем служебную шину с использованием Spring Boot + Spring Integration, которая должна иметь возможность принимать и создавать запросы, подписанные с помощью SAML, а не в контексте единого входа. Мы выбрали Wss4jSecurityInterceptor для проверки и подписания запросов SOAP с помощью SAML. Мы применяем перехватчик непосредственно к Spring Webservices и не полагаемся на Spring Integration.

В настоящее время у нас возникают проблемы при подписании. У нас есть проверка и подписи работают, но никакое утверждение не применяется к исходящим сообщениям. Это требует, чтобы мы использовали действие защиты «SAMLTokenSigned», которое требует CallbackHandler для перехватчика (SAMLCallbackHandler).

На данный момент нам не удалось найти существующие реализации или хорошие примеры такого SAMLCallbackHandler. То, что мы обнаружили, было тусклым и привело нас на долгий путь «угадывания» того, чего не хватает обработчику при отладке. На данный момент кажется, что мы идем по неверному пути и что-то упускаем. Это не совсем новая работа, которую мы делаем.

Настройка Wss4jSecurityInterceptor выглядит так, как показано ниже.

@Bean
public Wss4jSecurityInterceptor wss4jSecurityInterceptor(){

    Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();

    // The action SAMLTokenSigned requires us to use SAMLCallbackk
    interceptor.setSecurementActions("Signature SAMLTokenSigned");

    interceptor.setSecurementSignatureCrypto(keystoreCrypto());
    interceptor.setSecurementUsername("client");
    interceptor.setSecurementPassword("password");
    interceptor.setSecurementSignatureDigestAlgorithm("http://www.w3.org/2007/05/xmldsig-more#sha3-256");
    interceptor.setSecurementSignatureAlgorithm("http://www.w3.org/2009/xmldsig11#dsa-sha256");

    SAML2CallbackHandler saml2CallbackHandler = new SAML2CallbackHandler(); // implements CallbackHandler
    saml2CallbackHandler.crypto = keystoreCrypto(); // using the same keystore for the issuer
    interceptor.setSecurementSamlCallbackHandler(saml2CallbackHandler);

    // we ignore validationActions for now. e.g. interceptor.setValidationActions("Signature");

    return interceptor;
}

public Crypto keystoreCrypto(){
    CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();

    try{
        cryptoFactoryBean.setKeyStoreLocation( new ClassPathResource("saml-keystore.jks"));
        cryptoFactoryBean.setKeyStorePassword("password");
        return cryptoFactoryBean.getObject();
    }
    catch(Exception e){}

    return null;
}

Наш обработчик SAML2Callback в значительной степени вдохновлен https://github.com/jaminh/spring-saml-example-war/blob/master/src/test/java/org/apache/ws/security/common/SAML2CallbackHandler.java но нам пришлось иметь дело с библиотеками, которые мы не могли найти в репозиториях maven, что дало ряд небольших проблем. Я могу предоставить нашу версию по запросу, но это не совсем понятно.

Хотя я не ожидаю, что она даст много, вот Stacktrace для исключения, которое выдается для кода в момент написания :

Original Exception was org.apache.wss4j.common.ext.WSSecurityException: No certificates were found for SAML signature
    at org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor.secureMessage(Wss4jSecurityInterceptor.java:577) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    at org.springframework.ws.soap.security.AbstractWsSecurityInterceptor.handleResponse(AbstractWsSecurityInterceptor.java:157) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.triggerHandleResponse(MessageDispatcher.java:371) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:239) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:176) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:89) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:61) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:293) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: org.apache.wss4j.common.ext.WSSecurityException: Error when signing the SAML token: 
    at org.apache.wss4j.dom.action.SAMLTokenSignedAction.execute(SAMLTokenSignedAction.java:133) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.apache.wss4j.dom.handler.WSHandler.doSenderAction(WSHandler.java:238) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.springframework.ws.soap.security.wss4j2.Wss4jHandler.doSenderAction(Wss4jHandler.java:63) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    at org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor.secureMessage(Wss4jSecurityInterceptor.java:574) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    ... 45 common frames omitted
Caused by: org.apache.wss4j.common.ext.WSSecurityException: No certificates were found for SAML signature
    at org.apache.wss4j.dom.saml.WSSecSignatureSAML.prepare(WSSecSignatureSAML.java:258) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.apache.wss4j.dom.saml.WSSecSignatureSAML.build(WSSecSignatureSAML.java:110) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.apache.wss4j.dom.action.SAMLTokenSignedAction.execute(SAMLTokenSignedAction.java:125) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    ... 48 common frames omitted

То же самое ожидание для информации о хранилище ключей, но, возможно, это может быть уместно:

  • Сгенерировано с помощью keytool (я не помню команду, к сожалению)
  • Publi c Тип и размер ключа: DSA 2048 бит Алгоритм подписи:
  • SHA256WITHDSA Отпечаток пальца SHA-1
  • 37: E8: E0: B7: DD: 7E: 7A: 33: 43: F8: 9D: 06: 6D: 20: 1E: BE: B7: 63: 3A: B9
...