- tocdepth
2
Защита сайта и API
Для защиты сайта и API нужно:
Создание Keycloak-сервера для аутентификации пользователей
Чтобы настроить аутентификацию на сайте, нужно создать провайдера, который будет удостоверять пользователей. В качестве примера будет настроен экземпляр Keycloak.
Для этого понадобится виртуальная машина, на которую будет установлен провайдер аутентификации Keycloak.
Создание виртуальной машины
Создайте виртуальную машину с публичным IP-адресом, по которому пользователи смогут перейти и выполнить аутентификацию:
В списке сервисов выберите Elastic Cloud Server.
Нажмите Create ECS в правом верхнем углу.
В поле AZ выберите Random.
Выберите конфигурацию с 2 vCPUs и 4 GiB. Например, «s6.large.2» или «s7n.large.2».
В поле Image выберите .
Нажмите Next: Configure Network.
В поле Network выберите виртуальную сеть и подсеть, в которой будет находиться виртуальная машина.
В поле Security Group нажмите Create Security Group.
На новой вкладке нажмите Create Security Group.
В поле Name введите keycloak.
В поле Template выберите Custom — шаблон без дополнительных настроек.
Нажмите OK.
Нажмите Manage Rule.
Перейдите во вкладку Inbound Rule.
Нажмите Add Rule.
В поле Priority введите
1
.В поле Protocol & Port введите
8443
. По этому порту будет открыт доступ к серверу из интернета.Нажмите OK.
Вернитесь на предыдущую вкладку, в которой создавали виртуальную машину.
Обновите список групп безопасности и выберите keycloak.
В поле EIP выберите Auto assign.
Нажмите Next: Configure Advanced Settings.
В поле ECS Name укажите название виртуальной машины.
Введите и повторите пароль для подключения к серверу.
Нажмите Next: Confirm.
Проверьте конфигурацию виртуальной машины.
Нажмите Apply Now.
Сервер создан, настроен и готов к работе.
Установка Keycloak
Чтобы установить Keycloak на сервер:
В списке сервисов выберите Elastic Cloud Server.
Напротив виртуальной машины, которую вы создали ранее, нажмите Remote Login.
В консоли введите:
root
— имя пользователя;пароль, указанный при создании сервера.
Скачайте Docker:
curl -fsSL https://get.docker.com -o get-docker.sh
Установите Docker:
sh get-docker.sh
Сгенерируйте самоподписанный сертификат:
openssl req -newkey rsa:2048 -nodes -keyout server.key.pem -x509 -days 3650 -out server.crt.pem
Смените права доступа к файлу
server.key.pem
:chmod 755 server.key.pem
Запустите контейнер с Keycloak:
docker run -d --name keycloak -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin -e KC_HTTPS_CERTIFICATE_FILE=/opt/keycloak/conf/server.crt.pem -e KC_HTTPS_CERTIFICATE_KEY_FILE=/opt/keycloak/conf/server.key.pem -v $PWD/server.crt.pem:/opt/keycloak/conf/server.crt.pem -v $PWD/server.key.pem:/opt/keycloak/conf/server.key.pem -p 8443:8443 quay.io/keycloak/keycloak:19.0.1 start-dev
Keycloak установлен.
Настройка Keycloak
В списке сервисов выберите Elastic Cloud Server.
Скопируйте EIP — публичный IP-адрес виртуальной машины, на которую вы установили Keycloak.
Чтобы попасть в консоль управления Keycloak, перейдите по адресу:
https://ip-адрес-сервера:8443/admin
Например, если IP-адрес сервера
203.0.113.1
, нужно перейти по:https://203.0.113.1:8443/admin
Так как на сервере установлен самоподписанный SSL-сертификат, при переходе возникнет уведомление «Подключение не защищено». Чтобы попасть в Keycloak, нажмите
.Войдите в Keycloak:
Username or email —
admin
;Password —
admin
.
Перейдите в раздел Clients в левом меню.
Нажмите Create Client.
В поле Client Type выберите OpenID Connect.
Придумайте и введите в поле Client ID идентификатор для сайта, который находится в OBS.
Нажмите Next.
Активируйте параметр Client authentication.
Активируйте опцию Implicit flow.
Нажмите Save.
Введите адрес сайта, который загружен в OBS, в следующие поля:
Root URL
Home URL
Valid redirect URIs
Чтобы узнать адрес сайта, откройте страницу сервиса OBS и нажмите на название бакета, в котором находится сайт. Затем перейдите в раздел
.Нажмите Save.
Сервер аутентификации Keycloak создан.
Аутентификация на сайте
Теперь аутентификацию нужно добавить на сайт. Она будет выполняться с помощью сервера Keycloak.
В разделе Публикация статического веб-сайта для работы с API вы уже загрузили сайт, который работает с API, но он не поддерживает аутентификацию пользователей. Нужно загрузить новый сайт с поддержкой аутентификации через Keycloak. Для размещения файлов сайта используйте тот же бакет, который вы создавали ранее.
Порядок действий при загрузке точно такой же, как и ранее. Отличаются файлы сайта, которые нужно загрузить.
Публикация сайта
Чтобы опубликовать сайт в OBS:
Скачайте и распакуйте архив с файлами сайта.
Откройте файл
settings.json
.Укажите настройки в конфигурационном файле:
api_url
— адрес API. Узнать его можно в разделе Узнать API URL.oauth_endpoint
— адрес сервера Keycloak. В URL заменитеexample
на IP-адрес вашего сервера Keycloak. Это адрес виртуальной машины, которую вы создали в разделе Настройка Keycloak.client_id
— Client ID в Keycloak. Он указывался в разделе Настройка Keycloak. Узнать Client ID можно на странице Keycloak по адресуhttps://ip-адрес-сервера:8443/admin
в разделе Clients.response_type
— без изменений.scope
— без изменений.nonce
— без изменений.redirect_url
— адрес вашего сайта в Object Storage Service. Узнать URL можно в разделе .
Сохраните изменения в файле.
Откройте ранее созданный бакет и перейдите в раздел Objects в правом меню.
Выделите и удалите все ранее загруженные файлы в бакете.
Нажмите Upload Object.
В поле Object Permission выберите Public Read.
Перетащите содержимое каталога
react-js-oauth-spa
в форму загрузки OBS.Нажмите Upload.
Примечание
Если у вас возникли проблемы во время загрузки файлов сайта, воспользуйтесь OBS Browser.
Перейдите в раздел
.Перейдите по адресу, который указан в поле Hosted Website URL.
Откроется страница аутентификации Keycloak. Введите:
логин —
admin
;пароль —
admin
.
Нажмите Sign In. После успешной аутентификации вы будете перенаправлены обратно на сайт, а в правом верхнем углу появится название аккаунта.
Проверьте добавление, отображение и удаление записей на сайте.
Сайт опубликован. Теперь каждый посетитель сайта должен пройти аутентификацию. При этом API все равно доступен любому анонимному пользователю. Чтобы запретить анонимный доступ, нужно настроить аутентификацию в API.
Аутентификация в API
Для аутентификации в API нужно создать отдельную функцию валидации запросов к API.
API Gateway будет вызывать ее при обращении к API.
Функция будет проверять входящий access_token
и разрешать обращение к API только валидным пользователям.
API Gateway умеет кешировать ответ от функции валидации. Это позволяет не вызывать функцию валидации при каждом обращении к API.
Можно воспользоваться готовой функцией авторизации или создать самостоятельно.
Использование готовой функции
Скачайте архив с файлами функции.
Внимание
По умолчанию Node.js не обрабатывает самоподписанный сертификат, который используется в функции аутентификации. Чтобы аутентификация работала несмотря на самоподписанный сертификат, в код добавлена строка:
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
. Это небезопасно, но допустимо в рамках практической работы.В списке сервисов выберите FunctionGraph.
Нажмите Create Function в правом верхнем углу.
В поле Function name укажите название функции, например «API-AUTH».
В списке Runtime выберите Node.js 12.13.
В поле Handler нужно указать название файла и название функции. Если использовали код из примера, оставьте значение по умолчанию.
В поле Code Entry Mode выберите Upload ZIP и загрузите архив с функцией.
Нажмите Create Function.
Функция загружена в FunctionGraph.
Для работы функции нужно указать переменные окружения. Для этого:
В разделе Functions сервиса FunctionGraph нажмите на название загруженной ранее функции.
Перейдите во вкладку Configuration.
В разделе Environment Variables нажмите Add Now и добавьте два параметра:
Идентификатор клиента:
Key —
audience
;Value —
account
.
Адрес провайдера, выписавшего токен:
Key —
issuer
;Value — адрес сервера Keycloak
https://ip-адрес-сервера:8443/realms/master
.
Нажмите Save напротив каждого параметра.
В правом верхнем углу нажмите Save.
Функция загружена и настроена. Перейдите к разделу Настройка API Gateway.
Ручное создание и загрузка функции авторизации
Создайте каталог для хранения кода функции:
mkdir catalog-name
Перейдите в созданный каталог:
cd catalog-name
Инициализируйте проект:
npm init -y
Установите зависимости:
npm install jsonwebtoken
Создайте файл
index.js
:touch index.js
Добавьте в файл
index.js
код:exports.handler = async (event, context) => { const jwt = require('jsonwebtoken'); const request = require('request'); const util = require('util'); const requestWrapper = util.promisify(request); const audience = process.env.audience; const issuer = process.env.issuer; process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; let body = { status: "deny" }; try { const oauthConfig = await requestWrapper(`${issuer}/.well-known/openid-configuration`); const keyUrl = JSON.parse(oauthConfig.body).jwks_uri; const keys = await requestWrapper(keyUrl); const key = JSON.parse(keys.body).keys[0].x5c[0]; const signingCertificate = `-----BEGIN CERTIFICATE-----\n${key}\n-----END CERTIFICATE-----`; //verify token const token = event.headers["x-access-token"]; const jwttoken = jwt.verify(token, signingCertificate, {audience: audience, issuer: issuer}); body.status = "allow"; } catch (e) { console.log(e); } const output = { "statusCode": 200, "body": JSON.stringify(body) } return output; }
Внимание
По умолчанию Node.js не обрабатывает самоподписанный сертификат, который используется в функции аутентификации. Чтобы аутентификация работала несмотря на самоподписанный сертификат, в код добавлена строка:
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
. Это небезопасно, но допустимо в рамках практической работы.Создайте ZIP-архив с содержимым каталога
catalog-name
. Архив должен содержать файлыindex.js
,package.jsos
,package-lock.json
и каталогnode_modules
.
Функция создана. Чтобы загрузить ее в FunctionGraph:
В списке сервисов выберите FunctionGraph.
Нажмите Create Function в правом верхнем углу.
В поле Function name укажите название функции, например «API-AUTH».
В списке Runtime выберите Node.js 12.13.
В поле Handler нужно указать название файла и название функции. Если использовали код из примера, оставьте значение по умолчанию.
В поле Code Entry Mode выберите Upload ZIP и загрузите архив с функцией.
Нажмите Create Function.
Функция загружена в FunctionGraph.
Для работы функции нужно указать переменные окружения. Для этого:
В разделе Functions сервиса FunctionGraph нажмите на название загруженной ранее функции.
Перейдите во вкладку Configuration.
В разделе Environment Variables нажмите Add Now и добавьте два параметра:
Идентификатор клиента:
Key —
audience
;Value —
account
.
Адрес провайдера, выписавшего токен:
Key —
issuer
;Value — адрес сервера Keycloak
https://ip-адрес-сервера:8443/realms/master
.
Нажмите Save напротив каждого параметра.
В правом верхнем углу нажмите Save.
Функция загружена и настроена. Перейдите к разделу Настройка API Gateway.
Настройка API Gateway
API Gateway нужно настроить на использование функции валидации. Для этого сначала нужно создать Custom Authorizer на уровне API Gateway:
В списке сервисов выберите API Gateway.
Перейдите в раздел
.Нажмите Create Custom Authorizer в правом верхнем углу.
В поле Name укажите название.
В поле Type выберите Frontend.
В поле Function URN нажмите Select и выберите ранее созданную функцию авторизации.
Нажмите OK.
Custom Authorizer создан.
Теперь нужно настроить авторизацию для функций.
access_token
будет передаваться с сайта в каждом запросе в заголовке X-Access-Token.
Авторизацию нужно настроить для каждого API: для GET, POST и DELETE. Повторите инструкцию ниже для каждого из методов.
В списке сервисов выберите API Gateway.
Перейдите в раздел
.Напротив нужного метода нажмите Edit.
В поле Security Authentication выберите Custom.
В поле Custom Authorizer выберите созданный ранее Custom Authorizer.
Нажмите Next.
Нажмите Add Input Parameter.
В поле Name введите X-Access-Token.
В поле Location выберите Header.
В поле Type выберите String.
Нажмите OK.
Нажмите Finish.
Нажмите Publish API.
Нажмите Publish.
Когда для каждого API настроена авторизация, запросы через Postman работать перестанут. Они не будут содержать нужный заголовок. Если же вручную добавить заголовок и задать произвольное значение, API вернет ошибку и никаких действий с базой данных выполнено не будет.
для Dev & Test