Рубрики
Без рубрики

Краткое Руководство По Использованию Cloud Foundry UAA

Узнайте, как использовать учетную запись пользователя Cloud Foundry и аутентификацию (CF UAA) в качестве службы управления идентификацией.

Автор оригинала: baeldung.

1. Обзор

Учетная запись пользователя и аутентификация Cloud Foundry (CF UAA) – это служба управления идентификацией и авторизации. Точнее, это поставщик OAuth 2.0, позволяющий аутентифицировать и выдавать токены клиентским приложениям.

В этом уроке мы рассмотрим основы настройки сервера CF UAA. Затем мы рассмотрим, как использовать его для защиты приложений сервера ресурсов.

Но прежде давайте проясним роль UAA в структуре авторизации OAuth 2.0 .

2. Облачный литейный завод UAA и OAuth 2.0

Давайте начнем с понимания того, как UAA соотносится со спецификацией OAuth 2.0.

Спецификация OAuth 2.0 определяет четыре участника , которые могут подключаться друг к другу: владелец ресурса, Сервер ресурсов, Клиент и Сервер авторизации.

Как поставщик OAuth 2.0, UAA играет роль сервера авторизации|/. Это означает, что его основной целью является выдача токенов доступа для клиентских приложений и проверка этих токенов для сервера ресурсов s.

Чтобы обеспечить взаимодействие этих участников, нам необходимо сначала настроить сервер UAA, а затем реализовать еще два приложения: одно в качестве клиента, а другое в качестве сервера ресурсов.

Мы будем использовать authorization_code grant поток с клиентом. И мы будем использовать авторизацию токенов на предъявителя с сервером ресурсов. Для более безопасного и эффективного рукопожатия мы будем использовать подписанные JWTS в качестве наших токенов доступа .

3. Настройка сервера UAA

Во-первых, мы установим UAA и заполним его некоторыми демонстрационными данными.

После установки мы зарегистрируем клиентское приложение с именем web app client. Затем мы создадим пользователя с именем appuser с двумя ролями resource.read и resource.write .

3.1. Установка

UAA-это веб-приложение Java, которое можно запускать в любом совместимом контейнере сервлетов. В этом уроке мы будем использовать Tomcat .

Давайте продолжим и скачаем войну UAA и внесем ее в свой Tomcat развертывание:

wget -O $CATALINA_HOME/webapps/uaa.war \
  https://search.maven.org/remotecontent?filepath=org/cloudfoundry/identity/cloudfoundry-identity-uaa/4.27.0/cloudfoundry-identity-uaa-4.27.0.war

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

3.2. Требуемая конфигурация

По умолчанию UAA считывает конфигурацию из uaa.yml в своем пути к классу. Но, поскольку мы только что загрузили файл war , нам будет лучше указать UAA пользовательское местоположение в нашей файловой системе.

Мы можем сделать это, установив свойство |/UAA_CONFIG_PATH :

export UAA_CONFIG_PATH=~/.uaa

В качестве альтернативы мы можем установить CLOUD_FOUNDRY_CONFIG_PATH. Или мы можем указать удаленное местоположение с помощью UAA_CONFIG_URL.

Затем мы можем скопировать Требуемая конфигурация UAA в наш путь конфигурации:

wget -qO- https://raw.githubusercontent.com/cloudfoundry/uaa/4.27.0/uaa/src/main/resources/required_configuration.yml \
  > $UAA_CONFIG_PATH/uaa.yml

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

3.3. Настройка источника данных

Итак, давайте настроим источник данных, в котором UAA будет хранить информацию о клиентах.

Для целей этого урока мы будем использовать HSQLDB:

export SPRING_PROFILES="default,hsqldb"

Конечно, поскольку это приложение Spring Boot, мы также могли бы указать это в uaa.yml в качестве свойства spring.profiles .

3.4. Настройка пары ключей JWS

Поскольку мы используем JWT, UAA должен иметь закрытый ключ для подписи каждого JWT, который выдает UAA.

OpenSSL делает это простым:

openssl genrsa -out signingkey.pem 2048
openssl rsa -in signingkey.pem -pubout -out verificationkey.pem

Сервер авторизации подпишет |/JWT с помощью закрытого ключа, а наш клиент и сервер ресурсов проверят эту подпись с помощью открытого ключа.

Мы экспортируем их в JWT_TOKEN_SIGNING_KEY и JWT_TOKEN_VERIFICATION_KEY :

export JWT_TOKEN_SIGNING_KEY=$(cat signingkey.pem)
export JWT_TOKEN_VERIFICATION_KEY=$(cat verificationkey.pem)

Опять же, мы могли бы указать их в uaa.yml с помощью токена jwt.ключ подписи и jwt.token.verification-key свойства.

3.5. Запуск UAA

Наконец, давайте начнем все сначала:

$CATALINA_HOME/bin/catalina.sh run

На данный момент у нас должен быть работающий AAA-сервер, доступный по адресу http://localhost:8080/uaa .

Если мы пойдем в http://localhost:8080/uaa/info , затем мы увидим некоторую базовую информацию о запуске

3.6. Установка клиента командной строки UAA

Клиент командной строки CF UAA является основным инструментом для администрирования UAA , но для его использования нам сначала нужно установить Ruby :

sudo apt install rubygems
gem install cf-uaac

Затем мы можем настроить uac так, чтобы он указывал на наш запущенный экземпляр UAA:

uaac target http://localhost:8080/uaa

Обратите внимание, что если мы не хотим использовать клиент командной строки, мы, конечно, можем использовать HttpClient UAA.

3.7. Заполнение Клиентов и Пользователей С помощью UAAC

Теперь, когда у нас установлен uaac , давайте заполним UAA некоторыми демонстрационными данными. Как минимум, нам понадобятся:/| клиент , пользователь и resource.read и resource.write группы.

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

uaac token client get admin -s adminsecret

(Конечно, нам определенно нужно изменить эту учетную запись – через oauth-clients.xml файл – перед отправкой!)

В принципе, мы можем прочитать эту команду как: “Дайте мне токен, используя client учетные данные с идентификатором client_id admin и s ecret adminsecret “.

Если все пойдет хорошо, мы увидим сообщение об успехе:

Successfully fetched token via client credentials grant.

Токен хранится в состоянии uaac .

Теперь, работая как администратор , мы можем зарегистрировать клиента по имени клиент веб-приложения с добавить клиента:

uaac client add webappclient -s webappclientsecret \ 
--name WebAppClient \ 
--scope resource.read,resource.write,openid,profile,email,address,phone \ 
--authorized_grant_types authorization_code,refresh_token,client_credentials,password \ 
--authorities uaa.resource \ 
--redirect_uri http://localhost:8081/login/oauth2/code/uaa

А также мы можем зарегистрировать пользователя по имени пользователь приложения с добавить пользователя:

uaac user add appuser -p appusersecret --emails [email protected]

Далее мы добавим две группы – resource.read и resource.write – с помощью group add:

uaac group add resource.read
uaac group add resource.write

И, наконец, мы назначим эти группы appuser с member add:

uaac member add resource.read appuser
uaac member add resource.write appuser

Фу! Итак, то, что мы сделали до сих пор, это:

  • Установлен и настроен UAA
  • Установлен uaac
  • Добавлен демо-клиент, пользователи и группы

Итак, давайте запомним эти фрагменты информации и перейдем к следующему шагу.

4. Клиент OAuth 2.0

В этом разделе мы будем использовать Spring Boot для создания клиентского приложения OAuth 2.0 .

4.1. Настройка приложения

Давайте начнем с доступа к Spring Initializr и создания веб-приложения Spring Boot. Мы выбираем только Web и Клиент OAuth2 компоненты:


    org.springframework.boot
    spring-boot-starter-web


    org.springframework.boot
    spring-boot-starter-oauth2-client

В этом примере мы использовали версию 2.1.3 Spring Boot.

Далее, нам нужно зарегистрировать нашего клиента, веб-приложение клиент .

Проще говоря, нам нужно будет дать приложению идентификатор клиента, секрет клиента, и UAA issueruri . Мы также определим области OAuth 2.0, которые этот клиент хочет, чтобы пользователь предоставил ему:

#registration
spring.security.oauth2.client.registration.uaa.client-id=webappclient
spring.security.oauth2.client.registration.uaa.client-secret=webappclientsecret
spring.security.oauth2.client.registration.uaa.scope=resource.read,resource.write,openid,profile

#provider
spring.security.oauth2.client.provider.uaa.issuer-uri=http://localhost:8080/uaa/oauth/token

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

И поскольку мы уже используем порт 8080 для UAA, давайте запустим это на 8081:

server.port=8081

4.2. Вход в систему

Теперь, если мы получим доступ к пути /login , у нас должен быть список всех зарегистрированных клиентов. В нашем случае у нас есть только один зарегистрированный клиент:

Нажатие на ссылку перенаправит нас на страницу входа в систему UAA:

Здесь давайте войдем в систему с помощью app user/app user secret .

Отправка формы должна перенаправить нас на форму утверждения, в которой пользователь может разрешить или запретить доступ к нашему клиенту:

Затем пользователь может предоставить необходимые привилегии. Для наших целей мы выберем все , кроме resource:write.

Все, что проверяет пользователь, будет областями действия результирующего маркера доступа.

Чтобы доказать это, мы можем скопировать токен, показанный в пути к индексу, http://localhost:8081 , и декодировать его с помощью отладчика JWT . Мы должны увидеть области, которые мы проверили на странице утверждения:

{
  "jti": "f228d8d7486942089ff7b892c796d3ac",
  "sub": "0e6101d8-d14b-49c5-8c33-fc12d8d1cc7d",
  "scope": [
    "resource.read",
    "openid",
    "profile"
  ],
  "client_id": "webappclient"
  // more claims
}

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

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

Завершенный сервер ресурсов будет иметь два защищенных API: один, который требует resource.read scope, и другой, который требует resource.write.

Мы увидим, что клиент, используя предоставленные нами области, сможет вызывать read API, но не write.

5. Сервер ресурсов

На сервере ресурсов размещаются защищенные ресурсы пользователя.

Он аутентифицирует клиентов через заголовок Authorization и консультируется с сервером авторизации – в нашем случае это UAA.

5.1. Настройка Приложения

Чтобы создать наш сервер ресурсов, мы снова будем использовать Spring Initializr для создания веб-приложения Spring Boot. На этот раз мы выберем Web и Сервер ресурсов OAuth2 компоненты:


    org.springframework.boot
    spring-boot-starter-oauth2-resource-server


    org.springframework.boot
    spring-boot-starter-web

Как и в случае с клиентским приложением, мы используем версию 2.1.3 Spring Boot.

Следующим шагом является указание местоположения запущенного CF UAA в Следующим шагом является указание местоположения запущенного CF UAA в файл:

spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/uaa/oauth/token

Конечно, давайте и здесь выберем новый порт. 8082 будет работать нормально:

server.port=8082

И это все! У нас должен быть работающий сервер ресурсов, и по умолчанию для всех запросов потребуется действительный токен доступа в заголовке Authorization .

5.2. Защита API Сервера ресурсов

Далее, давайте добавим некоторые конечные точки, которые стоит защищать.

Мы добавим RestController с двумя конечными точками, одна из которых авторизована для пользователей, имеющих область resource.read , а другая-для пользователей, имеющих область resource.write:

@GetMapping("/read")
public String read(Principal principal) {
    return "Hello write: " + principal.getName();
}

@GetMapping("/write")
public String write(Principal principal) {
    return "Hello write: " + principal.getName();
}

Затем мы переопределим конфигурацию загрузки Spring по умолчанию для защиты двух ресурсов:

@EnableWebSecurity
public class OAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()
        .antMatchers("/read/**").hasAuthority("SCOPE_resource.read")
        .antMatchers("/write/**").hasAuthority("SCOPE_resource.write")
        .anyRequest().authenticated()
      .and()
        .oauth2ResourceServer().jwt();
   }
}

Обратите внимание, что области, указанные в маркере доступа, имеют префикс SCOPE_ при переводе в Spring Security GrantedAuthority .

5.3. Запрос Защищенного Ресурса От Клиента

Из клиентского приложения мы вызовем два защищенных ресурса с помощью RestTemplate. Перед выполнением запроса мы извлекаем токен доступа из контекста и добавляем его в заголовок Authorization :

private String callResourceServer(OAuth2AuthenticationToken authenticationToken, String url) {
    OAuth2AuthorizedClient oAuth2AuthorizedClient = this.authorizedClientService.
      loadAuthorizedClient(authenticationToken.getAuthorizedClientRegistrationId(), 
      authenticationToken.getName());
    OAuth2AccessToken oAuth2AccessToken = oAuth2AuthorizedClient.getAccessToken();

    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Bearer " + oAuth2AccessToken.getTokenValue());

    // call resource endpoint

    return response;
}

Обратите внимание, однако, что мы можем удалить этот шаблон, если мы используем WebClient вместо RestTemplate .

Затем мы добавим два вызова к конечным точкам сервера ресурсов:

@GetMapping("/read")
public String read(OAuth2AuthenticationToken authenticationToken) {
    String url = remoteResourceServer + "/read";
    return callResourceServer(authenticationToken, url);
}

@GetMapping("/write")
public String write(OAuth2AuthenticationToken authenticationToken) {
    String url = remoteResourceServer + "/write";
    return callResourceServer(authenticationToken, url);
}

Как и ожидалось, вызов API/ read будет успешным, но не вызов/ write . Статус HTTP 403 говорит нам, что пользователь не авторизован.

6. Заключение

В этой статье мы начали с краткого обзора OAuth 2.0, поскольку он является базовой основой для UAA, сервера авторизации OAuth 2.0. Затем мы настроили его для выдачи токенов доступа для клиента и защиты приложения сервера ресурсов.

Полный исходный код примеров доступен на Github .