Статьи

Школа SOA: проектирование водонепроницаемой безопасности для нового предприятия

Безопасность всегда актуальна для ИТ. Это может быть довольно сложной областью, когда рассматриваются все возможные опасности и большое разнообразие решений для их устранения. Но цель Enterprise Security на самом деле сводится к созданию и поддержанию различных уровней контроля доступа . Сам мул всегда облегчал безопасную обработку сообщений как на уровне транспорта, так и на уровне обслуживания и сообщения. Мул конфигурации могут включать в себя все, что может предложить Spring Security , предоставляя, например, легкий доступ к серверу LDAP для аутентификации и авторизации. Кроме того,   приложения Mule могут применять WS-Security.таким образом, облегчая, например, проверку входящих сообщений SAML . Но в этом посте, вместо того чтобы углубляться во все детали очень обширного набора функций безопасности, я бы скорее подошел к этой теме, рассматривая основные проблемы, которые обусловливают необходимость обеспечения безопасности в сервисно-ориентированной архитектуре , как в отрасли в целом Решил эти проблемы, последующее появление популярных технологий, основанных на этой наилучшей промышленной практике, и, наконец, внедрение этих технологий в Муле.

Основные проблемы

целостность

Это все о том, кто знает, кто отправил сообщение. Защита наших ИТ-ресурсов — это вопрос принятия решения о том, кто получает к ним доступ и, конечно же, вступление в области авторизации, в какой степени каждый человек или система должны иметь к ним доступ. Сообщение (которое также сродни вызову службы) должно быть определено как подлинное, чтобы сервер мог принять его и обработать. Это аутентично, если Сервер распознает Клиента как действительного пользователя сервиса. Теперь такое признание обычно достигается какими-то полномочиями, сопровождающими Послание. Однако проверка того, какой Клиент отправил Сообщение, не гарантирует целостность Сообщения: возможно, оно было изменено какой-либо недружелюбной третьей стороной во время транзита! Целостность сообщения, которая включает аутентификацию,гарантирует, что Сообщение, полученное Сервером, является именно тем, которое было отправлено известным Клиентом.

конфиденциальность

Для сервера очень хорошо быть уверенным в целостности сообщения, отправленного известным клиентом, но путь от клиента к серверу, возможно, был засвидетельствован некоторыми нежелательными шпионами, которым удалось увидеть все эти потенциально очень личные детали внутри сообщение! Таким образом, необходимо скрыть эти данные от точки доставки Клиентом до получения Сервером. Требуется соглашение между Клиентом и Сервером, чтобы иметь возможность скрыть детали Сообщения таким образом, чтобы только Сервер мог их раскрыть, и наоборот.

Реакция отрасли

Учетные данные на основе токена

Обычная практика отправки пар имени пользователя / пароля с сообщениями не рекомендуется с двух точек зрения: 

  1. Пароли имеют уровень предсказуемости, в то время как идеал — максимизировать случайность или энтропию. Пары «Имя пользователя / Пароль» являются формой аутентификации с низкой энтропией. 
  2. Кроме того, обслуживание паролей является болью! Если вам нужно сменить пароль, вы сразу же воздействуете на всех Клиентов, которые используют этот пароль. Пока каждый из них не был перенастроен, у вас нарушена связь с ними. Как следствие, нет способа заблокировать доступ к одному Клиенту, в частности, без блокировки всех Клиентов, использующих один и тот же пароль. 

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

Цифровая подпись

Мы, люди, подписываем все виды документов, когда это имеет значение в гражданских, юридических и даже личных сделках, в которых мы участвуем. Это механизм, который мы используем для установления подлинности транзакции. Цифровой мир подражает этому с использованием цифровых подписей, Идея заключается в том, чтобы Клиент создал подпись, используя некоторый алгоритм и секретный код. Сервер должен применить тот же алгоритм с секретным кодом, чтобы создать свою собственную подпись и сравнить входящую подпись с этим. Если они совпадают, Сервер фактически завершил Аутентификацию, гарантируя не только то, что это Сообщение было отправлено известным Клиентом (только известный Клиент мог создать узнаваемую подпись), но и что оно сохранило свою целостность, поскольку оно не было изменено третья сторона в пути В качестве дополнительного преимущества для случаев, когда это имеет значение для сторонних Клиентов, этот механизм также вносит Невозвращение в уравнение, поскольку Клиент не может утверждать, что не отправил подписанное Сообщение.

Криптография с открытым ключом

Вековая практика криптографии сделала науку об искусстве сокрытия вещей! ИТ принял эту науку и может произвести шифрованиесообщения, которое практически невозможно расшифровать без соответствующего ключа для этого. Это как если бы у Клиента была возможность заблокировать Сообщение внутри некоторого воображаемого ящика специальным ключом, скрывая его от посторонних глаз, пока Сервер не разблокирует ящик своим собственным специальным ключом. Цифровая подпись, рассмотренная выше, производит подписи именно таким образом. Криптография имеет две формы: симметричная, когда и клиент, и сервер используют один и тот же ключ для шифрования и дешифрования сообщения; и асимметричный, когда Сервер выдает Клиенту открытый ключ, позволяющий Клиенту зашифровать Сообщение, но сохраняет закрытый ключ, который является единственным, который может расшифровать Сообщение: один ключ для блокировки Сообщения и другой ключ для его разблокировки!

Стандартные реализации Defacto

HTTPS

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

OAuth2

Этот новый стандарт управляет миром авторизации с использованием токенов. Я не буду вдаваться во все сложности полного  танца OAuth2 здесь, но я могу рекомендовать OAuth2 как надежный способ защитить наше Предприятие и который хорошо масштабируется для удовлетворения потребностей ориентированного на SAAS Нового Предприятия. Для этого есть два типа клиентов, которых мы должны обслуживать в нашей защищенной архитектуре SOA :

  1. Внутренние приложения, которые обычно предоставляются конечным пользователям. Они должны предоставить имя пользователя и пароль конечного пользователя и запросить токен в силу их. Этот процесс также предоставляет нам возможность единого входа , поскольку токен может быть сохранен браузером в виде файла cookie на основе доменного имени организации. Все остальные веб-приложения могут получить доступ к cookie. Это то, что Google делает со своим SSO для каждого из своих облачных приложений, таких как Gmail, Календарь, Документы и т. Д.
  2. Сторонние приложения, предоставляющие услуги нашим пользователям, но которым мы хотели бы предоставить ограниченный доступ к нашим системам. Мы не хотим, чтобы эти Приложения получили в свои руки учетные данные наших конечных пользователей, поэтому мы можем провести их через типичный танец OAuth2, который мы все так часто видим в наши дни, когда веб-сайты приглашают нас войти в систему с помощью нашего Google, Facebook или Твиттер аккаунты.

Решение в Муле

Давайте реализуем веб-сервис RESTful в Mule, который предоставит список продуктов в нашем интернет-магазине различным клиентским приложениям. Мы настроим контроль доступа таким образом, чтобы определенные операции были доступны только определенным клиентам. Мы могли бы даже применить более конкретный контроль доступа, учитывая роли пользователей этих Приложений: Admin для полного доступа и Standard для доступа только для чтения. 

HTTPS входящая конечная точка

Входящей конечной точке https в нашем API необходимо использовать соединитель со ссылкой на хранилище ключей. Хранилище ключей — это хранилище сертификатов открытых ключей вместе с их закрытыми ключами. Эти сертификаты отправляются Клиенту по первому запросу HTTPS. Сертификат содержит открытый ключ и идентификатор сервера и подписывается цифровой подписью того же сервера (самозаверяющий сертификат) или независимым центром сертификации. Вы можете создать свой собственный самоподписанный сертификат для целей разработки с помощью  утилиты JDK keytool . Для хранилища ключей требуется пароль как для хранилища ключей, так и для закрытого ключа.

<https:connector name="httpsConnector" cookieSpec="netscape" validateConnections="true" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" doc:name="HTTP\HTTPS">
    <https:tls-key-store path="src/main/resources/keystore.jks" keyPassword="mule123" storePassword="mule123"/>
</https:connector>

Anypoint Secure Token Service

Теперь Mule может выступать в качестве поставщика OAuth2, выдавая токены зарегистрированным клиентам, применяя к этим токенам периоды истечения, связывая их с ролями пользователей и детализированным контролем доступа, известным в мире OAuth как области действия. Также могут быть выданы токены обновления и токены могут быть аннулированы. Мул, конечно, впоследствии может проверять входящие токены на периоды истечения срока действия, роли и области действия и, таким образом, предоставлять или запрещать доступ к потокам в приложении.

  <oauth2-provider:config 
		host="0.0.0.0" 
		port="8081" 
		name="oauth2-provider" 
		accessTokenEndpointPath="access-token" 
		scopes="READ WRITE" 
		resourceOwnerSecurityProvider-ref="security-provider" 
		supportedGrantTypes="IMPLICIT RESOURCE_OWNER_PASSWORD_CREDENTIALS" 
		tokenTtlSeconds="300" 
		enableRefreshToken="true" 
		authorizationEndpointPath="authorization-code"
		loginPage="login.html"
		connector-ref="httpsConnector" 
		doc:name="OAuth provider module">
		<oauth2-provider:clients>
			<oauth2-provider:client clientId="customer-web-app" type="PUBLIC" clientName="Web UI" description="Javascript web UI">
				<oauth2-provider:authorized-grant-types>
					<oauth2-provider:authorized-grant-type>PASSWORD</oauth2-provider:authorized-grant-type>
				</oauth2-provider:authorized-grant-types>
				<oauth2-provider:scopes>
					<oauth2-provider:scope>READ</oauth2-provider:scope>
				</oauth2-provider:scopes>
			</oauth2-provider:client>
			<oauth2-provider:client clientId="admin-web-app" type="PUBLIC" clientName="Private Web UI" description="Javascript web UI">
				<oauth2-provider:authorized-grant-types>
					<oauth2-provider:authorized-grant-type>PASSWORD</oauth2-provider:authorized-grant-type>
					<oauth2-provider:authorized-grant-type>REFRESH_TOKEN</oauth2-provider:authorized-grant-type>
				</oauth2-provider:authorized-grant-types>
				<oauth2-provider:scopes>
					<oauth2-provider:scope>READ</oauth2-provider:scope>
					<oauth2-provider:scope>WRITE</oauth2-provider:scope>
				</oauth2-provider:scopes>
			</oauth2-provider:client>
		</oauth2-provider:clients>
	</oauth2-provider:config>

Приведенная выше конфигурация регистрирует 2 разных клиента для нашего API :

  • Веб-интерфейс: общедоступное веб-приложение, предоставляющее доступ только для чтения к защищенному списку продуктов.
  • Private Web UI: внутреннее приложение администратора, которое позволяет администраторам добавлять новые продукты.

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

GET https://localhost:8081/access-token?grant_type=password&client_id=admin-web-app&username=nialdarbey&password=hello123&scope=READ%20WRITE 

Это даст ответу что-то вроде:

{
  "scope":"READ WRITE",
  "expires_in":299,
  "token_type":"bearer",
  "access_token":"l8bFMEC9PA7NcpmHeTYS43Wl96_Y6LuIOhGci2zMJf0Qso9llgRLkgQjarMzUhvQz8vGVHmazrZ2C-Gjo20khg"
}


Запрос включает в себя обе области: READ и WRITE.
Они появляются в запрашиваемых областях для этого конкретного клиента. Области представляют широкие уровни доступа к потокам мулов. Предоставленный токен доступа должен быть отправлен с каждым запросом и может быть проверен Mule, чтобы убедиться, что он не истек или не был отозван, и что у него есть области, которые соответствуют определенному потоку. В следующем примере мы разрешаем только запросы, имеющие область ЗАПИСИ.

<flow name="createProduct" doc:name="createProduct">
    <oauth2-provider:validate scopes="WRITE" config-ref="oauth2-provider" doc:name="Validate WRITE scope" />
    <logger level="INFO" doc:name="Logger"/>
    <jdbc-ee:outbound-endpoint exchange-pattern="request-response" queryKey="select" queryTimeout="-1" connector-ref="Database" doc:name="Select Manufacturers">
        <jdbc-ee:query key="insert" value="insert into products (name, description) values (#[payload.name], #[payload.description])"/>
    </jdbc-ee:outbound-endpoint>
</flow>

Более точный контроль также может быть применен путем сравнения роли пользователя, для которого был выдан токен, с разрешенными ролями для потока.
Фильтр проверки имеет атрибут resourceOwnerRoles, чтобы указать их. (Детализация контроля доступа может быть либо в предоставлении, либо в роли).

<oauth2-provider:validate resourceOwnerRoles="Administrator" scopes="WRITE" config-ref="oauth2-provider" doc:name="Validate WRITE scope" />

Поскольку мы вступаем в мир нового предприятия, без сомнения, нам, возможно, придется обслуживать приложения, принадлежащие партнерам.
Представьте, что мы должны предоставить доступ к нашему сервису мобильному приложению. Нам нужно только зарегистрировать этого нового клиента в конфигурации нашего провайдера OAuth2. Обратите внимание, что тип предоставления для этой конфигурации TOKEN, который соответствует типу IMPLICIT в соответствии со спецификацией OAuth2. Это приведет к тому, что мы все станем свидетелями, когда веб-сайты позволят нам войти в систему с помощью наших учетных записей Google, Facebook или Twitter.

<oauth2-provider:client clientId="partner-smartphone-app" type="PUBLIC" clientName="Smartphone App" description="Smartphone app produced by partner">
    <oauth2-provider:redirect-uris>
        <oauth2-provider:redirect-uri>http://localhost*</oauth2-provider:redirect-uri>
    </oauth2-provider:redirect-uris>
    <oauth2-provider:authorized-grant-types>
        <oauth2-provider:authorized-grant-type>TOKEN</oauth2-provider:authorized-grant-type>
    </oauth2-provider:authorized-grant-types>
    <oauth2-provider:scopes>
        <oauth2-provider:scope>READ</oauth2-provider:scope>
    </oauth2-provider:scopes>
</oauth2-provider:client>

в заключение

Anypoint Enterprise Security также позволяет нам явно подписывать Сообщения и проверять входящие подписи и шифровать Сообщения с помощью 3 различных стратегий и 20 различных алгоритмов, а также расшифровывать входящие Сообщения. Могут быть случаи, когда вам приходится явно подписывать или кодировать Сообщения, которые вы отправляете третьим сторонам, или аналогичным образом дешифровать и проверять подписи третьих сторон. Для клиентов, над которыми у нас есть полный контроль над нашей архитектурой, достаточно использовать HTTPS, но для этих боковых случаев у вас есть все лучшее, что может предложить индустрия, в чрезвычайно простых конфигурациях, которые требует Мул. из вас! Вы можете скачать приведенный выше пример приложения здесь .