Cloud Foundry UAAのクイックガイド

  • link:/category/cloud/ [クラウド]

  • link:/category/security-2/ [セキュリティ]

  • OAuth

1. 概要

  • Cloud Foundryユーザーアカウントおよび認証(CF UAA)は、ID管理および承認サービスです。*より正確には、認証を許可し、クライアントアプリケーションにトークンを発行するOAuth 2.0プロバイダーです。

    このチュートリアルでは、CF UAAサーバーのセットアップの基本について説明します。 次に、リソースサーバーアプリケーションを保護するためにそれを使用する方法を見ていきます。
    しかし、前に、https://auth0.com/docs/protocols/oauth2 [OAuth 2.0]承認フレームワークでのUAAの役割を明確にしましょう。

*2. Cloud Foundry UAAおよびOAuth 2.0 *

UAAがOAuth 2.0仕様にどのように関係するかを理解することから始めましょう。
OAuth 2.0仕様では、相互に接続できるhttps://tools.ietf.org/html/rfc6749#section-1.1[4人の参加者]を定義しています。リソース所有者、リソースサーバー、クライアント、承認サーバーです。
OAuth 2.0プロバイダーとして、UAAは_authorizationサーバーの役割を果たします。これは、*その主な目標は、_client_アプリケーションのアクセストークンを発行し、__ resource server__sのトークンを検証することです*。
これらの参加者の相互作用を可能にするには、まずUAAサーバーをセットアップしてから、さらに2つのアプリケーションを実装する必要があります。1つはクライアントとして、もう1つはリソースサーバーとして。
クライアントでhttps://tools.ietf.org/html/rfc6749#section-1.3.1[_authorization_code_ grant]フローを使用します。 そして、リソースサーバーでBearerトークン認証を使用します。 より安全で効率的なハンドシェイクのために、署名済みのJWTをhttps://tools.ietf.org/html/rfc6749#section-1.4 [アクセストークン]として使用します。

3. UAAサーバーのセットアップ

まず、* UAAをインストールし、デモデータを入力します。*
インストールしたら、_webappclient._というクライアントアプリケーションを登録します。次に、_resource.read_と_resource.write_の2つのロールを持つ_appuser_という名前のユーザーを作成します。

* 3.1。 インストール*

UAAは、あらゆる準拠サーブレットコンテナで実行できるJava Webアプリケーションです。 このチュートリアルでは、https://tomcat.apache.org/whichversion.html [use Tomcat]を使用します。
先に進み、* https://search.maven.org/search?q = g:org.cloudfoundry.identity%20AND%20a:cloudfoundry-identity-uaa [UAA war]をダウンロードして、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._でリモートロケーションを指定できます。
次に、https://raw.githubusercontent.com/cloudfoundry/uaa/4.27.0/uaa/src/main/resources/required_configuration.yml [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行を削除していることに注意してください。

3.3. データソースの構成

そこで、UAAがクライアントに関する情報を格納するデータソースを設定しましょう。*
このチュートリアルでは、HSQLDBを使用します。
export SPRING_PROFILES="default,hsqldb"
もちろん、これはSpring Bootアプリケーションであるため、__ uaa.yml __as the _spring.profiles_プロパティでこれを指定することもできます。

3.4. JWSキーペアの構成

JWTを使用しているため、* UAAはUAAが発行する各JWTに署名するための秘密鍵を持っている必要があります。*
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)
繰り返しますが、_jwt.token.signing-key_および_jwt.token.verification-key_プロパティを介してこれらをth​​ese_uaa.yml_で指定できます。

3.5. UAAの起動

最後に、物事を始めましょう:
$CATALINA_HOME/bin/catalina.sh run
この時点で、http:// localhost:8080 / uaa [_http:// localhost:8080 / uaa_]で使用可能な作業UAAサーバーが必要です。
http:// localhost:8080 / uaa / info [_http:// localhost:8080 / uaa / info_]にアクセスすると、いくつかの基本的なスタートアップ情報が表示されます

* 3.6。 UAAコマンドラインクライアントのインストール*

  • CF UAAコマンドラインクライアントはUAA *を管理するためのメインツールですが、使用するにはhttps://rubygems.org/[Rubyを最初にインストール]する必要があります。

sudo apt install rubygems
gem install cf-uaac
次に、UAAの実行中のインスタンスを指すように_uaac_を構成できます。
uaac target http://localhost:8080/uaa
コマンドラインクライアントを使用したくない場合は、もちろんUAAのHTTPクライアントを使用できます。

* 3.7。 UAAC *を使用したクライアントとユーザーの入力

_uaac_がインストールされたので、デモデータをUAAに入力しましょう。 *少なくとも、次のものが必要です:_client _、_ user_、および_resource.read_および_resource.write_グループ。*
したがって、管理を行うには、自分で認証する必要があります。 UAAに同梱されているデフォルトの管理者を選択します。これには、他のクライアント、ユーザー、グループを作成する権限があります:
uaac token client get admin -s adminsecret
(もちろん、必ずこのアカウントを変更する必要があります* https://github.com/cloudfoundry/uaa/blob/master/uaa/src/main/webapp/WEB-INF/spring/oauth- clients.xml [oauth-clients.xml]ファイル–出荷前!)
基本的に、このコマンドは次のように読み取ることができます。
すべてうまくいけば、成功メッセージが表示されます。
Successfully fetched token via client credentials grant.
トークンは_uaac_‘s状態で保存されます。
*これで、_admin_として動作し、_webappclient_というクライアントをwith__ client add:__ *と登録できます。
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
*また、_user add:_ *で_appuser_という名前のユーザーを登録できます。
uaac user add appuser -p appusersecret --emails [email protected]
次に、with__ group add:__を使用して、2つのグループ_resource.read_および_resource.write_を追加します。
uaac group add resource.read
uaac group add resource.write
そして最後に、これらのグループを_appuser_ with__ 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。 アプリケーションのセットアップ*

https://start.spring.io/[Spring Initializr]にアクセスし、Spring Boot Webアプリケーションを生成することから始めましょう。 _Web_および_OAuth2 Client_コンポーネントのみを選択します。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
この例では、https://search.maven.org/search?q = g:org.springframework.boot%20AND%20a:spring-boot-starter-parentを使用しました
次に、**クライアント_webapp _ ** __ * client * .__を登録する必要があります
簡単に言うと、アプリに_client-id、_ _client-secret、_およびUAAの_issuer-uri_を与える必要があります。 また、このクライアントがユーザーに許可する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
これらのプロパティの詳細については、https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/security/oauth2/のJavaドキュメントをご覧ください。 client / OAuth2ClientProperties.Registration.html [登録]およびhttps://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientProperties.Provider.html [プロバイダ]豆。
そして、UAAには既にポート8080を使用しているので、8081でこれを実行してみましょう。
server.port=8081

* 4.2。 ログインする*

_ / login_パスにアクセスすると、登録されているすべてのクライアントのリストが必要になります。 この場合、登録されているクライアントは1つだけです。
link:/uploads/uaa-1-100x19.png%20100w [] *リンクをクリックすると、UAAログインページにリダイレクトされます。*
link:/uploads/uaa1-100x29.png%20100w []
ここで、_appuser / appusersecret_でログインしてみましょう。
*フォームを送信すると、ユーザーがクライアントへのアクセスを許可または拒否できる承認フォームにリダイレクトされます:*
link:/uploads/uaa2-100x44.png%20100w []
ユーザーは、必要な特権を付与できます。 この目的のために、* resource:write ._ *を除くすべてを選択します。
ユーザーがチェックするものはすべて、結果のアクセストークンのスコープになります。
これを証明するために、インデックスパスhttp:// localhost:8081 / [_http:// localhost:8081_]に表示されているトークンをコピーし、https://jwt.io/#debugger-ioを使用してデコードできます。 [JWTデバッガー]。 *承認ページでチェックしたスコープが表示されます:*
{
  "jti": "f228d8d7486942089ff7b892c796d3ac",
  "sub": "0e6101d8-d14b-49c5-8c33-fc12d8d1cc7d",
  "scope": [
    "resource.read",
    "openid",
    "profile"
  ],
  "client_id": "webappclient"
  // more claims
}
クライアントアプリケーションがこのトークンを受け取ると、ユーザーを認証でき、ユーザーはアプリにアクセスできるようになります。
さて、*データをまったく表示しないアプリはあまり有用ではないので、次のステップはリソースサーバー*を立ち上げて、ユーザーのデータを保持し、クライアントをそれに接続することです。
完成したリソースサーバーには、2つの保護されたAPIがあります。1つは_resource.read_スコープを必要とし、もう1つは_resource.write._を必要とします
表示されるのは、*クライアントが、許可したスコープを使用して、_read_ APIを呼び出すことはできますが、_write ._ *は呼び出せないということです。

5. リソースサーバー

*リソースサーバーは、ユーザーの保護されたリソースをホストします。*
_Authorization_ヘッダーを介してクライアントを認証し、承認サーバーと相談します。この例では、UAAです。

* 5.1。 アプリケーションのセットアップ*

リソースサーバーを作成するには、https://start.spring.io/ [Spring Initializr]を再度使用して、Spring Boot Webアプリケーションを生成します。 今回は、_Web_および_OAuth2 Resource Server_コンポーネントを選択します。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
クライアントアプリケーションと同様に、https://search.maven.org/search?q = g:org.springframework.boot%20AND%20a:spring-boot-starter-parentを使用しています。
*次のステップは、_application.properties_ファイルで実行中のCF UAAの場所を示すことです*
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/uaa/oauth/token
もちろん、ここでも新しいポートを選択しましょう。 8082は正常に機能します。
server.port=8082
以上です! 動作するリソースサーバーが必要です。デフォルトでは、すべてのリクエストには__Authorization __headerの有効なアクセストークンが必要です。

* 5.2。 リソースサーバーAPIの保護*

次に、保護する価値のあるエンドポイントをいくつか追加します。
2つのエンドポイントを持つ_RestController_を追加します。1つは_resource.read_スコープを持つユーザーに許可され、もう1つは_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 Boot構成*をオーバーライドして、2つのリソースを保護します:
@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();
   }
}
*アクセストークンで提供されるスコープは、https://www.baeldung.com/role-and-privilege-for-spring-security-registration [Spring Security _GrantedAuthority _] *に変換されるときに、_SCOPE__のプレフィックスが付けられることに注意してください。

* 5.3。 クライアントから保護されたリソースを要求する*

クライアントアプリケーションから、_RestTemplate._を使用して2つの保護されたリソースを呼び出します。リクエストを行う前に、コンテキストからアクセストークンを取得し、_Authorization_ header __:__に追加します。
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;
}
ただし、https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#servlet-webclient [_RestTemplate_の代わりにuse__WebClient_]を使用すると、この定型文を削除できることに注意してください。
次に、リソースサーバーエンドポイントに2つの呼び出しを追加します。
@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);
}
予想どおり、* / _ read_ APIの呼び出しは成功しますが、/ _ write_の呼び出しは成功しません。* HTTPステータス403は、ユーザーが認証されていないことを示しています。

6. 結論

この記事では、OAuth 2.0承認サーバーであるUAAの基本基盤であるOAuth 2.0の簡単な概要から始めました。 次に、クライアントにアクセストークンを発行し、リソースサーバーアプリケーションを保護するように構成しました。
サンプルの完全なソースコードは、https://github.com/eugenp/tutorials/tree/master/cloud-foundry-uaa [Github上]で入手できます。