Reactive Spring ABAC Security: безопасность уровня Enterprise

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

В продолжение к предыдущей статье Передовые технологии на службе СЭД рассмотрим современные подходы к обеспечению корпоративной безопасности и ожидаемые риски у корпораций в России.

Аннотация

Что такое безопасность уровня Enterprise? Встречается огромное разнообразие схем конфигурации безопасности инфраструктуры. Например: валидация и кэширование токена только в сервисе Gateway с прямой отправкой логина и списка ролей сервисам или ретрансляция токена с Gateway в сервисы для активации функций Spring Security через распаковку токена в логин и роли с проверкой только подписи токена открытым ключом.

На самом деле, любую существующую схему безопасности можно отнести к Enterprise. Базовая конфигурация Spring Security, предоставляемая по умолчанию, не выдерживает высоких нагрузок. Данный фактор стал одним из главных причин разнообразия подходов к безопасности, возникших в поиске оптимального способа поддержки высоких нагрузок в рамках существующей инфраструктуры и технологий.

В статье рассматриваются основные аспекты конфигурирования корпоративной безопасности с поддержкой высоких нагрузок в реактивном стеке технологий. Подробно описана модель безопасности attribute-based access control (ABAC), которая применяет совокупность абстрактных правил к определённому типу действий с учётом роли при необходимости.

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

Введение

Начнём с рассмотрения основополагающей на данный момент модели безопасности ABAC в сравнении с классической моделью role-based access control (RBAC).

Классическая модель безопасности RBAC предлагает грубый подход, не позволяющий описать политику безопасности многоуровневой филиальной системы.

RBAC оперирует ролями и группами ролей. Каждая роль напрямую привязана к действию, что приводит к созданию большого количества ролей (роль менеджера головной организации, роль менеджера филиала, роль менеджера подразделения филиала – разные сущности в силу функциональных различий).

Сплошной список ролей не позволяют эффективно выстроить политики безопасности, группирующие типичные действия из-за неочевидности их разграничения. Модель RBAC стала архаичной не смотря на сегодняшнее присутствие в большинстве информационных систем.

Основное преимущество модели безопасности ABAC в возможности описания политики безопасности через совокупность правил, основанных на атрибутах участвующих в действиях пользователя. Такой подход позволяет детализировать политики безопасности до необходимого уровня.

Целевое направление применения ABAC – описание политик безопасности филиальной системы с полным контролем доступа до любого уровня вложенности и сложности описания. Все правила ABAC описываются в виде SpEL-выражений и в отличии от RBAC хранятся в базе данных, где соответственно легко поддаются анализу и модификации.

Можно отметить интересный факт связанный с переходом информационной безопасности от модели RBAC к ABAC – на первом этапе каждая политика содержит одно правило.

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

В итоге, реализована библиотека Reactive Spring ABAC Security с открытым исходным кодом на GutHub, обладающая рядом свойств: как гибкость в настройках, мощь в широких возможностях и скорость в работе. Библиотека опубликована в Maven Central:

<dependency>
    <groupId>io.github.sevenparadigms</groupId>
    <artifactId>reactive-spring-abac-security</artifactId>
    <version>1.0.0</version>
</dependency>

Через настройки библиотеки можно выбрать любую гомоморфную исходной схему конфигурации безопасности из коробки, а также генерировать или валидировать токен – в совокупности такая гибкость становится особенно удобно при разработке макета проекта на начальной стадии с целью точной оценки итоговых сроков реализации или участия в тендере, продемонстрировав готовый макет с основным функционалом, в то время, как у конкурентов ничего нет.

Совсем не обязательно поднимать дополнительный корпоративный SSO-сервер аутентификации типа Keycloak для задач такого рода, когда скорость реализации и простота развёртывания выходят на передний план – ведь такие задачи выполняют фрилансеры без отрыва внутренних ресурсов.

Предлагаемая библиотека на клиентской стороне активирует Spring Security с моделью безопасности ABAC, при этом, кэшируя данные по токену, обратившись к сервису авторизации только один раз. Пометка отозванности токена в кэше происходит через событие Spring Event, инициацию которого оставляем за логикой инфраструктуры при завершении сессии пользователя.

Основные аспекты реализации

Рассмотрим основные моменты при настройке конфигурации безопасности Spring Security:

@Bean
fun securityWebFilterChain(
    http: ServerHttpSecurity,
    authenticationWebFilter: AuthenticationWebFilter,
    abacRulePermissionService: AbacRulePermissionService,
    expressionHandler: DefaultMethodSecurityExpressionHandler
): SecurityWebFilterChain {
    expressionHandler.setPermissionEvaluator(abacRulePermissionService)
    http.csrf().disable()
        .headers().frameOptions().disable()
        .cache().disable()
        .and()
        .exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint())
        .and()
        .authorizeExchange()
        .pathMatchers(HttpMethod.OPTIONS)
        .permitAll()
        .and()
        .requestCache().requestCache(NoOpServerRequestCache.getInstance())
        .and()
        .authorizeExchange()
        .matchers(EndpointRequest.toAnyEndpoint())
        .hasAuthority(Constants.ROLE_ADMIN)
        .and()
        .authorizeExchange()
        .pathMatchers(*Constants.whitelist).permitAll()
        .anyExchange().authenticated()
        .and()
        .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
        .addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHORIZATION)
        .httpBasic().disable()
        .formLogin().disable()
        .logout().disable()
    if (super.tokenIntrospector() != null) {
        http.oauth2ResourceServer()
            .opaqueToken().introspector(super.tokenIntrospector())
    }
    return http.build()
}

Строка expressionHandler.setPermissionEvaluator(abacRulePermissionService) включает функционал ABAC. Все правила ABAC представляют собой компилируемые и кэшируемые SpEL-выражения, предоставляя полную свободу в предикатах. Описание подключения ABAC будет в разделе настройки безопасности на стороне клиентского сервиса через файл конфигурации application.yml

По умолчанию, при первом запросе клиента, Spring создаёт web-сессию для кэширования сессионных переменных, результата запросов и сбора различных данных при взаимодействии с клиентом в рамках одной сессии. Данный подход устарел, даже при кэшировании сессий в Redis или Hazelcast – сессии занимают значительный объем памяти и вся логика вокруг сессий не имеет перспектив, не говоря уже о проблемах утечки в реактивном стеке.

На много проще и увереннее поддерживать жизнь сессии в рамках одной реактивной цепочки инструкций запрос-ответа, после чего, сессия благополучно закроется вместе с сессионным потоком. Кто-то возразит и скажет, что кэширование сессий экономит до тысячи инструкций на её создание, но тут дело в совокупности факторов: неоднозначность данной оптимизации пришедшей в наследство из синхронного стека, высокой эффективности современных процессоров, когда тысяча инструкций выполняются менее чем за 1 мс и высоком риске утечки памяти реактивного стека.

Следующей строкой отключаем поддержку сессий: securityContextRepository(NoOpServerSecurityContextRepository.getInstance())

В Webflux была проблема #7157 связанная с кэшированием в сессиях, поэтому также отключаем сессионное кэширование строкой: requestCache().requestCache(NoOpServerRequestCache.getInstance()), чтобы Webflux оперировал только кэшем уровня бизнес-логики и только в контексте потока исполняемого запроса.

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

Возможность кэширования токенов предусмотрена в библиотеке Spring OAuth2 через расширение OpaqueToken и кэширующий интроспектор NimbusOpaqueToken, который единожды валидирует токен в сервисе авторизации. Заменим интроспектор на свою реализацию, т.к. в нашей библиотеке не используются автоконфиги Spring OAuth2 не смотря на заимствование функционала и включим в конфигурацию строкой: http.oauth2ResourceServer().opaqueToken().introspector(super.tokenIntrospector())

Настройка безопасности клиента

Рассмотрим файл конфигурации application.yml из демонстрационного проекта webflux-dsl-abac-example:

spring:
  r2dbc:
    url: r2dbc:postgresql://postgres:postgres@localhost/dsl_abac?schema=public
    pool:
      maxSize: 20
  main:
    allow-bean-definition-overriding: true
  security:
    abac.url: r2dbc:postgresql://postgres:postgres@localhost/abac_rules?schema=public
    iteration: 512
    length: 720
    secret: eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ1c2VyIiwiYXV0aCI6IlJPTEVfVVNFUiIsImV4cCI6MTYzMDYxMDI5NX0.m0XU2NvGaAtzptgLfmptj3Fk7S1e1NrBTYTqBAjHoPI8lbRB7z3J52FiLRw-PUZPjQusDt19RszrUQDsZoVXeQ
    expiration: 1800
    X-User-Id: true
    skip-token-validation: true
    cache-token: true

Как видим, есть основное соединение с базой данных, а есть отдельная база данных abac_rules, в которой аккумулируются правила со всех сервисов, что удобно в управлении безопасностью и появляется возможность переиспользования правил. А если включить репликацию таблиц abac_rules в базы данных филиалов, то появится централизованное управление безопасностью.

Переменные iteration и length используются для генерации секретного ключа и соли системного пароля пользователя. Переменная secret используется как часть секрета для генерации пароля пользователя и токена. Переменная expiration имеет значение времени жизни токена в секундах.

X-User-Id при значении true активирует Spring Security, когда ожидается в заголовках в ключе X-User-Id приходит значение id пользователя, а в X-Roles массив ролей. Имя пользователя в Spring Security указывается как пустая строка, если заголовок X-Login отсутствует.

Переменная skip-token-validation при значении true активирует Spring Security, извлекая из токена имя пользователя и роли. Стоит единственная проверка на время жизни токена.

Переменная cache-token при значении true активирует Spring Security с полной валидацией токена и кэшированием данных токена. В случае, если в конфигурации не прописан путь до сервиса авторизации spring.security.introspection.uri, тогда ожидается, что токен каким-то образом уже лежит в текущем CacheManager – это удобно при кустомном способе авторизации пользователя, а иначе CacheManager используется для кластерного кэширования токена.

Практическое применение ABAC

Скрипт создания таблицы:

CREATE TABLE abac_rule
(
    id             uuid DEFAULT uuid_generate_v1mc() NOT NULL PRIMARY KEY,
    name           text,
    domain_type    text,
    target         text,
    condition      text
);

insert into abac_rule(name, domain_type, target, condition)
values('Test Rule', 'Dsl', 'action == ''findAll'' and subject.roles.contains(''ROLE_ADMIN'')', 'domainObject.sort == ''id:desc'''),
      ('IP Rule', 'Dsl', 'action == ''findAll'' and environment.ip == ''192.168.2.207''', 'domainObject.sort == ''id:desc'''),
      ('Query jtree not null Rule', 'Dsl', 'action == ''findAll'' and subject.roles.contains(''ROLE_ADMIN'')', 'domainObject.query == ''!@jtree'' and domainObject.fields ==''id''  and domainObject.sort == ''id:desc'''),
      ('Query equals jsonb field Rule', 'Dsl', 'action == ''findAll'' and subject.roles.contains(''ROLE_ADMIN'')', 'domainObject.query == ''jtree.name==Acme doc'' and domainObject.sort == ''id:desc'''),
      ('Query equals jsonb field in Rule', 'Dsl', 'action == ''findAll'' and subject.roles.contains(''ROLE_ADMIN'')', 'domainObject.query == ''jtree.name^^Acme doc'' and domainObject.sort == ''id:desc''');

Применение правила в аннотации над методом:

@PreAuthorize("hasPermission(#dsl, 'findAll')")
fun findAll(@PathVariable jfolderId: UUID, dsl: Dsl) 
                                         = objectService.findAll(jfolderId, dsl)

Для более подробного изучения применения ABAC следует изучить исходный код тестов демонстрационного проекта webflux-dsl-abac-example

Системные риски безопасности

Microsoft официально до 2013 года, в соответствии с законами на тот момент, была обязана встраивать в свои ОС дыры и сообщать о выявленных спецслужбам США. Сейчас эти пункты из законов исключены, но оставили возможность взаимодействия на коммерческой основе для формирования баланса между коммерческим имиджем и уровнем технологичности ведения разведки.

В 2013 году спецслужбами США было взломано большинство правительственных серверов Китая через маршрутизаторы Cisco и ОС Windows Server. В дальнейшем выяснилось, маршрутизаторы подменили во время таможенного досмотра в США. По прибытию в Китай маршрутизаторы были успешно перепрошиты, но изменений в печатной плате не выявлены.

В результате данного инцидента, с текущего 2022 года все правительственные учреждения, подрядчиковые организации и финансовые институты Китая обязаны работать только с маршрутизаторами, серверами и операционными системами отечественного производства.

Есть у этой истории и обратная сторона – сразу после инцидента, с 2013 по 2015 года в Китае было произведено десятки тысяч серверов Supermicro с дополнительным чипом 2х3 мм, которые в массовом порядке поставлены сотням компаний по всей планете. Из них 7000 серверов были установлены в Apple. Также сервера доставили подрядчику Министерства обороны США Elemental, который устанавливал их в бортовые сети боевых кораблей ВМФ, центры управления беспилотников ЦРУ, центры обработки данных Министерства обороны, NASA, обе палаты Конгреса, подразделение внутренней безопасности Госдепа, а также в Amazon.

В результате этой атаки, все представляющие интерес сервера Supermicro с выходом в Интернет были взломаны и на десятки анонимных серверов в Интернете выгружено петабайты информации. Микрокод встроенного чипа регулярно пытался установить соединение с рядом действующих DNS-серверов в Интернете, имитируя dns-запрос и как только соединение устанавливалось, сразу загружалась подпрограмма сканирования и идентификации.

В 2015 году новое подразделение Amazon Web Services (AWS), созданное для нужд ЦРУ, наняла стороннюю компанию для проверки безопасности серверов, поставляемые Elemental, где обнаружили чип вне оригинальной конструкции плат Supermicro. Apple в том же году демонтировал 7000 серверов Supermicro и разорвал контракт на поставку еще 30 тыс. серверов Supermicro.

Эта история приблизилась к развязке в конце сентября 2015 года, когда председатель КНР Си Цзиньпин и президент США Барак Обама сделали совместное заявление о правовой поддержке защиты интеллектуальной собственности и увеличении поставок сетевого оборудования из США в Китай.

В России же налажен выпуск отечественных маршрутизаторов на процессоре «Байкал-Т1», но по ним еще нет эксплуатационной экспертизы и соответственно компании не готовы к переходу. Также нет серверной ОС и все крупнейшие системообразующие институты России на свой постоянный страх и критически высокий риск используют Windows Server и AWS от Amazon.

В случае начала театра военных действий и в силу «чуждости» повсеместно используемых технологий, вполне логично ожидать прямой атаки и уничтожения под корень, в первую очередь, баз данных финансовых институтов страны.

И обратно, если прилегающая страна, нарушая принципы добрососедства стала размещать у себя системы ПРО-ПВО и авиационные системы противника, то во время боевых действий вероятность «утечки» данных к противнику будет близка к 100%, сколько не из-за желания соседей их передавать, а из-за возможного наличия дополнительного чипа.

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

К слову, Россия производит модульную военную технику, отчасти чтобы исключить возможность использования дополнительного чипа, чтобы заказчики вставляли свои модули в самые чувствительные места самолёта, корабля, танка или средств ПВО.

Резюме

Усиление информационной безопасности Китая привело к значительному ускорению развития отечественных технологий и беспрецедентной поддержке IT-стартапов государством. России было бы естественно рассмотреть существующие стандарты безопасности Китая по оборудованию в госсекторе, что сэкономило бы немало времени.

Самый быстрый способ соответствовать общемировым трендам в информационной безопасности – перенести часть производственных мощностей процессоров и системных плат из Китая в Россию для целенаправленного импортозамещения оборудования в госсекторе.

Необходимо строить совместные кластера с Китаем и Индией как c ближайшими союзниками, с которыми связаны десятилетия совместных работ по исследованию и производству высокотехнологичной продукции. А финансовым институтам выстраивать партнёрские отношения с IT-гигантами Alibaba и Xiaomi для обоюдного обогащения компетенциями. Настоящая мощь всех исторических империй была в разнообразии способа выражения силы.

Источник: https://habr.com/ru/post/645923/


Интересные статьи

Интересные статьи

Создание простого бота для Телеграм на Java Spring, который демонстрирует базовые возможности работы с Telegram API.
Я, Дмитрий Лазаренко, руковожу командой, создающей и внедряющей собственный Kubernetes aaS на платформе Mail.ru Cloud Solutions. Давно работая с внедрением Kubernetes, мы...
Spring Data JDBC был анонсирован в 2018 году. Целью было предоставить разработчикам более простую альтернативу JPA, продолжая при этом следовать принципам Spring Data. Подробнее узнать о ...
Предыстория Когда-то у меня возникла необходимость проверять наличие неотправленных сообщений в «1С-Битрикс: Управление сайтом» (далее Битрикс) и получать уведомления об этом. Пробле...
Среди советов по улучшению юзабилити интернет-магазина, которые можно встретить в инете, один из явных лидеров — совет «сообщайте посетителю стоимость доставки как можно раньше».