Когда принципал пытается получить доступ к ресурсу (например, интерфейсу на веб-основе), он перенаправляется на аутентификацию с участием провайдера идентификации. При этом у него могут быть запрошены имя пользователя и пароль или же может быть использовано что-то более совершенное — вроде двухфакторной аутентификации. После того как поставщик убедится в том, что принципал был аутентифицирован, он выдает информацию сервис-провайдеру, позволяя ему решать, нужно ли предоставлять принципалу доступ к ресурсу.
Провайдером идентификации может быть система на внешнем оборудовании или что-нибудь, что находится внутри вашей организации. Например, компанией Google предоставляется провайдер идентификации OpenID Connect. Но промышленным предприятиям свойственно иметь собственного провайдера идентификации, который может быть связан с сервисом каталогов вашей компании. Сервисом каталогов может быть какое-либо средство вроде Lightweight Directory Access Protocol (LDAP) или Active Directory. Эти системы позволяют хранить информацию о принципалах, свидетельствующую о тех ролях, которые они играют в организации. Зачастую сервис каталогов и провайдер идентификации представляют собой единое целое, а иногда они могут быть разделены, но тесно связаны друг с другом. Например, Okta содержит SAML-провайдер идентификации, выполняющий задачи двухфакторной идентификации, но как источник достоверных данных он может быть связан с сервисами каталогов вашей компании.
SAML представляет собой стандарт на основе использования SOAP-протокола, он известен тем, что с ним весьма непросто работать, несмотря на доступность поддерживающих его библиотек и инструментальных средств. OpenID Connect является стандартом, возникшим в качестве конкретной реализации OAuth 2.0 и основанным на способах управления технологией единого входа, принятых Google и рядом других компаний. В нем используются простые REST-вызовы, и, на мой взгляд, это сделано, скорее всего, для проникновения на рынок промышленных предприятий за счет простоты использования. Сейчас главным камнем преткновения является отсутствие поддерживающих его провайдеров идентификации. Для открытых для публичного просмотра сайтов может вполне подойти использование в качестве вашего провайдера средств компании Google, но для внутренних систем или систем, в которых требуются повышенный контроль и отображение того, как и где устанавливаются ваши данные, понадобится собственный домашний провайдер идентификации. На момент написания книги доступными в данном качестве были два из весьма немногих вариантов, OpenAM и Gluu, что не может сравниться с богатством выбора вариантов для SAML (включая средство Active Directory, которое, похоже, получило всеобщее распространение). До тех пор пока имеющиеся провайдеры идентификации не начали поддерживать OpenID Connect, распространение этого средства будет ограничено ситуациями, при которых люди будут вполне удовлетворены использованием публичных провайдеров идентификации.
Итак, несмотря на то, что, на мой взгляд, у OpenID есть будущее, вполне возможно, что на его широкое распространение понадобится время.
При установке микросервиса вопрос о перенаправлении на провайдера идентификации и о квитировании связи с ним может решаться каждым сервисом. Очевидно, это приведет к многократному дублированию работы. Конечно, в решении вопроса может помочь общая библиотека, но мы ведь должны избегать связанности микросервисов, исходящей от общего кода. К тому же такое решение будет бесполезным в случае использования нескольких различных технологических стеков.
Вместо обременения каждого сервиса решением вопросов управления квитированием с вашим провайдером идентификации можно воспользоваться шлюзом, работающим в качестве прокси-сервера и располагающимся между вашими сервисами и внешним миром (рис. 9.1). Идея состоит в том, что мы можем централизовать поведение для перенаправления пользователя и выполнения квитирования в одном месте.
Но нам еще нужно решить проблему получения расположенными ниже сервисами такой информации о принципалах, как их имена пользователей или роли, которые они играют в организации. Если используется HTTP, эту информацию можно поместить в заголовки. Одним из средств, выполняющих эту задачу за вас, является Shibboleth, использование которого вместе с Apache для получения отличных результатов в управлении интеграцией с провайдерами идентификации на основе SAML мне уже приходилось наблюдать.
Рис. 9.1. Использование шлюза для управления единым входом (SSO)
Если будет принято решение о том, чтобы переложить ответственность за аутентификацию на шлюз, возникнет еще одна проблема, связанная с затруднениями при осмыслении поведения микросервисов, когда они рассматриваются в изоляции от всего остального. Помните, как в главе 7 исследовались затруднения, связанные с воспроизведением среды, подобной той, в которой ведется работа в производственном режиме? Если вы пойдете по пути использования шлюза, нужно гарантировать разработчикам возможность запуска их сервисов за этим шлюзом без приложения чрезмерных усилий.
И еще одной, последней проблемой, связанной с этим подходом, является возможность возникновения у вас ложного чувства безопасности. Мне нравится идея глубоко эшелонированной обороны — от периметра сети к подсети, брандмауэру, машине, операционной системе, используемому оборудованию. У вас есть возможность реализовать меры безопасности на всех этих рубежах, часть из которых мы вскоре рассмотрим. Мне встречались люди, которые клали все яйца в одну корзину, всецело полагаясь на шлюз. И нам всем известно, что происходит, когда у нас есть единая точка отказа…
Разумеется, шлюз можно применять и для других целей. Например, при использовании уровня Apache-экземпляров, выполняющих Shibboleth, на этом уровне можно также принимать решения о завершении HTTPS, запуске обнаружения вторжений и т. д. Но при этом нужно проявлять осторожность. На уровни шлюзов зачастую возлагается все больше и больше функциональных обязанностей, что может вылиться в возникновение гигантской точки связывания. И чем больше функциональных нагрузок, тем шире становится поле для проведения атак.
Шлюз может быть в состоянии обеспечить вполне эффективную широкомасштабную аутентификацию. Например, он может воспрепятствовать доступу к приложению технической поддержки любого незарегистрировавшегося пользователя. При условии, что шлюз в результате аутентификации может извлечь атрибуты, касающиеся принципала, можно рассчитывать на возможность принятия более гибких решений. Например, весьма распространено сведение людей в группы или присвоение им тех или иных ролей. Этой информацией можно воспользоваться, чтобы понять, что они могут делать. Следовательно, доступ к приложению технической поддержки можно предоставить только принципалам с конкретной ролью (например, только сотрудникам). Но, кроме разрешения (или запрещения) доступа к конкретным ресурсам или конечным точкам, нам нужно допустить всех остальных к самим микросервисам, а для этого следует принимать дальнейшие решения о том, какие действия разрешать.
Возвращаясь к приложению технической поддержки, нужно решить, следует ли позволять видеть абсолютно все подробности любому сотруднику организации? Скорее всего, их работа будет распределена по ролям. Например, принципалу из группы CALL_CENTER может быть разрешено просматривать любые информационные блоки, относящиеся к клиенту, за исключением подробностей, касающихся его платежей. Принципалу также может быть разрешено выдавать возвраты, но сумма может быть ограничена. А вот сотрудникам, имеющим роль CALL_CENTER_TEAM_LEADER, может быть позволено выдавать более крупные суммы возврата.
По отношению к отдельно взятому микросервису эти решения должны быть локальными. Мне встречались люди, применяющие различные атрибуты, предоставляемые провайдерами идентификации, самым ужасным образом, используя совершенно мелочные роли вроде CALL_CENTER_50_DOLLAR_REFUND (то есть специалист колл-центра с правами возврата сумм до 50 долларов), где они в конечном итоге помещали в свои службы каталогов информацию, относящуюся к какой-то небольшой части одной из характеристик нашего системного поведения. Поддержка таких установок превращается в настоящий кошмар и оставляет для наших сервисов весьма скромные возможности иметь собственный независимый жизненный цикл, поскольку вдруг оказывается, что часть информации, касающейся поведения сервиса, находится за его пределами, возможно, в системе, управляемой другой частью организации.
Вместо этого предпочтение нужно отдавать ролям более общего плана, смоделированным вокруг характера работы вашей организации. Если вспомнить все, о чем говорилось в предыдущих главах, можно сделать вывод: мы стремимся создавать такие программные средства, которые соответствуют порядку работы нашей организации. Поэтому и роли нужно выбирать, руководствуясь тем же принципом.
До сих пор термин «принципал» использовался для описания любых субъектов, способных пройти аутентификацию и авторизоваться для выполнения тех или иных действий, но фактически приводимые примеры касались людей, использующих компьютеры. А как насчет программ или других сервисов, проходящих взаимную аутентификацию?
Нашим первым вариантом может быть простое предположение, что любые вызовы сервиса, которые делаются внутри нашего периметра, вызывают безоговорочное доверие.
В зависимости от степени конфиденциальности данных этот вариант может стать вполне приемлемым. Некоторые организации пытаются обеспечить безопасность по периметру своих сетей и, следовательно, предполагают, что, когда два сервиса общаются друг с другом, делать что-либо дополнительно не нужно. Но стоит только взломщику проникнуть в вашу сеть, у вас практически не будет защиты против посреднической атаки. Если взломщик решит перехватить и прочитать отправленные данные, внести в них изменения без ва