Инструменты пользователя

Инструменты сайта


docker:otp-ifobs-client-java-applets

OTP клиент банк: проблема поддержки Java applets

Введение

В связи с полным и безвозвратным переходом на Linux, как на работе, так и дома, столкнулся с проблемой запуска клиент банка. На момент написания статьи я пользуюсь услугами OTP Bank. Типичный банк для Украины, ничего выдающегося, но вот в техническом и технологическом плане, тут все очень печально.

И пока я дома использовал ОС Windows, все было более менее нормально. У них есть и десктопная версия клиент банка, но работает она только под Windows, а судя по интерфейсу написана она на Delphi. Мобильная версия не позволяет производить никаких операций, а только просматривать данные, так что она тоже не подходит. И остается только веб клиент, но и тут меня ждало разочарование. У данного банка есть два вида веб клиентов - для физических лиц и для юридических. Если с первым все нормально, и он работает на любой ОС, то вот со вторым беда полная.

И да, в 2018 году, их клиент банк для юридических лиц работает на технологии java applet!!!. А как многие уже знают, на данный момент практически не осталось веб проводников, которые поддерживали java applet. На странице самого банка красуется такое предупреждение

Внимание! Уважаемые клиенты,

обращаем ваше внимание, что с 7-го марта 2017, после планового обновления браузера Firefox до версии 52, закончится поддержка всех NPAPI плагинов.

В связи с этим, единственным браузером в котором будет корректная работа стандартной web-версии системы клиент-банк OTP-Online на платформе OS Windows остается Internet Explorer версии 9 и выше. В качестве альтернативного варианта предлагаем воспользоваться портейбл версиею браузера Firefox, которая после установки не будет обновляться.

Собственно вариантов остается не так уж и много:

  1. Вернуться снова на Windows (нет, спасибо, но нет)
  2. Поменять банк на более продвинутый (уже занимаюсь этим), а такие у нас есть.
  3. Устанавливать и запускать Windows в любой среде виртуализации, например, KVM/VirtualBox.
  4. Попробовать запустить клиент банк через Wine.
  5. Попробовать собрать docker образ со строй версией Firefox.

Первый пункт отпадает сразу. Второй в процессе реализации, но требует много времени, так как с ФОП все немного сложнее, чем с обычным физ лицом. Третий не понравился по причине необходимости установки ПО для виртуализации и установке самой Windows, а по хорошему у вас должна быть куплена и лицензия под это дело. Wine в принципе как вариант, но там много шаманства, возможно как нибудь попробую. Так что, по сути, остается последний пункт, а так как последние 3 года я работаю devops инженером, и по долгу службы почти каждый день приходится сталкиваться с docker, то именно на нем мы и попробуем решить данную задачу.

Подготавливаем docker образа: Oracle Java vs OpenJDK

Итак, при попытке запустить веб клиент на современных версиях веб проводников, а на домашней машине я использую ubuntu 18.04 и Firefox 61.0.1, вы получите примерно такое сообщение с ошибкой

Запустить firefox в docker не проблема, проблема именно в необходимости поддержки NPAPI. Ибо тот же FF заявляет

Firefox 52 and above Beginning with Firefox 52 (released March 2017), plug-in support is limited to Adobe Flash, and drops support for NPAPI, impacting plugins for Java, Silverlight, and other similar NPAPI based plugins.

Немного поискав, нашел на странице самого FF информацию о специальной сборке под названием ESR (Extended Support Release)

Firefox 52 ESR Mozilla offers an Extended Support Release (ESR) version of Firefox specifically for use by organizations who need extended support for mass deployments. Only Mozilla Firefox 52 ESR release will continue offering support for the standards-based plugin support technology required to launch Java Applets. To see if you are using an ESR release, check the Firefox menu item (Help → About) and looking for the «ESR» identifier.

Так как нам придется установить еще и плагин для работы с Java, то тут возникает вопрос - а какую сборку Java использовать. На данный момент есть две сборки - православная от Oracle и OpenJDK.

С первой проблема заключается в том, что вы не сможете нормально скачать архив с произвольной версией Java c сайта Oracle, они требуют регистрации. Если очень надо автоматизировать данный шаг, то можно попробовать варианты со StackOverflow. А с OpenJDK проблема в том, что в ее составе нет плагина (libnpjp2.so). Вы должны использовать сторонний плагин, например icedtea-plugin (IcedTeaPlugin.so). Какую версию Java использовать в итоге - дело вкуса, в данной статье я буду использовать версию от Oracle.

Создаем папку для нашего образа и предварительно скачиваем Java и FireFox ESR. В итоге у нас должно получится примерно такое

$ mkdir -p ~/sandbox/docker/otp-ifobs-ffesr52/src
$ cd ~/sandbox/docker/otp-ifobs-ffesr52/
$ tree .
.
├── Dockerfile
└── src
    ├── firefox-52.9.0esr.tar.bz2
    └── jre-8u181-linux-x64.tar.gz

1 directory, 3 files

Собираем docker образ

FROM ubuntu:16.04


ENV TERM=xterm \
    JAVA_HOME=/otp/jre1.8.0_181 \
    PATH=$PATH:/otp/jre1.8.0_181/bin

# Устанавливаем зависимости, необходимые для запуска firefox
RUN DEBIAN_FRONTEND=noninteractive apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
    bzip2 apt-transport-https libx11-6 libfreetype6 \
    libfontconfig1 hicolor-icon-theme libxrender1 \
    libxext6 libxdamage1 libxcomposite1 libasound2 libxt6 \
    libxtst6 libdbus-glib-1-2 libxtst6 fontconfig \
    xfonts-cyrillic xfonts-100dpi ttf-ubuntu-font-family \
    ca-certificates dbus-x11 libgtk-3-0 desktop-file-utils \
    libgtk2.0-0 libcanberra-gtk3-module libcanberra-gtk-module \
    && fc-cache -fv \
    && apt-get clean \
    && apt-get autoremove -y \
    && rm -rf /var/lib/apt/lists/*


# Копируем архивы с java и firefox esr внутрь контейнера
COPY src/* /otp/


# Создаем отдельного пользователя firefox, от которого будет запускаться наш веб проводник,
# так как от root он работать не будет. А так же подключаем и настраиваем java plugin
RUN useradd firefox -s /bin/bash -m -d /otp/firefox/ \
    && cd /otp/ && tar jxf firefox-52.9.0esr.tar.bz2 \
    && tar zxf jre-8u181-linux-x64.tar.gz \
    && mkdir -p /otp/firefox/.mozilla/plugins \
    && cd /otp/firefox/.mozilla/plugins \
    && ln -s /otp/jre1.8.0_181/lib/amd64/libnpjp2.so . \
    && chown -R firefox:firefox /otp/firefox/ \
    && echo '577fed1c21a64f2cb186c800ae467e9d' > /etc/machine-id


WORKDIR /otp/firefox/
USER firefox

ENTRYPOINT ["/otp/firefox/firefox"]

После этого запускаем сборку контейнера

$ docker build -t otp-ifobs:ff-esr-52 .
Sending build context to Docker daemon    139MB
Step 1/8 : FROM ubuntu:16.04
 ---> 7aa3602ab41e
Step 2/8 : ENV TERM=xterm   JAVA_HOME=/otp/jre1.8.0_181   PATH=$PATH:/otp/jre1.8.0_181/bin
 ---> Running in bec83477b887
Removing intermediate container bec83477b887
 ---> dfd60f7b3d5c
...
...
...
Step 7/8 : USER firefox
 ---> Running in a4a162ec103b
Removing intermediate container a4a162ec103b
 ---> 059011e8d3e1
Step 8/8 : ENTRYPOINT ["/otp/firefox/firefox"]
 ---> Running in 5a6cc84b6ae3
Removing intermediate container 5a6cc84b6ae3
 ---> 11c92fce4b37
Successfully built 11c92fce4b37
Successfully tagged otp-ifobs:ff-esr-52

Тестирование

Ну а теперь переходим к самому интересному. Запускаем наш образ. Нам осталось решить только один вопрос - а как нам отображать собственно окно самого firefox? А для этого нам необходимо пробросить в наш докер контейнер папку с сокетом X server, на современных Linux дистрибутивах это как правило каталог /tmp/.X11-unix. Если запустить lsof, то мы увидим примерно такой вывод

$ lsof /tmp/.X11-unix/X0 
COMMAND  PID USER   FD   TYPE             DEVICE SIZE/OFF  NODE NAME
Xorg    2011 alex    7u  unix 0x0000000000000000      0t0 30532 /tmp/.X11-unix/X0 type=STREAM

Но этого недостаточно, так же нам надо передать номер дисплея, куда осуществлять вывод, который хранится в переменной $DISPLAY. Вы можете посмотреть значение этой переменной

$ echo $DISPLAY
:0

Итак, у нас все готово для запуска, так что пробуем взлететь

$ docker run -it --rm -e DISPLAY=${DISPLAY} -v /tmp/.X11-unix:/tmp/.X11-unix otp-ifobs:ff-esr-52

После этой команды на рабочем столе должно появится окно с Firefox. Для проверки смотрим Help → About Firefox

Проверяем, что java plugin был подключен и загружен, для этого в строке адреса открываем about:plugin

Если видим в списке плагинов Java, значит все у нас собранно и настроенно правильно. Для проверки работы самого плагина есть тестовая страница - http://www.java.com/en/download/installed.jsp?detect=jre

Нажимаем на Activate Java и соглашаемся с запуском Java приложения

В итоге мы должны увидеть такое сообщение

На этом проверку можно считать завершенной и переходим непосредственно к клиент банку - https://ibank.otpbank.com.ua/ifobsClient/. Вводим логин и пароль, после этого у нас должно появится окно с запросом подтверждения запуска Java аплета

После того как мы даем разрешение, мы наконец то попадаем в клиент банк

Для удобства запуска, я добавил адрес клиент банка параметром в ENTRYPOINT

ENTRYPOINT ["/opt/firefox/firefox", "https://ibank.otpbank.com.ua/ifobsClient/LoginShow.action?localeName=ru"]

Так же если хочется, чтобы между запусками сохранялись все настройки самого Firefox, то достаточно при запуске контейнера пробрасывать папку /otp/firefox/.mozilla/firefox

$ docker run -it --rm -e DISPLAY=${DISPLAY} -v /tmp/.X11-unix:/tmp/.X11-unix \
-v ~/sandbox/docker/otp-ifobs-ffesr52/profile:/otp/firefox/.mozilla/firefox otp-ifobs:ff-esr-52

Alpine: OpenJDK

Решил таки добавить информацию о запуске данной системы на базе OpenJDK. Как оказалось там не все так просто как c Oracle Java. Создаем следующий Dockerfile, но на этот раз наш образ будет базироваться на базе alpine. Самое главное отличие alpine от других дистрибутивов, в том числе и Ubuntu, в том, что вместо традиционной библиотеки glibc используется альтернативная реализация - musl. С основными отличиями от других реализаций можно ознакомиться по данной ссылке

FROM alpine:3.8

ENV TERM=xterm \
    JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk/jre \
    PATH=$PATH:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin

RUN apk update \
    && apk add bash \
    firefox-esr \
    icedtea-web-mozilla \
    icedtea-web \
    libcanberra-gtk3 \
    adwaita-gtk2-theme \
    adwaita-icon-theme \
    ttf-ubuntu-font-family \
    ttf-liberation \
    ttf-dejavu \
    shadow \
    && mkdir /otp

RUN useradd firefox -s /bin/bash -m -d /otp/firefox/ \
    && chown -R firefox:firefox /otp/firefox/ \
    && echo '577fed1c21a64f2cb186c800ae467e9d' > /etc/machine-id

WORKDIR /otp/firefox/
USER firefox

ENTRYPOINT ["firefox", "https://ibank.otpbank.com.ua/ifobsClient/LoginShow.action?localeName=ru"]

У alpine есть несколько преимуществ - он легковесный, так например, результирующий образ получился 295 Mb, против 810 на базе Ubuntu. Так же в составе уже идет Firefox 52 ESR и OpenJDK. Собираем и запускаем образ, на первый взгляд все тоже самое, разве что окна с запросом на разрешения запуска аплетов немного отличаются

После этого мы попадаем в сам клиент банк, но как оказалось чуть позже - радоваться было рано. При выполнение базовых операций, например клонирование документа, начали появляться ошибки

При этом в самой консоли были следующие ошибки

com.cs.crypto.applet.client.CSApplet Exception: 
java.security.AccessControlException: access denied ("java.util.PropertyPermission" "java.io.tmpdir" "read")
       at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
       at java.security.AccessController.checkPermission(AccessController.java:884)
       at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
       at net.sourceforge.jnlp.runtime.JNLPSecurityManager.checkPermission(JNLPSecurityManager.java:292)
       at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1294)
       at java.lang.System.getProperty(System.java:717)
       at com.cs.crypto.applet.processor.IOProcessor.getTmpPathFile(Unknown Source)
       at com.cs.crypto.applet.processor.IOProcessor.loadPathProp(Unknown Source)
       at com.cs.crypto.applet.processor.IOProcessor.getLastPath(Unknown Source)
       at com.cs.crypto.applet.client.CSApplet.doRun(Unknown Source)
       at com.cs.crypto.applet.base.AbstractThreadJApplet.run(Unknown Source)
       at java.lang.Thread.run(Thread.java:748)
com.cs.crypto.applet.client.CSApplet Exception: 
Code: CRYPTO_ERR_SYSTEM_OPERATION. CryptoMsg: Произошла системная ошибка при выполнения крипто-операции. Попробуйте еще раз.

Немного поискав информацию по данной ошибке, стало очевидно, что дело связано с java.policy. Я не знаю тонкостей, но получается, что java плагины от Oracle и Icedtea абсолютно по разному работают в контексте java applets. Так что, для успешной работы в OpenJDK нам необходимо создать файл с политикой и разместить его в домашней папке пользователя firefox

$ cat ~/.java.policy
grant codeBase "https://ibank.otpbank.com.ua/ifobsClient/-" {
    permission java.security.AllPermission;
};

Модифицируем наш Dockerfile и добавляем соответствующий файл

FROM alpine:3.8


ENV TERM=xterm \
    JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk/jre \
    PATH=$PATH:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin


RUN apk update \
    && apk add bash \
    firefox-esr \
    icedtea-web-mozilla \
    icedtea-web \
    libcanberra-gtk3 \
    adwaita-gtk2-theme \
    adwaita-icon-theme \
    ttf-ubuntu-font-family \
    ttf-liberation \
    ttf-dejavu \
    shadow \
    && mkdir /otp

RUN useradd firefox -s /bin/bash -m -d /otp/firefox/ \
    && chown -R firefox:firefox /otp/firefox/ \
    && echo '577fed1c21a64f2cb186c800ae467e9d' > /etc/machine-id \
    && { \
        echo 'grant codeBase "https://ibank.otpbank.com.ua/ifobsClient/-" {'; \
        echo '    permission java.security.AllPermission;'; \
        echo '};'; \
    } > /otp/firefox/.java.policy


WORKDIR /otp/firefox/
USER firefox

ENTRYPOINT ["firefox", "https://ibank.otpbank.com.ua/ifobsClient/LoginShow.action?localeName=ru"]

После этого пересобираем образ и проверяем, что все работает. Вообще давать полные права как в случае с java.security.AllPermission является плохой практикой, и по хорошему в файле ~/.java.policy необходимо прописать только необходимые права, но так как мы используем контейнер только для работы с клиент банком, это не так критично. Так что формирование списка политик оставляю вам в качестве домашнего задания.

docker/otp-ifobs-client-java-applets.txt · Последние изменения: 2018/09/03 12:59 — root