

AWS Mainframe Modernization Service (マネージドランタイム環境エクスペリエンス) は、新規のお客様に公開されなくなりました。 AWS Mainframe Modernization Service (マネージドランタイム環境エクスペリエンス) と同様の機能については、 AWS Mainframe Modernization Service (セルフマネージドエクスペリエンス) をご覧ください。既存のお客様は、通常どおりサービスを引き続き使用できます。詳細については、[AWS 「 Mainframe Modernization の可用性の変更](https://docs.aws.amazon.com/m2/latest/userguide/mainframe-modernization-availability-change.html)」を参照してください。

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Gapwalk アプリケーションのセキュリティを設定する
<a name="ba-runtime-security"></a>

以下のトピックでは、Gapwalk アプリケーションのセキュリティを保護する方法について説明します。

Transform AWS for Mainframe フレームワークの使用が確実に安全になるように、適切な設定を提供するのはお客様の責任です。

セキュリティ関連の機能はすべてデフォルトで無効になっています。認証 (および CSRF、XSS、CSP など) を有効にするには、`gapwalk-application.security` を `enabled` に、また `gapwalk-application.security.identity` を `oauth` に設定します。

**Topics**
+ [Gapwalk アプリケーションに URI アクセシビリティを設定する](ba-runtime-filteringURIs.md)
+ [Gapwalk アプリケーションの認証の設定](ba-runtime-auth.md)
+ [メインフレームランタイムの AWS 変換のレート制限を設定する](ba-runtime-rate-limiting.md)

# Gapwalk アプリケーションに URI アクセシビリティを設定する
<a name="ba-runtime-filteringURIs"></a>

このトピックでは、Gapwalk アプリケーションに URI のフィルタリングを設定する方法について説明します。この機能には ID プロバイダー (IdP) が不要です。

URI のリストをブロックするには、モダナイズしたアプリケーションの `application-main.yml` に次の 2 行を追加し、*URI-1*、*URI-2* などをブロックする URI に置き換えます。

```
gapwalk-application.security.filterURIs: enabled
gapwalk-application.security.blockedURIs: URI-1, URI-2, URI-3
```

# Gapwalk アプリケーションの認証の設定
<a name="ba-runtime-auth"></a>

Gapwalk アプリケーションに OAuth2 認証を構成するには、ID プロバイダー (IdP) を設定し、それをアプリケーションに組み込む必要があります。このガイドでは、IdP として Amazon Cognito または Keycloak を使用する手順について説明します。Amazon Cognito を使用すると、アプリケーションの構成ファイルを Cognito ユーザープールの情報で更新できます。Keycloak を使用すると、アプリケーションの API およびリソースへのアクセスを、ユーザーに割り当てられたロールに基づいて制御できます。

**Topics**
+ [Amazon Cognito で Gapwalk OAuth2 認証を設定する](ba-runtime-auth-cognito.md)
+ [Keycloak で Gapwalk OAuth2 認証を設定する](ba-runtime-auth-keycloak.md)

# Amazon Cognito で Gapwalk OAuth2 認証を設定する
<a name="ba-runtime-auth-cognito"></a>

このトピックでは、Amazon Cognito を ID プロバイダー (IdP) として使用し、Gapwalk アプリケーションに OAuth2 認証を設定する方法について説明します。

## 前提条件
<a name="ba-runtime-auth-cognito-prereq"></a>

このチュートリアルでは、IdP として Amazon Cognito を使用し、モダナイズされたプロジェクトとして PlanetDemo を使用します。

他の外部 ID プロバイダーも使用できます。ClientRegistration 情報は IdP から取得する必要があり、Gapwalk の認証に必要です。詳細については、「[Amazon Cognito デベロッパーガイド](https://docs.aws.amazon.com/cognito/latest/developerguide/)」をご覧ください。

**ClientRegistration 情報:**

client-id  
ClientRegistration の ID。この例では、PlanetsDemo になります。

client-secret  
クライアントシークレット。

認可エンドポイント  
認可サーバーの認可エンドポイント URI。

トークンエンドポイント  
認可サーバーのトークンエンドポイント URI。

jwks エンドポイント  
認可サーバーによって発行された JSON ウェブ署名を検証するためのキーを含む JSON ウェブキー (JWK) の取得に使用される URI。

リダイレクト URI  
アクセスが許可された場合に認可サーバーがエンドユーザーをリダイレクトする URI。

## Amazon Cognito のセットアップ
<a name="cog-setup"></a>

まず、テストの目的でデプロイした Gapwalk アプリケーションで使用する、Amazon Cognito ユーザープールとユーザーを作成して設定します。

**注記**  
他の IdP を使用している場合は、このステップを省略できます。

**ユーザープールを作成する**

1. で Amazon Cognito に移動 AWS マネジメントコンソール し、 AWS 認証情報を使用して認証します。

1. **[ユーザープール]** を選択します。

1. **[ユーザープールを作成]** を選択します。

1. **[サインインエクスペリエンスを設定]** では、**[Cognito ユーザープール]** のデフォルトプロバイダータイプをそのまま使用します。**[Cognito ユーザープールのサインインオプション]** を 1 つまたは複数選択できます。ここでは、**[ユーザー名]** を選択し、**[次へ]** を選択します。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/cog-auth-provider.png)

1. **[セキュリティ要件を設定]** では、デフォルトのまま使用します。**[MFA なし]** を選択して **[多要素認証]** を無効にし、**[次へ]** を選択します。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/cog-sec-requirements.png)

1. セキュリティ対策として **[自己登録を有効化]** を無効にして、**[次へ]** を選択します。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/cog-config-sign-up.png)

1. **[Cognito で E メールを送信]** を選択し、**[次へ]** を選択します。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/cog-email.png)

1. **[アプリケーションを統合]** で、ユーザープールの名前を指定します。**[ホストされた認証ページ]** で、**[Cognito でホストされた UI を使用]** を選択します。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/cog-domain.png)

1. わかりやすくするために、**[ドメイン]** で **[Cognito ドメインを使用する]** を選択し、ドメインプレフィックス (例: `https://planetsdemo`) を入力します。デモアプリケーションはクライアントとして追加する必要があります。

   1. **[最初のアプリケーションクライアント]** で **[秘密クライアント]** を選択します。アプリのクライアント名 (**planetsdemo** など) を入力し、**[クライアントのシークレットを生成する]** を選択します。

   1. **[許可されているコールバック URL]** に、認証後にユーザーをリダイレクトする URL を入力します。URL は `/login/oauth2/code/cognito` で終わる必要があります。例えば、このアプリケーションおよびバックエンドの Gapwalk と BAC アプリケーションの場合は次のようになります:

      ```
      http://localhost:8080/bac
            http://localhost:8080/bac/login/oauth2/code/cognito
            http://localhost:8080/gapwalk-application
            http://localhost:8080/gapwalk-application/login/oauth2/code/cognito
            http://localhost:8080/planetsdemo
            http://localhost:8080/planetsdemo/login/oauth2/code/cognito
      ```

      URL は後で編集できます。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/cog-urls.png)

   1. **[許可されているサインアウト URL]** に、アプリケーションがユーザーをサインアウトする際の、Amazon Cognito によるリダイレクト先のページの URL を入力します。例えば、バックエンドの Gapwalk と BAC アプリケーションの場合は次のようになります:

      ```
      http://localhost:8080/bac/logout
      http://localhost:8080/gapwalk-application/logout
      http://localhost:8080/planetsdemo/logout
      ```

      URL は後で編集できます。

   1. **[高度なアプリケーションクライアントの設定]** と **[属性の読み込みおよび書き込みアクセス権限]** セクションはデフォルト値のままにします。

   1. [**次へ**] を選択します。

1. **[確認して作成]** で、選択を確認し、**[ユーザープールを作成]** を選択します。

詳細については、「[ユーザープールの作成](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-user-pool.html)」を参照してください。

**ユーザーの作成**

自己登録は無効になっているので、Amazon Cognito ユーザーを作成します。 AWS マネジメントコンソールの Amazon Cognito コンソールに移動します。作成したユーザープールを選択し、**[ユーザー]** で **[ユーザーを作成]** を選択します。

**[ユーザー情報]** で、**[E メールで招待を送信]** を選択し、ユーザー名とメールアドレスを入力して、**[パスワードの生成]** を選択します。**[ユーザーの作成]** を選択します。

**ロールの作成**

**[グループ]** タブで、3 つのグループ (SUPER\$1ADMIN、ADMIN、USER) を作成し、ユーザーをこれらのグループの 1 つ以上に関連付けます。これらのロールは、後に Gapwalk アプリケーションによって ROLE\$1SUPER\$1ADMIN、ROLE\$1ADMIN、および ROLE\$1USER にマッピングされます。これで、アクセスが制限された API REST の呼び出しが可能になります。

アプリケーションは、複数の OAuth2 ID プロバイダーで動作する階層scope-to-roleマッピングを実装します。Cognito によって発行された JWT トークンがリソースサーバーの認可に使用されると、トークンで定義されたスコープは自動的に対応するロールにマッピングされます。

## Gapwalk アプリケーションへの Amazon Cognito の統合
<a name="integrate-cognito"></a>

Amazon Cognito ユーザープールとユーザーの準備ができたので、モダナイズしたアプリケーションの `application-main.yml` ファイルに移動し、次のコードを追加します。

```
gapwalk-application.security: enabled
gapwalk-application.security.identity: oauth
gapwalk-application.security.issuerUri: https://cognito-idp.<region-id>.amazonaws.com/<pool-id>
gapwalk-application.security.domainName: <your-cognito-domain>

spring:
  security:
    oauth2:
      client:
        registration:
          cognito:
            client-id: <client-id>
            client-name: <client-name>
            client-secret: <client-secret>
            provider: cognito
            authorization-grant-type: authorization_code
            scope: openid
            redirect-uri: "<redirect-uri>"
        provider:
          cognito:
            issuer-uri: ${gapwalk-application.security.issuerUri}
            authorization-uri: ${gapwalk-application.security.domainName}/oauth2/authorize
            jwk-set-uri: ${gapwalk-application.security.issuerUri}/.well-known/jwks.json
            token-uri: ${gapwalk-application.security.domainName}/oauth2/token
            user-name-attribute: username
      resourceserver:
        jwt:
          jwk-set-uri: ${gapwalk-application.security.issuerUri}/.well-known/jwks.json
```

説明に従って、次のプレースホルダーを置き換えます。

1. で Amazon Cognito に移動 AWS マネジメントコンソール し、 AWS 認証情報を使用して認証します。

1. **[ユーザープール]** を選択して、作成したユーザープールを選択します。*プール ID* は、**[ユーザープール ID]** にあります。

1. **[アプリケーションの統合]** を選択し、*your-cognito-domain* を検索して、**[アプリクライアントと分析]** に移動してアプリを選択します。

1. **[アプリケーションクライアント: yourApp]** では、*クライアント名*、*クライアント ID*、*クライアントシークレット* (**[クライアントシークレットを表示]**) を確認できます。

1. *region-id* は、Amazon Cognito ユーザーとユーザープールを作成した AWS リージョン ID に対応します。例えば、`eu-west-3` などです。

1. *redirect-uri* には、**許可されているコールバック URL** に指定した URI を入力します。今回の例では、`http://localhost:8080/planetsdemo/login/oauth2/code/cognito` となります。

これで Gapwalk アプリケーションをデプロイし、以前に作成したユーザーを使用してアプリケーションにサインインできます。

# Keycloak で Gapwalk OAuth2 認証を設定する
<a name="ba-runtime-auth-keycloak"></a>

このトピックでは、Keycloak を ID プロバイダー (IdP) として使用し、Gapwalk アプリケーションに OAuth2 認証を設定する方法について説明します。このチュートリアルでは Keycloak 24.0.0 を使用します。

## 前提条件
<a name="ba-runtime-auth-keycloak-prereq"></a>
+ [Keycloak](https://www.keycloak.org/)
+ Gapwalk アプリケーション

## Keycloak の設定
<a name="keycloak-setup"></a>

1. ウェブブラウザで Keycloak ダッシュボードに移動します。デフォルトの認証情報は admin/admin です。左上のナビゲーションバーに移動し、次の画像に示すように **demo** という名前の領域を作成します。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/ba-runtime-auth-keycloak_2.png)

1. **app-demo** という名前のクライアントを作成します。  
![\[User interface for creating a new client in an authentication management system.\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/ba-runtime-auth-keycloak_3.jpg)

   `localhost:8080` は Gapwalk アプリケーションのアドレスに置き換えてください。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/ba-runtime-auth-keycloak_4.png)  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/ba-runtime-auth-keycloak_5.png)

1. クライアントシークレットを取得するために、**[クライアント]**、**[app-demo]**、**[認証情報]** を選択します。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/ba-runtime-auth-keycloak_6.jpg)

1. **[クライアント]**、**[クライアントの範囲]**、**[事前定義されたマッパーを追加]** の順に選択します。**[領域ロール]** を選択します。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/ba-runtime-auth-keycloak_7.jpg)

1. 次の画像に示す構成で領域ロールを変更します。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/ba-runtime-auth-keycloak_8.jpg)

1. **[トークンクレーム名]** に定義した値を覚えておいてください。この値は、Gapwalk の `gapwalk-application.security.claimGroupName` プロパティを設定する際に必要になります。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/ba-runtime-auth-keycloak_9.jpg)

1. **[領域ロール]** を選択し、**SUPER\$1ADMIN**、**ADMIN**、**USER** の 3 つのロールを作成します。これらのロールは、後に Gapwalk アプリケーションによって `ROLE_SUPER_ADMIN`、`ROLE_ADMIN`、および `ROLE_USER` にマッピングされます。これで、アクセスが制限された API REST の呼び出しが可能になります。  
![\[alt_text\]](http://docs.aws.amazon.com/ja_jp/m2/latest/userguide/images/ba-runtime-auth-keycloak_10.jpg)

## Keycloak を Gapwalk アプリケーションに統合する
<a name="gapwalk-setup"></a>

`application-main.yml` を次のように変更します:

```
gapwalk-application.security: enabled
gapwalk-application.security.identity: oauth
gapwalk-application.security.issuerUri: http://<KEYCLOAK_SERVER_HOSTNAME>/realms/<YOUR_REALM_NAME>
gapwalk-application.security.claimGroupName: "keycloak:groups"

gapwalk-application.security.userAttributeName: "preferred_username"
# Use "username" for cognito, 
#     "preferred_username" for keycloak
#      or any other string

spring:
  security:
    oauth2:
      client:
        registration:
          demo:
            client-id: <YOUR_CLIENT_ID>
            client-name: Demo App
            client-secret: <YOUR_CLIENT_SECRET>
            provider: keycloak
            authorization-grant-type: authorization_code
            scope: openid
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
        provider:
          keycloak:
            issuer-uri: ${gapwalk-application.security.issuerUri}
            authorization-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/auth
            jwk-set-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/certs
            token-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/token
            user-name-attribute: ${gapwalk-application.security.userAttributeName}
      resourceserver:
        jwt:
          jwk-set-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/certs
```

*<KEYCLOAK\$1SERVER\$1HOSTNAME>*、*<YOUR\$1REALM\$1NAME>*、*<YOUR\$1CLIENT\$1ID>*、および *<YOUR\$1CLIENT\$1SECRET>* を、Keycloak サーバーのホスト名、領域名、クライアント ID、およびクライアントシークレットに置き換えてください。

# メインフレームランタイムの AWS 変換のレート制限を設定する
<a name="ba-runtime-rate-limiting"></a>

AWS メインフレームランタイムの変換には、過剰なリクエストや潜在的な不正使用から gapwalk アプリケーションを保護するためのレート制限機能が組み込まれています。レート制限システムは、トークンバケットアルゴリズムを使用して、バースト容量と持続的なレート制限の両方を提供します。

**Topics**
+ [レート制限の概要](#ba-runtime-rate-limiting-overview)
+ [設定プロパティ](#ba-runtime-rate-limiting-config)
+ [レート制限を有効にする](#ba-runtime-rate-limiting-enable)
+ [クライアント識別](#ba-runtime-rate-limiting-client-id)
+ [レート制限ヘッダー](#ba-runtime-rate-limiting-headers)
+ [メモリ管理](#ba-runtime-rate-limiting-memory)

## レート制限の概要
<a name="ba-runtime-rate-limiting-overview"></a>

レート制限システムには以下の機能があります。

**トークンバケットアルゴリズム**  
+ 設定されたバースト容量までのバーストトラフィックを許可する
+ 1 分あたりのリクエスト数に基づいてトークンを一定の割合で補充します
+ 正当なトラフィックスパイクをブロックすることなく、スムーズなレート制限を提供

**クライアント ID**  
+ プロキシサポートを使用して IP アドレスでクライアントを識別する
+ X-Forwarded-For ヘッダーと X-Real-IP ヘッダーをサポート
+ ロードバランサーとリバースプロキシのシナリオを処理します

**自動メモリ管理**  
+ 期限切れのレート制限バケットを自動的にクリーンアップする
+ 設定可能なクリーンアップ間隔と有効期限
+ 長時間実行されるアプリケーションでのメモリリークの防止

**HTTP 統合**  
+ 制限を超えたときに HTTP 429 (リクエストが多すぎます) を返します
+ レスポンスに標準レート制限ヘッダーを含める
+ クライアントの再試行情報を提供します。

## 設定プロパティ
<a name="ba-runtime-rate-limiting-config"></a>

`application-main.yaml` ファイルでレート制限を設定します。

```
gapwalk:
  ratelimiting:
    enabled: true                                        # Enable/disable rate limiting
    requestsPerMinute: 1000                              # Sustained rate limit per minute
    burstCapacity: 1500                                  # Maximum burst requests allowed
    includeHeaders: true                                 # Include X-RateLimit-* headers
    cleanupIntervalMinutes: 5                            # Cleanup interval for expired buckets
    bucketExpiryHours: 1                                 # Hours after which unused buckets expire
    errorMessage: "Too many requests. Try again later."  # Custom error message
    whitelistIps: ""                                     # Comma-separated IPs to bypass limiting
    perEndpointLimiting: false                           # Apply limits per endpoint (not implemented)
```

### プロパティの説明
<a name="ba-runtime-rate-limiting-config-properties"></a>

**有効**  
レート制限機能を有効または無効にするマスタースイッチ。デフォルト: `false`

**requestsPerMinute**  
持続的なレート制限に対して 1 分あたりに許可されるリクエストの数。これはトークンリフィルレートを表します。デフォルト: `1000`

**burstCapacity**  
レート制限が適用される前にバーストで許可されるリクエストの最大数。トラフィックの急増を許可する`requestsPerMinute`には、 よりも高くする必要があります。デフォルト: `1500`

**includeHeaders**  
HTTP レスポンスに標準レート制限ヘッダー (`X-RateLimit-Limit`、`X-RateLimit-Remaining`、`X-RateLimit-Reset`) を含めるかどうか。デフォルト: `true`

**cleanupIntervalMinutes**  
期限切れレート制限バケットの自動クリーンアップの分単位の間隔。メモリリークの防止に役立ちます。デフォルト: `5`

**bucketExpiryHours**  
未使用のレート制限バケットが期限切れと見なされ、クリーンアップの対象となる時間。デフォルト: `1`

**errorMessage**  
レート制限を超えたときに JSON レスポンスで返されるカスタムエラーメッセージ。デフォルト: `"Too many requests. Try again later."`

**whitelistIps**  
レート制限を完全にバイパスする IP アドレスのカンマ区切りリスト。ヘルスチェックや信頼できるシステムに役立ちます。デフォルト: `empty`

**perEndpointLimiting**  
クライアントのみではなくエンドポイントごとに個別のレート制限を適用するかどうか。現在実装されていません。デフォルト: `false`

## レート制限を有効にする
<a name="ba-runtime-rate-limiting-enable"></a>

デフォルト設定でレート制限を有効にするには:

```
gapwalk:
  ratelimiting:
    enabled: true
```

## クライアント識別
<a name="ba-runtime-rate-limiting-client-id"></a>

レート制限システムは、次の優先順位を使用してクライアントを識別します。

1. **X-Forwarded-For ヘッダー** (カンマ区切りの場合は最初の IP)

1. **X-Real-IP ヘッダー**

1. HTTP リクエストからの**リモートアドレス** 

これにより、アプリケーションの背後にある場合の適切なクライアント識別が保証されます。
+ ロードバランサー
+ リバースプロキシ
+ CDNs
+ API ゲートウェイ

### クライアント ID の例
<a name="ba-runtime-rate-limiting-client-id-example"></a>

```
# Direct connection
Client IP: 192.168.1.100

# Behind load balancer with X-Forwarded-For
X-Forwarded-For: 203.0.113.45, 192.168.1.100
Client IP: 203.0.113.45 (first IP used)

# Behind reverse proxy with X-Real-IP
X-Real-IP: 203.0.113.45
Client IP: 203.0.113.45
```

## レート制限ヘッダー
<a name="ba-runtime-rate-limiting-headers"></a>

`includeHeaders` を有効にすると、次のヘッダーが HTTP レスポンスに追加されます。

**X-RateLimit-Limit**  
クライアントのレート制限の上限 (1 分あたりのリクエスト数)

**X-RateLimit-Remaining**  
現在のレート制限ウィンドウに残っているリクエストの数

**X-RateLimit-Reset**  
レート制限ウィンドウがリセットされる時刻 (Unix タイムスタンプ)

### レスポンスヘッダーの例
<a name="ba-runtime-rate-limiting-headers-example"></a>

```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1640995200
```

### レート制限がレスポンスを超えました
<a name="ba-runtime-rate-limiting-headers-exceeded"></a>

レート制限を超えると、システムは以下を返します。

**HTTP ステータス**  
429 Too Many Requests

**Content-Type**  
application/json

**再試行後**  
再試行するまでの待機秒数

```
{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Try again later.",
  "retryAfter": 60,
  "timestamp": 1640995140000
}
```

## メモリ管理
<a name="ba-runtime-rate-limiting-memory"></a>

レート制限システムは、長時間実行されるアプリケーションのリークを防ぐためにメモリを自動的に管理します。

**自動クリーンアップ**  
+ `cleanupIntervalMinutes` 分ごとに実行
+ `bucketExpiryHours` 時間未使用のバケットを削除します
+ モニタリングのクリーンアップアクティビティを記録します。

**メモリ効率**  
+ スレッドの安全性のために同時データ構造を使用する
+ 遅延バケットの作成 (必要な場合のみ)
+ 効率的なトークンバケットの実装

### クリーンアップアクティビティのモニタリング
<a name="ba-runtime-rate-limiting-memory-monitoring"></a>

クリーンアップメッセージのログを確認します。

```
INFO  RateLimitingService - Cleaned up 15 expired rate limiting buckets
```