barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)

вторник, 30 июня 2015 г.

TortoiseHG: push и "SSL: Server certificate verify failed"

Проблема

При попытке сделать push через TortoiseHG выдается ошибка:
SSL: Server certificate verify failed
, при этом push не выполняется.

Workaround

Идем в настройки, на вкладке глобальных настроен жмем "Edit File" (либо просто открываем файл mercurial.ini в домашней папке пользователя), добавляем:
[web]
cacerts=

WSO2 ESB: аутентификация на прокси-сервиса с помощью SAML 2.0-токена и ошибка "Version of the SAML token does not match with the required version"

Проблема

Есть защищенный прокси-сервис, policy которого имеет вид:
<wsp:Policy wsu:Id="SAML2HoKProtection31" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:IssuedToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<sp:Issuer>
<Address xmlns="http://www.w3.org/2005/08/addressing">https://localhost:9443/services/wso2carbon-sts</Address>
</sp:Issuer>
<sp:RequestSecurityTokenTemplate>
<t:TokenType xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</t:TokenType>
<t:KeyType xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://schemas.xmlsoap.org/ws/2005/02/trust/Bearer</t:KeyType>
<t:KeySize xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">256</t:KeySize>
</sp:RequestSecurityTokenTemplate>
<wsp:Policy>
<sp:RequireInternalReference/>
</wsp:Policy>
</sp:IssuedToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<rampart:RampartConfig xmlns:rampart="http://ws.apache.org/rampart/policy">
<!-- ... -->
</rampart:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Запрашиваем необходимый токен у сервиса wso2carbon-sts на той же шине:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
   <soapenv:Header xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
      <!-- ... -->
   </soapenv:Header>
   <soapenv:Body>
      <wst:RequestSecurityToken xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
         <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
         <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
            <wsa:EndpointReference xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
               <wsa:Address>https://localhost:8243/services/MySecuredService.MySecuredServiceHttpsSoap11Endpoint</wsa:Address>
            </wsa:EndpointReference>
         </wsp:AppliesTo>
         <wst:Lifetime>
            <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2015-06-16T21:00:47.099Z</wsu:Created>
            <wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2015-07-16T22:00:47.099Z</wsu:Expires>
         </wst:Lifetime>
         <wst:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</wst:TokenType>         <wst:KeyType>http://schemas.xmlsoap.org/ws/2005/02/trust/Bearer</wst:KeyType>
          <wst:KeySize>256</wst:KeySize>
      </wst:RequestSecurityToken>
   </soapenv:Body>
</soapenv:Envelope>

Используем полученный assertion в запросе к нашему защищенному сервису. В итоге получаем неожиданную ошибку:
"Version of the SAML token does not match with the required version"
Причина

При валидации токена Rampart сравнивает указанный в policy TokenType и значение пространства имен полученного в запросе Assertion'а (чтобы понять это, пришлось немного подправить класс org.apache.rampart.PolicyBasedResultsValidator. Для SAML 2.0-токена значение пространства имен равно "urn:oasis:names:tc:SAML:2.0:assertion", т.е. отличается от значения TokenType.

Решение

Пока нашел единственное решение - указывать в policy TokenType = urn:oasis:names:tc:SAML:2.0:assertion. Это не совсем корректно, т.к. в действительности STS-сервис не примет такое значение, если попробовать его использовать при запросе токена, но зато проверка токена в таком случае срабатывает.

суббота, 20 июня 2015 г.

WSO2 ESB 4.8.1: wso2carbon-sts и org.apache.axis2.AxisFault: The specified request failed

Проблема

Установил "чистую" WSO2 ESB 4.8.1, пытаюсь вызвать wso2carbon-sts для получения SAML 2.0 токена. Получаю soap-fault и следующий лог:
TID: [0] [ESB] [2015-06-19 17:59:08,281] ERROR {org.apache.rahas.STSMessageReceiver} -  org.apache.rahas.TrustException: The specified request failed {org.apache.rahas.STSMessageReceiver}
TID: [0] [ESB] [2015-06-19 17:59:08,282] ERROR {org.apache.synapse.transport.passthru.ServerWorker} -  Error processing POST request for : /services/wso2carbon-sts.wso2carbon-stsHttpsSoap12Endpoint {org.apache.synapse.transport.passthru.ServerWorker}
org.apache.axis2.AxisFault: The specified request failed
at org.apache.rahas.STSMessageReceiver.invokeBusinessLogic(STSMessageReceiver.java:66)
at org.apache.axis2.receivers.AbstractInOutMessageReceiver.invokeBusinessLogic(AbstractInOutMessageReceiver.java:40)
at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:110)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:411)
at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:183)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
При этом в stdout валится стек исключения TrustException целиком, что позволяет залезть в исходники и найти то место, откуда эта ошибка родом (http://grepcode.com/file/repo1.maven.org/maven2/org.apache.rampart/rampart-trust/1.6.2/org/apache/rahas/RahasData.java?av=f):
org.apache.rahas.TrustException: The specified request failed
        at org.apache.rahas.RahasData.processWSS4JSecurityResults(RahasData.java:173)
        at org.apache.rahas.RahasData.<init>(RahasData.java:109)
        at org.apache.rahas.TokenRequestDispatcher.handle(TokenRequestDispatcher.java:55)
        at org.apache.rahas.STSMessageReceiver.invokeBusinessLogic(STSMessageReceiver.java:57)
        at org.apache.axis2.receivers.AbstractInOutMessageReceiver.invokeBusinessLogic(AbstractInOutMessageReceiver.java:40)
        at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:110)
        at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
        at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:411)
        at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:183)
        at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:619)

Причина 

Для сервиса wso2carbon-sts не включена security, соответственно, несмотря на то, что при вызове сервиса я передаю в заголовке UsernameToken, он игнорируется. Соответственно, Rahas не знает, кого использовать в роли принципала в генерируемом токене, и падает с ошибкой.

Решение

Включаем security для сервиса wso2carbon-sts.

пятница, 19 июня 2015 г.

WSO2 ESB 4.8.1: логирование работы Entitlement-медиатора

В log4j.properties шины достаточно добавить строчку:
log4j.logger.org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator=DEBUG
после чего в логах шины появится достаточно отладочной информации, чтобы понять, что происходит внутри медиатора:
TID: [0] [ESB] [2015-06-19 15:16:41,294] DEBUG {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator} -  Mediation for Entitlement started {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator}
TID: [0] [ESB] [2015-06-19 15:16:41,295] DEBUG {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator} -  Subject ID is : ***** Resource ID is : /services/***** Action ID is : ****. {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator}
TID: [0] [ESB] [2015-06-19 15:16:41,993] DEBUG {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator} -  Entitlement Decision is : Deny {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator}
TID: [0] [ESB] [2015-06-19 15:16:41,993] DEBUG {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator} -  User is not authorized to perform the action {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator}

WSO2 ESB 4.8.1: отключение верификации хостнэймов при выполнении HTTPS-вызова

Предыстория

На dev-стенде в процессе отладки интеграционных сценариев получаем ошибку:
TID: [0] [ESB] [2015-08-13 15:54:12,584] ERROR {org.apache.synapse.transport.passthru.TargetHandler} -  I/O error: Host name verification failed for host : *** {org.apache.synapse.transport.passthru.TargetHandler}
javax.net.ssl.SSLException: Host name verification failed for host : ***
at org.apache.synapse.transport.http.conn.ClientSSLSetupHandler.verify(ClientSSLSetupHandler.java:152)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:285)
at org.apache.http.nio.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:380)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:118)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:160)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:342)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:320)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:280)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:106)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:604)
at java.lang.Thread.run(Thread.java:745)
Ошибка вполне логична, т.к. сертификат черт знает какой, и на данном этапе эта нас устраивает. Решение - отключение верификации хостнэймов при выполнении исходящих HTTPS-вызовов. Выполняется в файле %WSO2_HOME%/repository/conf/axis2/axis2.xml:
<transportSender name="https" class="org.apache.synapse.transport.passthru.PassThroughHttpSSLSender">
<!-- ... -->
<parameter name="HostnameVerifier">AllowAll</parameter>
<!-- ... -->
</transportSender>


понедельник, 13 апреля 2015 г.

IE: отключение прокси-сервера с помощью reg-файла

Задача

Отключить прокси-сервер в IE (а также, например, в Chrome, который использует настройки прокси из IE), т.е. снять галочку "Use a proxy server for your LAN", с помощью скрипта.

Решение

Для начала делаем reg-файл со следующим содержимым:
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings]
"ProxyEnable"=dword:00000000 
Затем создаем bat-ник с одной единственной командой:
regedit.exe /s "C:\path\to\reg-file" 
Если нужно снимать галочку по какому-либо событию либо периодически, то идем в планировщик и создаем там задачу с соотв. action'ом:

На вкладке "General" нужно установить "Run with highest privileges".

понедельник, 6 апреля 2015 г.

Постоянные беспричинные Full GC

Проблема

Есть сервер приложений, на котором крутится несколько достаточно сложных Java-приложений, использующих множество различных фреймворков. Под определенной нагрузкой сервер начинает очень сильно тормозить, отклик на http-запросы падает с долей секунды до нескольких десятков секунд.
Было включено расширенное логирование сборщика мусора ключами:
-Xloggc:\some\path\to\gc.log -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps
Настройки памяти следующие:
-Xms3072m -Xmx3072m -XX:MaxPermSize=512m
Соотношение young- / tenored-разделов в хипе - по-умолчанию (т.е. параметры -XX:NewSize / -XX:MaxNewSize / -XX:NewRatio не используются) , сборщики также используются по-умолчанию.
В итоге в gc.log появилась интересная информация:
...
51222.509: [GC [PSYoungGen: 6003K->128K(995648K)] 418005K->412130K(3092800K), 0.0124632 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

51222.522: [Full GC (System) [PSYoungGen: 128K->0K(995648K)] [PSOldGen: 412002K->412004K(2097152K)] 412130K->412004K(3092800K) [PSPermGen: 160113K->160113K(160640K)], 1.8001088 secs] [Times: user=1.79 sys=0.00, real=1.79 secs]

51224.324: [GC [PSYoungGen: 106K->96K(992448K)] 412110K->412100K(3089600K), 0.0097823 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]

51224.334: [Full GC (System) [PSYoungGen: 96K->0K(992448K)] [PSOldGen: 412004K->412004K(2097152K)] 412100K->412004K(3089600K) [PSPermGen: 160113K->160113K(160640K)], 1.7753052 secs] [Times: user=1.78 sys=0.00, real=1.78 secs]

51226.115: [GC [PSYoungGen: 9595K->128K(1001792K)] 421600K->412132K(3098944K), 0.0120281 secs] [Times: user=0.05 sys=0.00, real=0.02 secs]

51226.128: [Full GC (System) [PSYoungGen: 128K->0K(1001792K)] [PSOldGen: 412004K->409356K(2097152K)] 412132K->409356K(3098944K) [PSPermGen: 160113K->160113K(160576K)], 1.7348557 secs] [Times: user=1.73 sys=0.00, real=1.73 secs]

51227.942: [GC [PSYoungGen: 20781K->6387K(998784K)] 430137K->415744K(3095936K), 0.0125255 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]

51227.955: [Full GC (System) [PSYoungGen: 6387K->0K(998784K)] [PSOldGen: 409356K->415263K(2097152K)] 415744K->415263K(3095936K) [PSPermGen: 160120K->160120K(160576K)], 1.7130215 secs] [Times: user=1.72 sys=0.00, real=1.72 secs]
...
Т.е. видим следующую ситуацию: примерно раз в 2 секунды срабатывает сначала обычный GC, а вслед за ним - Full GC. Причем объективных причин сборки мусора нет: на момент начала работы GC в young generation свободно около 98-99% процентов памяти, в old generation - около 75%, в permament geneartion - 70% (от максимальных 512m). 

Решение

Сказать по правде, ситуация поставила в ступор. Благо, достаточно быстро нагуглилась схожая проблема: http://basisondemand.com/as_java/how_we_resolved_the_issue_of_frequent_full_gc_that_was_running_every_03_seconds_verbose_systemgc. Там парни предположили, что причина такого поведения - явные вызовы System.gc() где-то в коде. Благо, этот вызов можно игнорировать, если установить следующий ключ:
-XX:+DisableExplicitGC
В моем случае это решение также сработало.

ЗЫ Кстати, вот хорошая статейка по сборке мусора в Java: http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html.