OAuth2 Proxy v7.5.1 + Nginx + IdP + RDWeb\webclient
Автор Denis Shelamov, Last modified by Denis Shelamov на 22 апреля 2024 04:24 PM

Настройка Indeed IDP аутентификации на RDweb / Webclient через OAuth2 Proxy + NGINX

Содержание:

  1. Предварительные требования
  2. Описание процесса
  3. Подготовка
  4. Настройка OAuth сервера
  5. Настройка NGINX сервера
  6. Настройка IDP сервера
  7. Настройка Redis DB

Предварительные требования:

Cхема взаимодействия и установки Nginx и OAuth2-proxy на разных машинах

Предполагается что установлен и настроен Indeed AM версии 8.1.5 и выше,

установлен и настроен rdweb\webclient.

Описание процесса:

На интернет шлюзе (internetgate.indeed.local) открывается порт 443, и пробрасывается на машину nginx.indeed.local, на 443 порт.

На nginx.indeed.local установлен nginx, для которого настроены правила публикации 3х порталов:

  1. Indeed IdP
  2. Rdweb
  3. oauth2-proxy

В Зависимости от URL, по которому происходит обращение, nginx распределяет запросы на конечные сервера.

Для URL, вида 

  1. Rdweb\webclient
  2. /remoteDesktopGateway

Происходит проверка cookie авторизации, и в случае их отсутствия, все запросы с этих URL перенаправляются на oauth2-proxy.

oauth2-proxy делает запрос к Indeed IdP, на машину am1.indeed.local, через URL nginx.indeed.local (rdweb.indeed.local\am\idp), где пользователь проходит аутентификацию.

Затем, Indeed IdP отправляет ответ на rdweb.indeed.local\oauth2\, который перенаправляется на oauth2-proxy.

В случае успешной аутентификации, oauth2-proxy отправляет на nginx cookie пользователя, для доступа к закрытым ресурсам.

Nginx.indeed.local, получив cookie, пропускает пользователя к изначально запрошенному ресурсу.

Подготовка:

Cинхронизируем время на nginx, oauth, idp

apt-get install ntp -y
nano /etc/ntp.conf

меняем на внутренний сервер времени

server 10.10.10.11 prefer iburst

Задаем часовой пояс

sudo timedatectl set-timezone Europe/Moscow

запускаем клиент времени

systemctl restart ntp

Настройка OAuth сервера

На сервере oauth.indeed.local

Т.к. rdweb публикуется с таким же именем, что и внутри домена, потребуется жесткая привязка имени rdweb.indeed.local ко внутреннему ip nginx

sudo nano /etc/hosts

укажем

10.10.10.8 oauth.indeed.local
10.10.10.7
rdweb.indeed.local

Устанавливаем oauth2-proxy актуальной версии (можно увидеть по ссылке https://github.com/oauth2-proxy/oauth2-proxy/releases)

wget https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.5.1/oauth2-proxy-v7.5.1.linux-amd64.tar.gz

tar xvzf oauth2-proxy-v7.5.1.linux-amd64.tar.gz

mv oauth2-proxy-v7.5.1.linux-amd64 /opt

Для удобства работы, сделаем символьную ссылку

ln -s /opt/oauth2-proxy-v7.5.1.linux-amd64 /opt/oauth2-proxy

Создадим файл конфигурации 

sudo nano /etc/oauth2-proxy.cfg

provider="oidc"

client_id="nginx_oauth"

client_secret="Qq123456"

login_url="https://rdweb.indeed.local/am/idp/connect/authorize"

profile_url="https://rdweb.indeed.local/am/idp/connect/userinfo"

redeem_url="https://rdweb.indeed.local/am/idp/connect/token"

redirect_url="https://rdweb.indeed.local/oauth2/callback"

oidc_jwks_url="https://rdweb.indeed.local/am/idp/.well-known/jwks"

oidc_issuer_url="https://rdweb.indeed.local/am/idp"

provider_display_name="Indeed IdP"

custom_sign_in_logo="https://download.indeed-company.ru/s/fWgurqdspwkZJYN/download"

cookie_secret="UklyW3dPZTlRVW05OGorJn1Beno3QXpPT0tfTTNOYXs="

pass_access_token="true"

set_authorization_header="true"

insecure_oidc_allow_unverified_email="true"

scope="openid"

oidc_email_claim="email"

email_domains='*'

cookie_secure="true"

cookie_httponly="true"

cookie_name="oauth2_cookie"

cookie_samesite="lax"

cookie_csrf_per_request="true"

cookie_csrf_expire="15m0s"

cookie_expire="6h0m0s"

cookie_refresh="1h0m0s"

cookie_domains=".indeed.local"

force_https="true"

ssl_upstream_insecure_skip_verify="true"

ssl_insecure_skip_verify="true"

https_address=":4180"

tls_cert_file="/etc/ssl/certs/indeed.crt"

tls_key_file="/etc/ssl/certs/indeed.key"

tls_min_version="TLS1.2"

code_challenge_method="S256"

errors_to_info_log="true"

Таким образом, oauth2-proxy будет общаться с Indeed IdP, через nginx, т.к. потребуется пересылка данных, в том числе, через браузер пользователя.

Параметр “custom_sign_in_logo” - опционален, может ссылаться на любую картинку с логотипом.

Параметр “cookie_secret”- сгенерирован командой 

openssl rand -base64 22

где 22 - число символов

Поместим файлы сертификата по пути /etc/ssl/certs/

/etc/ssl/certs/indeed.crt
/etc/ssl/certs/indeed.key

    Примечание - В составе indeed.crt, также должна быть вся цепочка сертификатов, во избежании проблем с nginx.

Для CA файла домена, в debian потребуются доп. действия:

apt install easy-rsa
apt install ca-certificates

CA файл поместим по пути

/usr/local/share/ca-certificates/ca.crt

и добавим его в хранилище

update-ca-certificates

Создадим пользователя для запуска службы

export PATH="$PATH:/sbin:/usr/sbin:usr/local/sbin"

useradd -d /dev/null -s /usr/sbin/nologin oauth2-proxy

или

sudo adduser oauth2-proxy --system --no-create-home

Добавим группу

groupadd oauth2-proxy

usermod -a -G oauth2-proxy oauth2-proxy

Выдадим права на каталог

chmod -R 775 /opt/oauth2-proxy

chown -R oauth2-proxy:oauth2-proxy /opt/oauth2-proxy/

chmod 755 /etc/oauth2-proxy.cfg

Создадим службу oauth2-proxy

sudo systemctl edit --full --force oauth2-proxy.service

[Unit]

Description=reverse proxy

[Service]

Type=simple

User=oauth2-proxy

WorkingDirectory=/opt/oauth2-proxy

EnvironmentFile=/etc/oauth2-proxy.cfg

ExecStart=/opt/oauth2-proxy/oauth2-proxy  --config=/etc/oauth2-proxy.cfg

Restart=always

ExecReload=/bin/kill -s HUP $MAINPID

KillMode=process

[Install]

WantedBy=multi-user.target

systemctl daemon-reload
systemctl enable oauth2-proxy
systemctl start oauth2-proxy

Просмотреть файл конфигурации службы oauth2-proxy, можно командой:
sudo nano /etc/systemd/system/oauth2-proxy.service

Настройка NGINX сервера

Переходим к серверу nginx.indeed.local

Используется ОС Ubuntu 22.04 LTS

Обновляем установленные пакеты:

apt-get update -y && apt-get upgrade -y && apt-get dist-upgrade -y

Устанавливаем nginx:

sudo apt install nginx -y

Подготовим файлы сертификатов для работы.

Каталог для хранения:

mkdir /etc/nginx/ssl

Сохраним файлы 

/etc/nginx/ssl/proxy.crt;
/etc/nginx/ssl/proxy_private.key;

где:

 proxy.crt - открытая часть сертификата,

 proxy_private.key - приватный ключ сертификата без пароля.

Сгенерируйте свой файл dhparam, для алгоритмов семейства DHE/EDH (рекомендуемая минимальная длина ключа 4096 бит)

Этот процесс займёт несколько минут. Ключи DH будут помещены в /etc/nginx/ssl/dhparam.pem

sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096

или скачайте общедоступный 2048 битный

wget -O /etc/nginx/ssl/dhparam.pem https://ssl-config.mozilla.org/ffdhe2048.txt

Создадим файл настроек:

nano /etc/nginx/sites-available/rdweb.indeed.local

С Содержимым:

#ddos protect

limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;

#end ddos protect

#proxy_cache_path /cache/validate levels=1:2 keys_zone=auth_cache:10m max_size=128m inactive=30m use_temp_path=off;

server {

    listen 80;

    server_name rdweb.indeed.local www.rdweb.indeed.local indeed.local;

    #return 301 https://$server_name$request_uri;

    return 301 https://$server_name/RDWeb/webclient/;

}

server {

large_client_header_buffers 8 64k;

       proxy_buffering on;

proxy_buffer_size   64k;

       proxy_buffers   8 64k;

       proxy_busy_buffers_size   64k;

#proxy tune

proxy_max_temp_file_size 2048m;

proxy_temp_file_write_size 64k;

#end proxy tune

        listen 443 ssl;

        # http2;

        server_name rdweb.indeed.local www.rdweb.indeed.local indeed.local;

        #logs

        access_log  /var/log/nginx/access.log ;

        error_log  /var/log/nginx/error.log ;

        # SSL config

        ssl_certificate /etc/nginx/ssl/proxy.crt;

        ssl_certificate_key /etc/nginx/ssl/proxy_private.key;

        ssl_session_timeout 1d;

        ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions

        ssl_session_tickets off;

        # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam

        ssl_dhparam /etc/nginx/ssl/dhparam.pem;

        # intermediate configuration

        ssl_protocols TLSv1.2;

        # TLSv1.3;

ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

 ssl_prefer_server_ciphers off;

        # HSTS (ngx_http_headers_module is required) (63072000 seconds)

        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

        #Expect-CT

        add_header Expect-CT 'enforce; max-age=604800';

        #header The anti-clickjacking X-Frame-Options SAMEORIGIN / DENY

        add_header X-Frame-Options SAMEORIGIN always;

        #X-XSS-Protection

        add_header X-XSS-Protection "1; mode=block";

        #X-Content-Type-Options

        add_header X-Content-Type-Options nosniff;

 add_header Content-Security-Policy      "connect-src 'self' ;

                                                font-src 'self' ;

                                                frame-src 'self' ;

                                                script-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                style-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                img-src 'self' ;

                                                manifest-src 'self';

                                                media-src 'self';

                                                object-src 'self';

                                                worker-src 'self';

                                                frame-ancestors 'self';

                                                form-action 'self';" always;

        # OCSP stapling

        ssl_stapling on;

        ssl_stapling_verify on;

#скрываем на чем запущено

        proxy_hide_header X-Powered-By;

        location /am/idp {

        #ddos

        limit_req zone=one burst=10 nodelay;

        limit_req_status 444;

        #end ddos

        # HSTS (ngx_http_headers_module is required) (63072000 seconds)

        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

        #Expect-CT

        add_header Expect-CT 'enforce; max-age=604800';

        #header The anti-clickjacking X-Frame-Options SAMEORIGIN / DENY

        add_header X-Frame-Options SAMEORIGIN always;

        #X-XSS-Protection

        add_header X-XSS-Protection "1; mode=block";

        #X-Content-Type-Options

        add_header X-Content-Type-Options nosniff;

        add_header Referrer-Policy "no-referrer-when-downgrade" always;

        ### This is the header referenced above ###

        add_header Content-Security-Policy      "connect-src 'self' ;

                                         font-src 'self' ;

                                         frame-src 'self' ;

                                         script-src 'self' 'unsafe-inline' 'unsafe-eval';  

                                         style-src 'self' 'unsafe-inline' 'unsafe-eval';

                                         img-src 'self' data: ;

                                         manifest-src 'self';

                                         media-src 'self';

                                         object-src 'self';

                                         worker-src 'self';

frame-ancestors 'self';

form-action 'self';" always;

        add_header X-Robots-Tag none;

        add_header X-Download-Options noopen;

        add_header X-Permitted-Cross-Domain-Policies none;

        proxy_read_timeout 120s;

        proxy_send_timeout 120s;

        proxy_connect_timeout 120s;

        send_timeout 120s;

        proxy_redirect     off;

        proxy_set_header   Host                 $host;

        proxy_set_header X-Forwarded-Server     $host;

        proxy_set_header X-Real-IP              $remote_addr;

        proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;

        proxy_set_header X-Forwarded-Host       $host;

        proxy_set_header X-Forwarded-Proto https;

        proxy_set_header X-Forwarded-Port 443;

        proxy_pass https://am1.indeed.local$request_uri;

        proxy_ssl_session_reuse on;

        proxy_ssl_protocols           TLSv1.2;

        resolver 10.10.10.11;

#скрываем на чем запущено

        proxy_hide_header X-Powered-By;

        }

        location /oauth2/ {

        proxy_pass       https://oauth.indeed.local:4180;

        proxy_set_header Host                    $host;

        proxy_set_header X-Real-IP               $remote_addr;

        proxy_set_header X-Scheme                $scheme;

        proxy_set_header X-Auth-Request-Redirect $request_uri;

resolver 10.10.10.11;

        #ddos

        limit_req zone=one burst=10 nodelay;

        limit_req_status 444;

        #end ddos

        # HSTS (ngx_http_headers_module is required) (63072000 seconds)

        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

        #Expect-CT

        add_header Expect-CT 'enforce; max-age=604800';

        #header The anti-clickjacking X-Frame-Options SAMEORIGIN / DENY

        add_header X-Frame-Options SAMEORIGIN always;

        #X-XSS-Protection

        add_header X-XSS-Protection "1; mode=block";

        #X-Content-Type-Options

        add_header X-Content-Type-Options nosniff;

        add_header Referrer-Policy "no-referrer-when-downgrade" always;

        ### This is the header referenced above ###

        add_header Content-Security-Policy      "connect-src 'self' ;

                                                font-src 'self' ;

                                                frame-src 'self' ;

                                                script-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                style-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                img-src 'self' https://download.indeed-company.ru;

                                                manifest-src 'self';

                                                media-src 'self';

                                                object-src 'self';

                                                worker-src 'self';

                                                frame-ancestors 'self';

                                                form-action 'self';" always;

        add_header X-Robots-Tag none;

        add_header X-Download-Options noopen;

        add_header X-Permitted-Cross-Domain-Policies none;

        proxy_read_timeout 120s;

        proxy_send_timeout 120s;

        proxy_connect_timeout 120s;

        send_timeout 120s;

#скрываем на чем запущено

        proxy_hide_header X-Powered-By;

        }

        location = /oauth2/auth {

        proxy_pass       https://oauth.indeed.local:4180;

 resolver 10.10.10.11;

        proxy_set_header Host             $host;

        proxy_set_header X-Real-IP        $remote_addr;

        proxy_set_header X-Scheme         $scheme;

        # nginx auth_request includes headers but not body

        proxy_set_header Content-Length   "";

        proxy_pass_request_body           off;

#скрываем на чем запущено

        proxy_hide_header X-Powered-By;

        }

        #аутентификация и меню доступных приложений

        location /RDWeb/webclient {

        #oauth2

        #старт требование аутентификации

        auth_request /oauth2/auth;

        error_page 401 = /oauth2/sign_in;

        #auth_request_set $email  $upstream_http_x_auth_request_email;

        #proxy_set_header X-Email $email;

        auth_request_set $user  $upstream_http_x_auth_request_user;

        proxy_set_header X-User  $user;

        auth_request_set $token  $upstream_http_x_auth_request_access_token;

        proxy_set_header X-Access-Token $token;

        auth_request_set $auth_cookie $upstream_http_set_cookie;

        add_header Set-Cookie $auth_cookie;

        #конец требование аутентификации

        #ddos

        limit_req zone=one burst=20 nodelay;

        limit_req_status 444;

        #end ddos

        # HSTS (ngx_http_headers_module is required) (63072000 seconds)

        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

        #Expect-CT

        add_header Expect-CT 'enforce; max-age=604800';

        #header The anti-clickjacking X-Frame-Options SAMEORIGIN / DENY

        add_header X-Frame-Options SAMEORIGIN always;

        #X-XSS-Protection

        add_header X-XSS-Protection "1; mode=block";

        #X-Content-Type-Options

        add_header X-Content-Type-Options nosniff;

        add_header Referrer-Policy "no-referrer-when-downgrade" always;

        ### This is the header referenced above ###

        add_header Content-Security-Policy      "connect-src 'self' ;

                                                font-src 'self' ;

                                                frame-src 'self' ;

                                                script-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                style-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                img-src 'self' ;

                                                manifest-src 'self';

                                                media-src 'self';

                                                object-src 'self';

                                                worker-src 'self';

                                                frame-ancestors 'self';

                                                form-action 'self';" always;

        add_header X-Robots-Tag none;

        add_header X-Download-Options noopen;

        add_header X-Permitted-Cross-Domain-Policies none;

        proxy_read_timeout 120s;

        proxy_send_timeout 120s;

        proxy_connect_timeout 120s;

        send_timeout 120s;

        proxy_redirect     off;

        proxy_set_header   Host                 $host;

        proxy_set_header X-Forwarded-Server     $host;

        proxy_set_header X-Real-IP              $remote_addr;

        proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;

        proxy_set_header X-Forwarded-Host       $host;

        proxy_pass https://rdweb.indeed.local/RDWeb/webclient/;

        proxy_ssl_session_reuse on;

        proxy_ssl_protocols           TLSv1.2;

        resolver 10.10.10.11;

#скрываем на чем запущено

        proxy_hide_header X-Powered-By;

        }

        #удаленка по html5

        location ~^/remoteDesktopGateway(.*)$  {

        #oauth2

        #старт требование аутентификации

        auth_request /oauth2/auth;

        error_page 401 = /oauth2/sign_in;

        #auth_request_set $email  $upstream_http_x_auth_request_email;

        #proxy_set_header X-Email $email;

        auth_request_set $user  $upstream_http_x_auth_request_user;

        proxy_set_header X-User  $user;

        auth_request_set $token  $upstream_http_x_auth_request_access_token;

        proxy_set_header X-Access-Token $token;

        auth_request_set $auth_cookie $upstream_http_set_cookie;

        add_header Set-Cookie $auth_cookie;

        #конец требование аутентификации

        #ddos

        limit_req zone=one burst=10 nodelay;

        limit_req_status 444;

        #end ddos

        # HSTS (ngx_http_headers_module is required) (63072000 seconds)

        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

        #Expect-CT

        add_header Expect-CT 'enforce; max-age=604800';

        #header The anti-clickjacking X-Frame-Options SAMEORIGIN / DENY

        add_header X-Frame-Options SAMEORIGIN always;

        #X-XSS-Protection

        add_header X-XSS-Protection "1; mode=block";

        #X-Content-Type-Options

        add_header X-Content-Type-Options nosniff;

        add_header Referrer-Policy "no-referrer-when-downgrade" always;

        ### This is the header referenced above ###

        add_header Content-Security-Policy      "connect-src 'self' ;

                                                font-src 'self' ;

                                                frame-src 'self' ;

                                                script-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                style-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                img-src 'self' blob: data: ;

                                                manifest-src 'self';

                                                media-src 'self';

                                                object-src 'self';

                                                worker-src 'self';

                                                frame-ancestors 'self';

                                                form-action 'self';" always;

        add_header X-Robots-Tag none;

        add_header X-Download-Options noopen;

        add_header X-Permitted-Cross-Domain-Policies none;

        proxy_read_timeout 120s;

        proxy_send_timeout 120s;

        proxy_connect_timeout 120s;

        send_timeout 120s;

        proxy_redirect     off;

        proxy_set_header   Host                 $host;

        proxy_set_header X-Forwarded-Server     $host;

        proxy_set_header X-Real-IP              $remote_addr;

        proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;

        proxy_set_header X-Forwarded-Host       $host;

        #proxy_set_header X-Forwarded-Proto https;

        #proxy_set_header X-Forwarded-Port 443;

        proxy_pass https://rdweb.indeed.local$request_uri;

        #proxy_pass $scheme://rdweb.indeed.local/RDWeb/webclient/;

        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;

        proxy_set_header Connection "upgrade";

        #proxy_read_timeout 86400;

        proxy_ssl_session_reuse on;

        proxy_ssl_protocols           TLSv1.2;

        resolver 10.10.10.11;

#скрываем на чем запущено

        proxy_hide_header X-Powered-By;

        }

        #классический rdweb

        location /RDWeb {

        #ddos

        limit_req zone=one burst=20 nodelay;

        limit_req_status 444;

        #end ddos

        # HSTS (ngx_http_headers_module is required) (63072000 seconds)

        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

        #Expect-CT

        add_header Expect-CT 'enforce; max-age=604800';

        #header The anti-clickjacking X-Frame-Options SAMEORIGIN / DENY

        add_header X-Frame-Options SAMEORIGIN always;

        #X-XSS-Protection

        add_header X-XSS-Protection "1; mode=block";

        #X-Content-Type-Options

        add_header X-Content-Type-Options nosniff;

        add_header Referrer-Policy "no-referrer-when-downgrade" always;

        ### This is the header referenced above ###

        add_header Content-Security-Policy      "connect-src 'self' ;

                                                font-src 'self' ;

                                                frame-src 'self' ;

                                                script-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                style-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                img-src 'self' ;

                                                manifest-src 'self';

                                                media-src 'self';

                                                object-src 'self';

                                                worker-src 'self';

                                                frame-ancestors 'self';

                                                form-action 'self';" always;

        add_header X-Robots-Tag none;

        add_header X-Download-Options noopen;

        add_header X-Permitted-Cross-Domain-Policies none;

        proxy_read_timeout 120s;

        proxy_send_timeout 120s;

        proxy_connect_timeout 120s;

        send_timeout 120s;

        proxy_redirect     off;

        proxy_set_header   Host                 $host;

        proxy_set_header X-Forwarded-Server     $host;

        proxy_set_header X-Real-IP              $remote_addr;

        proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;

        proxy_set_header X-Forwarded-Host       $host;

        proxy_set_header X-Forwarded-Proto https;

        proxy_set_header X-Forwarded-Port 443;

        proxy_pass https://rdweb.indeed.local/RDWeb/;

        proxy_ssl_session_reuse on;

        proxy_ssl_protocols           TLSv1.2;

        resolver 10.10.10.11;

#скрываем на чем запущено

        proxy_hide_header X-Powered-By;

        }

#поведение по умолчанию

        location / {

        #ddos

        #limit_req zone=one burst=5 nodelay;

        #limit_req_status 444;

        #end ddos

        # HSTS (ngx_http_headers_module is required) (63072000 seconds)

        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

        #Expect-CT

        add_header Expect-CT 'enforce; max-age=604800';

        #header The anti-clickjacking X-Frame-Options SAMEORIGIN / DENY

        add_header X-Frame-Options SAMEORIGIN always;

        #X-XSS-Protection

        add_header X-XSS-Protection "1; mode=block";

        #X-Content-Type-Options

        add_header X-Content-Type-Options nosniff;

        add_header Content-Security-Policy      "connect-src 'self' ;

                                                font-src 'self' ;

                                                frame-src 'self' ;

                                                script-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                style-src 'self' 'unsafe-inline' 'unsafe-eval';

                                                img-src 'self' ;

                                                manifest-src 'self';

                                                media-src 'self';

                                                object-src 'self';

                                                worker-src 'self';

                                                frame-ancestors 'self';

                                                form-action 'self';" always;

        #переадресуем на страницу входа

        return 301 https://$server_name/RDWeb/webclient/;

#скрываем на чем запущено

        proxy_hide_header X-Powered-By;

        }

}

В приведенном файле конфигурации, требуется аутентификация через IdP модуль, для двух URL

/RDWeb/webclient - Основное окно входа в webclient

 ~^/remoteDesktopGateway(.*)$ - маска URL адреса, для работы RDP через webclient

Для /RDWeb запроса IdP не происходит (в целях примера работы).

Для добавления требования аутентификации, в нужный location добавляется

#старт требование аутентификации

        auth_request /oauth2/auth;

        error_page 401 = /oauth2/sign_in;

        #auth_request_set $email  $upstream_http_x_auth_request_email;

        #proxy_set_header X-Email $email;

        auth_request_set $user  $upstream_http_x_auth_request_user;

        proxy_set_header X-User  $user;

        auth_request_set $token  $upstream_http_x_auth_request_access_token;

        proxy_set_header X-Access-Token $token;

        auth_request_set $auth_cookie $upstream_http_set_cookie;

        add_header Set-Cookie $auth_cookie;

#конец требование аутентификации

Который требует наличия куки аутентификации.

Для пересылки данных аутентификации, в пределах oauth2-proxy и ответа с Indeed IdP, используются:

location /oauth2/

location = /oauth2/auth

Создадим символьную ссылку

ln -s /etc/nginx/sites-available/rdweb.indeed.local /etc/nginx/sites-enabled/rdweb.indeed.local

Удалим default страницу 

rm /etc/nginx/sites-available/default 

rm /etc/nginx/sites-enabled/default  

Проверим файл конфигурации

nginx -t

Отключаем версию nginx

sudo nano /etc/nginx/nginx.conf

добавить 

server_tokens off;

В случае отсутствия ошибок, перезапустим службу и добавим в автозагрузку

systemctl restart nginx

systemctl enable nginx

Настройка IDP сервера

Переходим на am1.indeed.local, для настройки Indeed IdP

В файле

C:\inetpub\wwwroot\am\idp\app-settings.json

Добавляем настройку провайдера для работы с oauth2-proxy

  ,{

        "ClientId": "nginx_oauth",

        "ClientSecret": "Qq123456",

        "DisplayName": "nginx proxy auth request oauth2",

        "Permissions": [

          "ept:authorization",

          "ept:device",

          "ept:introspection",

          "ept:logout",

          "ept:revocation",

          "ept:token",

          "gt:authorization_code",

          "gt:client_credentials",

          "gt:urn:ietf:params:oauth:grant-type:device_code",

          "gt:implicit",

          "gt:password",

          "gt:refresh_token",

          "rst:code",

          "rst:code id_token",

          "rst:code id_token token",

          "rst:code token",

          "rst:id_token",

          "rst:id_token token",

          "rst:none",

          "rst:token",

          "scp:address",

          "scp:email",

          "scp:phone",

          "scp:profile",

          "scp:roles"

        ],

        "RedirectUris": [

"https://rdweb.indeed.local/oauth2/callback"

        ]

      }

где 

"ClientId": "nginx_oauth" - ID oidc клиента, указываемый в client_id на стороне oauth2-proxy

"ClientSecret": "Qq123456" - общий ключ с client_secret на стороне oauth2-proxy

"RedirectUris" - адрес, на который возвращается ответ от IdP, через браузер пользователя

Далее, в том же файле, добавим отправку email адреса в ответе

в секции “CustomAttributes

добавим:

{

        "ServiceProvider": "nginx_oauth",

        "Attributes": [

          {

            "Name": "email",

            "UserNameFormat": "Email"

          }

        ]

      }

Убедимся, что указан сертификат для работы с oidс, для подписи ответа

"OIDC": {

    "IDP": {

      "CertificateThumbprint": "d2846fb4d27f1865418501618dbbe51d9e4aae42"

    },

где “d2846fb4d27f1865418501618dbbe51d9e4aae42” - сертификат в локальном хранилище системы.

Сохраняем файл.

В файл C:\inetpub\wwwroot\am\idp\Web.config

Вносим изменения:

<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <system.webServer>

    <!-- Removing server header settings for IIS versions >=10.0

             for earlier versions use IIS extension "URL Rewrite"-->

       <security>

<requestFiltering removeServerHeader="true">

  <verbs>

<add verb="TRACE" allowed="false" />

<add verb="TRACK" allowed="false" />

  </verbs>

</requestFiltering>

        </security>

    <httpProtocol>

      <customHeaders>

        <add name="X-Frame-Options" value="SAMEORIGIN" />

        <remove name="X-Powered-By" />

      </customHeaders>

    </httpProtocol>

    <handlers>

      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />

    </handlers>

    <aspNetCore processPath="dotnet" arguments=".\AM.IDP.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />

  </system.webServer>

  <system.web>

    <httpCookies httpOnlyCookies="true" requireSSL="true"/>

  </system.web>

</configuration>



Перезапускаем IIS сервер.

Проверяем работу.

При переходе по ссылке:

https://rdweb.indeed.local/RDWeb/webclient/

Происходит внутреннее перенаправление на страницу входа






Настройка Redis DB

Используем БД Redis для хранения пары id-сессии.секрет, вместо хранения секрета в куки.

В качестве примера, будем использовать автономный вариант Redis (возможна настройка кластера Redis Sentinel), установленный на том же сервере, что и Oauth2.

Установка

sudo apt install redis-server -y

Зададим систему управления для службы Redis

sudo nano /etc/redis/redis.conf

меняем 

supervised no

на

supervised systemd

Т.к. мы предполагаем локальную установку redis, и к ней доступ должен иметь только oauth2, то убедимся, что подключаться можно только локально

sudo nano /etc/redis/redis.conf

должна быть привязка только 

bind 127.0.0.0 ::1

Защитим подключение к Redis, с помощью мастер пароля.

для этого, сгенерируем случайный пароль

openssl rand 128 | openssl base64 -A

и добавим пароль в параметр requirepass 

перезапускаем службу

sudo systemctl restart redis.service

добавляем в автозагрузку

sudo systemctl enable redis-server.service

Сконфигурируем Oauth2-Proxy, на работу с Redis

sudo nano /etc/oauth2-proxy.cfg

Оставляем cookie_secret, т.к. этот параметр является обязательным для конфигурационного файла oauth2-proxy

При этом, согласно документации, секреты для куки будут храниться в Redis:

{CookieName}-{ticketID}.{secret}

Where:

  • The CookieName is the OAuth2 cookie name (_oauth2_proxy by default)
  • The ticketID is a 128 bit random number, hex-encoded
  • The secret is a 128 bit random number, base64url encoded (no padding). The secret is unique for every session.
  • The pair of {CookieName}-{ticketID} comprises a ticket handle, and thus, the redis key to which the session is stored. 

добавляем 3 строки 

session_store_type="redis"

redis_password="8wh2Ahz8gIo43ENGiX7rVPhtwU6+5J4HRUEyg6OGD2vzisVaNXOlsy2BbIH90Ksjck9yRpd1WvBKkdN37UzOSC0BquDTkdyA/PLL0Nz8mHdHiXZgh2hg16dGQHBYw1xGQzJp13KB5LRJRXRblOQu2fwWnXeVAzP7YpQEkwgamxY="

redis_connection_url="redis://localhost:6379"




Перезапускаем Oauth2

systemctl start oauth2-proxy

Проверяем.

Размер куки, передаваемых клиенту, значительно уменьшается

в DB Redis появляется соответствующая запись



Вложения 
 
 OAuth_configs.zip (1.63 кБ)
 Nginx_configs.zip (3.39 кБ)
 IDP_config.zip (2.15 кБ)
 RedisDB_config.zip (29.30 кБ)
(0 голос(а))
Эта статья полезна
Эта статья бесполезна

Комментарии (0)
Добавить новый комментарий
 
 
Полное имя:
Email:
Комментарии: