Создание микросервисов — страница 50 из 69

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

API-ключи

API-ключи используются всеми открытыми API-интерфейсами таких сервисов, как Twitter, Google, Flickr и AWS. API-ключи позволяют сервису идентифицировать того, кто осуществляет вызов, и наложить ограничения на то, что он может сделать. Зачастую ограничения выходят за рамки простого предоставления доступа к ресурсам и могут распространяться на такие действия, как ограничение скорости конкретных абонентов для обеспечения качества предоставления сервиса другим людям.

Когда речь заходит об использовании API-ключей в ваших собственных подходах к обмену данными между микросервисами, конкретный рабочий механизм будет зависеть от используемой технологии. В некоторых системах применяется один общий API-ключ и используется подход, похожий на недавно рассмотренный HMAC. Более распространенный подход заключается в применении пары из открытого и закрытого ключей. Обычно управление ключами осуществляется централизованно, так же, как мы бы централизованно управляли определением идентичности людей. В данной области очень популярна модель шлюза.

Частично популярность API-ключей обусловлена тем фактом, что их применение для программ совсем не сложно. В сравнении с обработкой SAML-квитирования аутентификация на основе API-ключа намного проще и понятнее.

Конкретные возможности систем сильно отличаются друг от друга, и у вас есть несколько вариантов как в коммерческой области, так и в области программ с открытым кодом. Некоторые средства просто обрабатывают обмен API-ключами и выполняют некоторые основные функции управления ключами. Другие средства предлагают все, вплоть до включения ограничения скорости трафика, монетизации, API-каталогов и систем обнаружения.

Некоторые API-системы позволяют создавать мост от API-ключей к существующим сервисам каталогов. Это дает возможность выпускать API-ключи для принципалов (представленных людьми или системами) в вашей организации и следить за жизненным циклом этих ключей примерно так же, как вы бы управляли их обычными учетными данными. Это дает возможность разрешать доступ к вашим сервисам различными способами, но при сохранении единого источника достоверности, например с использованием SAML при аутентификации людей для SSO и API-ключей — при обмене данными между сервисами (рис. 9.2).

Проблема помощника

Аутентификация принципала с помощью отдельно взятого микросервиса осуществляется довольно просто. А что получится, если этому сервису для завершения операции понадобится совершить дополнительные вызовы? Посмотрите на рис. 9.3, где показан сайт интернет-магазина MusicCorp. Наш интернет-магазин представляет собой написанный на JavaScript пользовательский интерфейс, работающий в среде браузера. Он совершает вызовы приложения магазина, находящегося на серверной стороне, используя схему внутренних интерфейсов для внешних интерфейсов, которая рассматривалась в главе 4. Вызовы, осуществляемые между браузером и сервером, могут быть аутентифицированы с помощью SAML, OpenID Connect или подобных им технологий. Пока нас все устраивает.

Рис. 9.2. Использование сервисов каталогов для синхронизации информации о принципалах между SSO и API-шлюзом


Рис. 9.3. Пример создания ситуации, при которой можно обмануть помощника


После регистрации я могу щелкнуть на ссылке и просмотреть подробности заказа. Для отображения информации следует извлечь исходный заказ из сервиса заказов, но, кроме этого, нужно просмотреть информацию о доставке заказа. Следовательно, щелчок на ссылке /orderStatus/12345 заставит интернет-магазин при запросе подробностей инициировать вызов из сервиса интернет-магазина как к сервису заказов, так и к сервису доставок. Но примут ли эти нижестоящие сервисы вызовы от интернет-магазина? Можно было бы принять установку подразумеваемого доверия, поскольку вызов поступил в границах периметра, что вполне допустимо. Можно было бы даже воспользоваться сертификатами или API-ключами, чтобы подтвердить, что информацию действительно запрашивает интернет-магазин. Но будет ли этого достаточно?

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

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

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

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

Безопасность данных, находящихся в покое

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

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

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

Пользуйтесь хорошо известными средствами

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

Что касается шифрования данных, находящихся в покое, то, если у вас нет весьма веских аргументов в пользу чего-либо другого, остановите свой выбор на широко известных реализациях AES-128 или AES-256, предназначенных для вашей платформы[3]. Реализации AES, которые с высокой долей вероятности были всесторонне протестированы (и хорошенько подправлены), имеются в библиотеках времени выполнения как у Java, так и у. NET-технологии. Существуют и отдельные библиотеки для большинства других платформ, например библиотеки Bouncy Castle для Java и C#.

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

Плохо реализованное шифрование еще хуже, чем его полное отсутствие, поскольку ложное чувство защищенности может привести к потере бдительности.

Все зависит от ключей

До сих пор речь шла о том, что шифрование зависит от реализации алгоритма, получающей шифруемые данные и ключ, после чего выполняющей шифрование данных. А где же хранятся сами ключи? Если я шифрую данные, переживая за то, что кто-нибудь может похитить всю мою базу данных, и храню ключи в той же самой базе данных, то поставленной цели я явно не добьюсь! Поэтому ключи нужно хранить в каком-нибудь другом месте. Но где именно?