- Введение
- Вот краткое описание того, чем мы занимаемся:
- Ключевые вещи, которые нам нужны:
- Обзор безопасности API
- Шлюз API в качестве привратника👮
- Как шлюз APISIX защищает ваши API?
- Клонирование демонстрационного репозитория
- Понять структуру проекта
- Сборка многоконтейнерного APISIX с помощью Docker CLI
- Включение ограничения IP-адресов
- Блокирование прямого доступа к ресурсу API
- Разрешить пользователям запрашивать API
- Что дальше
- Рекомендуемый контент
Введение
В этом руководстве мы рассмотрим некоторые встроенные плагины Apache APISIX API Gateway для защиты ваших Spring Boot REST API и продемонстрируем, как эффективно их использовать. Вы научитесь запускать мультиконтейнерное приложение (backend, db, apisix и etcd вместе) с помощью Docker compose. В курсе также содержатся концептуальные знания о безопасности API, важной роли шлюза API в решении сквозных проблем, а также о том, как Apache APISIX может помочь вам упростить и ускорить задачу обеспечения безопасности API.
Вот краткое описание того, чем мы занимаемся:
✅ Обзор безопасности API.
✅ Шлюз API в качестве привратника.
✅ Как шлюз APISIX защищает ваши API?
✅ Клонируйте демо-репозиторий apisix-security-java-spring с GitHub.
✅ Разберитесь в структуре проекта и файла docker-compose.yaml
.
✅ Постройте многоконтейнерный APISIX с помощью Docker CLI.
✅ Разрешите доступ к вашему API только IP-адресам из белого списка с помощью плагина ограничения IP-адресов.
✅ Блокируйте прямой доступ к некоторым ресурсам API с помощью плагина Uri-blocker.
✅ Убедитесь, что только разрешенные пользователи могут запрашивать ваш API с помощью плагина Consumer restriction.
Ключевые вещи, которые нам нужны:
👉 JDK 11+. Убедитесь, что в вашей системе установлен пакет OpenJDK. Для этой демонстрации я использовал Windows OS и Java 11.
👉 Docker desktop — для выполнения этого руководства вам также понадобится локально установленный Docker desktop. Он доступен для Windows или macOS. Или установите Docker ACI Integration CLI для Linux.
💁 Прежде чем мы начнем, давайте быстро расширим наши теоретические знания о безопасности API и концепциях API Gateway.
Обзор безопасности API
Безопасность API — это термин, относящийся к практике и продуктам, которые предотвращают злонамеренные атаки на интерфейсы прикладных программ (API). Поскольку API стали ключом к программированию веб-интерфейсов, они стали мишенью для хакеров. В результате базовая аутентификация, требующая только имена пользователей и пароли, была заменена различными методами безопасности, такими как многофакторная аутентификация (MFA) или токены, например, веб-токены JWT.
В современную эпоху безопасность API становится все более важной. Существует множество методов усиления безопасности:
- шифрование TLS
- брандмауэры API
- Проверка достоверности данных запроса
- Дросселирование для защиты
- Постоянный мониторинг
- Аудит
- Ведение журнала
- Ограничение IP-адресов
- И многое другое.
Безопасность API с передачей репрезентативного состояния (REST) является одним из наиболее распространенных способов защиты API. Безопасность REST API подразумевает использование унифицированного идентификатора ресурса (URI) протокола передачи гипертекста (HTTP), который контролирует данные, к которым API получает доступ в процессе работы. Таким образом, защита REST API может предотвратить атаки с использованием вредоносных данных, которые злоумышленник пытается внедрить с помощью API.
Шлюз API в качестве привратника👮
Шлюз API — это важный компонент решения для управления API. Он является ключом к безопасности API и защищает базовые данные, как привратник, проверяющий аутентификацию и авторизацию и управляющий трафиком. Являясь тонким слоем между пользовательскими клиентами и вышестоящими сервисами, шлюз API расширяется многочисленными плагинами для обработки аутентификации, авторизации, управления трафиком и безопасности.
Apache APISIX — это легкий API-шлюз с открытым исходным кодом, который находится перед вашими вышестоящими службами. Простой в настройке и быстрый в развертывании API-шлюз APISIX служит центральной точкой для маршрутизации всех входящих запросов по назначению, будь то вышестоящий API-сервер, сторонний сервис, база данных или даже бессерверный.
Как шлюз APISIX защищает ваши API?
Безопасность API в APISIX является наивысшим приоритетом. Поскольку шлюз служит в качестве встроенной прокси-точки контроля над API.
- Проверяет личность, связанную с запросами API, с помощью проверки учетных данных и токенов, а также других средств аутентификации. Вы можете проверить доступные плагины аутентификации.
- Определяет, какой трафик разрешено пропускать через API к внутренним службам.
- Контролирует трафик, проходящий через API, используя ограничение скорости и дросселирование. Для этого существуют плагины контроля трафика.
- Наблюдает за всеми запросами и применяет политики времени выполнения для обеспечения управления. Существует множество плагинов наблюдаемости, которые можно легко включить для ваших API.
- Внедряет все стандартные для отрасли шифрования.
Получив достаточно знаний, теперь мы можем начать применять некоторые плагины безопасности в действии для нашего демонстрационного приложения Spring Boot App. Давайте приступим 🚀.
Клонирование демонстрационного репозитория
Для этой демонстрации мы воспользуемся демо-проектом apisix-security-java-spring, который я подготовил заранее. Вы можете посмотреть его на Github.
Используйте git для клонирования репозитория:
git clone 'https://github.com/Boburmirzo/apisix-security-java-spring'
Перейдите в корневой каталог apisix-security-java-spring
cd apisix-security-java-spring
Вы можете открыть проект в своем любимом редакторе кода. Я использовал IntelliJ Idea community edition. Вы увидите следующую структуру каталогов проекта:
Понять структуру проекта
В папках проекта находится список основных компонентов, на которые вы можете взглянуть:
- Конфигурационные файлы APISIX — Все сервисы настраиваются путем монтирования внешних конфигурационных файлов проекта в docker-контейнеры: /apisix_conf/conf.yaml определяет конфигурации для apisix. Аналогично, конфигурации для etcd, prometheus и grafana находятся в /etcd_conf/etcd.conf.yml, /prometheus_conf/prometheus.yml и /grafana_conf/config соответственно.
- Журналы APISIX — в папке apisix_log регистрируются запросы APISIX Admin и Control API, такие как
access.log
илиerror.log
. - Проект Spring Boot — Далее в папке spring-postgres хранится Java-приложение с фреймворком Spring (классы Controller, repository и entity) и настройка базы данных PostgreSQL с фиктивной схемой и данными.
-
Файл Docker compose — Файл docker-compose.yml определяет приложение с некоторыми сервисами:
☝️Вы можете заметить, что все сервисы сопоставлены с сетью apisix
.
Проект
apisix-security-java-spring
использует аналогичный пример шаблона APISIX docker compose.
version: "3"
services:
apisix-dashboard:
image: apache/apisix-dashboard:2.10.1-alpine
restart: always
volumes:
- ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml
ports:
- "9000:9000"
networks:
apisix:
apisix:
image: apache/apisix:2.13.1-alpine
restart: always
volumes:
- ./apisix_log:/usr/local/apisix/logs
- ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
depends_on:
- etcd
##network_mode: host
ports:
- "9080:9080/tcp"
- "9091:9091/tcp"
- "9443:9443/tcp"
- "9092:9092/tcp"
networks:
apisix:
etcd:
image: bitnami/etcd:3.4.15
restart: always
volumes:
- etcd_data:/bitnami/etcd
environment:
ETCD_ENABLE_V2: "true"
ALLOW_NONE_AUTHENTICATION: "yes"
ETCD_ADVERTISE_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ports:
- "12379:2379/tcp"
networks:
apisix:
prometheus:
image: prom/prometheus:v2.25.0
restart: always
volumes:
- ./prometheus_conf/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
networks:
apisix:
grafana:
image: grafana/grafana:7.3.7
restart: always
ports:
- "3000:3000"
volumes:
- "./grafana_conf/provisioning:/etc/grafana/provisioning"
- "./grafana_conf/dashboards:/var/lib/grafana/dashboards"
- "./grafana_conf/config/grafana.ini:/etc/grafana/grafana.ini"
networks:
apisix:
backend:
build: spring-postgres/backend
ports:
- "8080:8080"
environment:
- POSTGRES_DB=example
networks:
apisix:
db:
image: postgres
restart: always
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql/data
networks:
apisix:
environment:
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
networks:
apisix:
driver: bridge
secrets:
db-password:
file: spring-postgres/db/password.txt
volumes:
db-data:
etcd_data:
driver: local
Сборка многоконтейнерного APISIX с помощью Docker CLI
Теперь мы можем запустить наше приложение, выполнив команду docker compose
из корневой папки проекта:
docker-compose -p docker-apisix up -d
Пример вывода:
Список запущенных контейнеров можно увидеть, выполнив команду docker compose ps
CLI или используя docker desktop:
Когда контейнеры запущены, перейдите по адресу http://localhost:8080/get
в веб-браузере и вы увидите следующий результат:
Этот ответ на самом деле приходит от простого Spring Boot REST API. Если вы посмотрите папку проекта spring-postgres
, каталог src/main/java
содержит исходный код нашего проекта. Есть класс контроллера GreetingController
, аннотированный @RestController
, где одна конечная точка /get
обслуживает наши запросы. По сути, он извлекает данные из базы данных PostgreSQL и отвечает на запрос атрибутом name
в классе сущности Greeting
.
На следующих шагах мы включим различные плагины безопасности Apache APISIX для этой конечной точки.
@RestController
public class GreetingController {
private final GreetingRepository repository;
public GreetingController(GreetingRepository repository) {
this.repository = repository;
}
@GetMapping("/get")
public String getApisixGreeting() {
Greeting apisixGreeting = repository.findById(1).orElse(new Greeting("Not Found 😕"));
return apisixGreeting.getName();
}
}
Включение ограничения IP-адресов
Теперь мы можем включить плагин ограничения IP-адресов для конечной точки API. IP-ограничение — это метод ограничения IP-адресов клиентов, которые могут отправлять запросы, путем составления белого/черного списка IP-адресов. Мы не можем получить доступ к API с IP-адресов, отличных от разрешенных.
На первом этапе нам нужно создать восходящий поток для нашего бэкенд-сервиса. Мы используем команды curl
для взаимодействия с API администратора APISIX:
curl "http://127.0.0.1:9080/apisix/admin/upstreams/1" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d '
{
"type": "roundrobin",
"nodes": {
"backend:8080": 1
}
}'
Объект Upstream будет указывать на целевой сервис backend
или несколько сервисов backend, в нашем случае он ссылается на Spring Boot REST API.
На следующем этапе мы определяем маршрут и привязываем его к Upstream. Он может быть привязан по upstream_id
в конкретном маршруте. Также мы включим плагин ip-restriction
в конфигурации маршрута.
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/get",
"plugins": {
"ip-restriction": {
"whitelist": [
"127.0.0.2"
]
}
},
"upstream_id": "1"
}'
В атрибуте whitelist
плагина ip-restriction
мы разрешаем доступ к /get
URI только одному IP-адресу 127.0.0.2
. Если вы попытаетесь получить доступ к API с запрещенным IP-адресом, APISIX выдаст ошибку 403 Forbidden Http:
curl http://127.0.0.1:9080/get -i --interface 127.0.0.1
Пример вывода:
HTTP/1.1 403 Forbidden
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.13.1
{"message":"Your IP address is not allowed"}
☝️ В конфигурации плагина можно использовать один IP, несколько IP или диапазоны в нотации CIDR, например 10.10.10.0/24. Плагин также поддерживает адреса IPv4 и IPv6.
Теперь мы знаем один способ защиты наших API путем разрешения/запрета IP-адресов с помощью APISIX.
Блокирование прямого доступа к ресурсу API
Далее рассмотрим более расширенные возможности блокировки URI с помощью плагина uri-blocker путем применения правил фильтрации regex. Например, у нас может быть сценарий, когда конечная точка API должна быть заблокирована, если пользователь пытается получить доступ и загрузить приватный файл sample-file.csv
.
Мы можем включить плагин uri-blocker
аналогично настройке плагина ip-restriction
, которую мы применили в предыдущем шаге:
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/*",
"plugins": {
"uri-blocker": {
"block_rules": ["sample-file.csv+"]
}
},
"upstream_id": "1"
}'
После того, как вы настроили плагин, как показано выше, вы можете попробовать получить доступ к файлу с помощью команды curl
:
curl -i http://127.0.0.1:9080/sample-file.csv
Вы должны получить еще одну ошибку Http 403 Forbidden:
HTTP/1.1 403 Forbidden
Теперь мы ограничили прямой доступ к ресурсу URI. Вы также можете установить свойство
rejected_msg
в конфигурации плагина, чтобы настроить сообщение тела ответа.
Разрешить пользователям запрашивать API
Одна из техник — сделать соответствующие ограничения доступа к ресурсам API для определенных пользователей или сервисов. Ограничение потребителя (consumer-restriction) — делает соответствующие ограничения доступа к вашим сервисам или маршрутам на основе различных выбранных пользователей. Если неизвестный пользователь попытается отправить запрос, Apache APISIX встретит его ошибкой.
Предположим, что у нас есть два потребителя наших API (consumer1
и consumer2
). Мы хотим предоставить доступ только одному из них. Для этого давайте создадим двух потребителей и включим плагин consumer-restriction
для нашего существующего примера маршрута.
Чтобы создать первого потребителя, выполните следующую команду:
curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
"username": "consumer1",
"plugins": {
"basic-auth": {
"username":"consumer1",
"password": "123456"
}
}
}'
Чтобы создать второго потребителя, выполните следующую команду:
curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
"username": "consumer2",
"plugins": {
"basic-auth": {
"username":"consumer2",
"password": "654321"
}
}
}'
Затем включите плагин consumer-restriction
и разрешите только consumer1
доступ к конечной точке /get
:
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/get",
"plugins": {
"basic-auth": {},
"consumer-restriction": {
"whitelist": [
"consumer1"
]
}
},
"upstream_id": "1"
}'
У consumer-restriction
есть свойство type, которое является перечислимым типом (поддерживает следующие значения: consumer_name, service_id и route_id), мы можем указать его, чтобы разрешить доступ к соответствующему объекту.
По умолчанию плагин возвращает общее сообщение {"message": "Имя_потребителя_запрещено."}
, если объект не разрешен. Можно настроить более дружественное сообщение через атрибут плагина.
Теперь мы можем проверить, может ли потребитель consumer1
запросить ресурс API с предоставленными учетными данными:
curl -u consumer1:123456 http://127.0.0.1:9080/get -i
Выход:
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 19
Connection: keep-alive
Server: APISIX/2.13.1
Hello Apache APISIX
Очевидно, что consumer1
может запросить конечную точку, поскольку мы внесли его в белый список в конфигурации плагина consumer-restriction
.
Однако второй потребитель не имеет доступа. Теперь мы можем попробовать запросить тот же путь с другими учетными данными потребителя:
curl -u consumer2:123456 http://127.0.0.1:9080/get -i
Выход:
HTTP/1.1 403 Forbidden
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.13.1
{"message":"The consumer_name is forbidden."}
Что дальше
В этой статье блога мы показали, как развернуть наше приложение Spring Boot REST API вместе с Apache APISIX API Gateway, используя возможность Docker compose для более плавного развертывания. Кроме того, мы научились использовать базовые плагины безопасности, поэтому вы можете ознакомиться с другими доступными плагинами для удовлетворения более сложных сценариев безопасности API или создать свой собственный плагин для API Gateway с помощью Java Plugin Runner.
Рекомендуемый контент
➔ Смотреть видеоурок Начало работы с Apache APISIX
➔ Прочитать статью в блоге Обзор плагинов для шлюза API Apache APISIX
➔ Читайте статью в блоге Централизованная аутентификация с помощью плагинов Apache APISIX
➔ Читайте запись в блоге Безопасность API с OIDC с помощью Apache APISIX и Microsoft Azure AD
➔ Читайте запись в блоге Наблюдаемость API с помощью плагинов Apache APISIX.
Сообщество⤵️
🙋 Присоединяйтесь к сообществу Apache APISIX
🐦 Следите за нами в Twitter
📝 Найдите нас в Slack
📧 Пишите нам со своими вопросами