第1章 Web エンドポイントの認可
Quarkus には、プラグ可能な Web セキュリティーレイヤーが組み込まれています。セキュリティーが有効な場合、システムはすべての HTTP リクエストに対して権限チェックを実行し、リクエストを続行するかどうかを決定します。
quarkus.http.auth.
設定によってパスが制限されている場合は、@PermitAll
を使用してもパスは開きません。特定のパスにアクセスできるようにするには、Quarkus のセキュリティー設定内で適切な設定を行う必要があります。
Jakarta RESTful Web サービスを使用する場合は、HTTP パスレベルのマッチングではなく、quarkus.security.jaxrs.deny-unannotated-endpoints
または quarkus.security.jaxrs.default-roles-allowed
を使用してデフォルトのセキュリティー要件を設定することを検討してください。アノテーションによって、個々のエンドポイントでこれらのプロパティーをオーバーライドできるためです。
認可は、セキュリティープロバイダーが提供するユーザーロールに基づいて行われます。ユーザーロールをカスタマイズするには、SecurityIdentityAugmentor
を作成します。Security Identity Customization を参照してください。
1.1. 設定を使用した認可
権限は、Quarkus 設定で権限セットによって定義されます。各権限セットで、アクセス制御用のポリシーを指定します。
組み込みのポリシー | 説明 |
---|---|
| このポリシーはすべてのユーザーを拒否します。 |
| このポリシーはすべてのユーザーを許可します。 |
| このポリシーは認証済みユーザーのみを許可します。 |
特定のロールを持つユーザーにリソースへのアクセスを許可するロールベースのポリシーを定義できます。
ロールベースのポリシーの例
quarkus.http.auth.policy.role-policy1.roles-allowed=user,admin 1
- 1
- これは、
user
ロールとadmin
ロールを持つユーザーを許可するロールベースのポリシーを定義します。
次の設定例に示すように、application.properties
ファイルで定義されている組み込みの権限セットを設定することで、カスタムポリシーを参照できます。
ポリシー設定の例
quarkus.http.auth.permission.permit1.paths=/public/* 1 quarkus.http.auth.permission.permit1.policy=permit quarkus.http.auth.permission.permit1.methods=GET quarkus.http.auth.permission.deny1.paths=/forbidden 2 quarkus.http.auth.permission.deny1.policy=deny quarkus.http.auth.permission.roles1.paths=/roles-secured/*,/other/*,/api/* 3 quarkus.http.auth.permission.roles1.policy=role-policy1
この例の正確なパス /forbidden
では、/forbidden/
パスは保護されません。セキュリティーの対象範囲を適切なものにするには、/forbidden/
パスの正確なパスを新しく追加する必要があります。
1.1.1. カスタムの HttpSecurityPolicy
場合によっては、独自の名前付きポリシーを登録すると便利です。これを実行するには、io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy
インターフェイスを実装するアプリケーションスコープの CDI Bean を作成します。以下にその例を示します。
import jakarta.enterprise.context.ApplicationScoped;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy;
import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
@ApplicationScoped
public class CustomNamedHttpSecPolicy implements HttpSecurityPolicy {
@Override
public Uni<CheckResult> checkPermission(RoutingContext event, Uni<SecurityIdentity> identity,
AuthorizationRequestContext requestContext) {
if (customRequestAuthorization(event)) {
return Uni.createFrom().item(CheckResult.PERMIT);
}
return Uni.createFrom().item(CheckResult.DENY);
}
@Override
public String name() {
return "custom"; 1
}
private static boolean customRequestAuthorization(RoutingContext event) {
// here comes your own security check
return !event.request().path().endsWith("denied");
}
}
- 1
- 名前付き HTTP セキュリティーポリシーは、
application.properties
パスマッチングルールにマッチするリクエストにのみ適用されます。
設定ファイルから参照されるカスタム名の HttpSecurityPolicy の例
quarkus.http.auth.permission.custom1.paths=/custom/*
quarkus.http.auth.permission.custom1.policy=custom 1
- 1
- カスタムポリシー名は、
io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy.name
メソッドによって返される値とマッチする必要があります。
すべてのリクエストで呼び出されるグローバルの HttpSecurityPolicy
を作成することもできます。io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy.name
メソッドを実装せず、ポリシーに名前を付けないままにしてください。
1.1.2. パスとメソッドのマッチング
権限セットでは、パスとメソッドをコンマ区切りリスト形式で指定することもできます。パスの末尾がワイルドカード *
の場合は、そのパスによって生成されたクエリーがすべてのサブパスにマッチします。それ以外の場合、クエリーは完全一致を照会し、特定のパスにのみマッチします。
quarkus.http.auth.permission.permit1.paths=/public*,/css/*,/js/*,/robots.txt 1
quarkus.http.auth.permission.permit1.policy=permit
quarkus.http.auth.permission.permit1.methods=GET,HEAD
- 1
- パスの末尾の
*
ワイルドカードは、0 個以上のパスセグメントにマッチしますが、/public
パスから始まる単語にはマッチしません。そのため、/public-info
のようなパスはこのパターンにマッチしません。
1.1.3. パスにはマッチするがメソッドにはマッチしない場合
パスに基づいて 1 つ以上の権限セットにマッチしても、必要なメソッドのいずれにもマッチしない場合、リクエストは拒否されます。
上記の権限セットが指定されている場合、GET/public/foo
は、パスとメソッドの両方にマッチするため、許可されます。対照的に、POST/public/foo
は、パスにはマッチしますが、メソッドにはマッチしないため、拒否されます。
1.1.4. 複数のパスのマッチング: 最長パスが優先される
マッチングは、常に "最長パスが優先される" という基準で行われます。より詳細な権限セットがマッチした場合、それよりも詳細でない権限セットは考慮されません。
quarkus.http.auth.permission.permit1.paths=/public/* quarkus.http.auth.permission.permit1.policy=permit quarkus.http.auth.permission.permit1.methods=GET,HEAD quarkus.http.auth.permission.deny1.paths=/public/forbidden-folder/* quarkus.http.auth.permission.deny1.policy=deny
上記の権限セットの場合、GET /public/forbidden-folder/foo
は、両方の権限セットのパスとマッチします。しかし、より長いパスが deny1
権限セットのパスとマッチするため、deny1
が選択され、リクエストが拒否されます。
前述の deny1
権限と permit1
権限の例で示したように、サブパスの権限がルートパスの権限よりも優先されます。
このルールをさらに例示するために、サブパス権限ではパブリックリソースへのアクセスを許可し、ルートパス権限では認可を要求するシナリオを示します。
quarkus.http.auth.policy.user-policy.roles-allowed=user quarkus.http.auth.permission.roles.paths=/api/* quarkus.http.auth.permission.roles.policy=user-policy quarkus.http.auth.permission.public.paths=/api/noauth/* quarkus.http.auth.permission.public.policy=permit
1.1.5. 複数のサブパスのマッチング: *
ワイルドカードへの最長パスが優先される
前の例では、パスの末尾が *
ワイルドカードの場合に、すべてのサブパスがマッチすることを示しました。
このワイルドカードは、パスの途中にも適用され、単一のパスセグメントを表します。他のパスセグメント文字と混在させることはできません。したがって、/public/
*/about-us
パスのように、*
ワイルドカードは常にパス区切り文字によって囲まれます。
複数のパスパターンが同じリクエストパスに対応する場合、システムは *
ワイルドカードに至る最長のサブパスを選択します。この場合は、すべてのパスセグメント文字が *
ワイルドカードよりも詳細なものとして扱われます。
以下は簡単な例です。
quarkus.http.auth.permission.secured.paths=/api/*/detail 1 quarkus.http.auth.permission.secured.policy=authenticated quarkus.http.auth.permission.public.paths=/api/public-product/detail 2 quarkus.http.auth.permission.public.policy=permit
認可を使用した設定で保護するパスは、すべてテストする必要があります。複数のワイルドカードを使用してパスパターンを記述するのは、手間がかかる場合があります。パスが意図したとおりに認可されていることを確認してください。
次の例では、パスは最も詳細なものから最も詳細でないものの順に並べられています。
最も詳細なパスから最も詳細でないパスの順に並べたリクエストパス /one/two/three/four/five
のマッチ
/one/two/three/four/five /one/two/three/four/* /one/two/three/*/five /one/two/three/*/* /one/two/*/four/five /one/*/three/four/five /*/two/three/four/five /*/two/three/*/five /*
パスの末尾の *
ワイルドカードは、0 個以上のパスセグメントとマッチします。その他の場所に指定された *
ワイルドカードは、1 つのパスセグメントに完全一致します。
1.1.6. 複数のパスのマッチング: 最も詳細なメソッドが優先される
パスが複数の権限セットに登録されている場合は、リクエストにマッチする HTTP メソッドを明示的に指定している権限セットが優先されます。この場合、メソッドのない権限セットが適用されるのは、リクエストメソッドがメソッドの指定を持つ権限セットとマッチしない場合に限られます。
quarkus.http.auth.permission.permit1.paths=/public/* quarkus.http.auth.permission.permit1.policy=permit quarkus.http.auth.permission.permit1.methods=GET,HEAD quarkus.http.auth.permission.deny1.paths=/public/* quarkus.http.auth.permission.deny1.policy=deny
上記の権限セットは、GET/public/foo
が両方の権限セットのパスにマッチすることを示しています。ただし、これは permit1
権限セットの明示的なメソッドと明確に一致しています。したがって、permit1
が選択され、リクエストが受け入れられます。
対照的に、PUT/public/foo
は、permit1
のメソッド権限とマッチしません。その結果、deny1
がアクティブになり、リクエストが拒否されます。
1.1.7. 複数のパスとメソッドのマッチング: どちらも優先される
場合によっては、前述のルールにより、複数の権限セットが同時に適用されることがあります。その場合、リクエストを続行するには、すべての権限でアクセスが許可されている必要があります。これを実現するには、両方にメソッドを追加するか、両方からメソッドを除外する必要があります。メソッド固有のマッチが優先されます。
quarkus.http.auth.policy.user-policy1.roles-allowed=user quarkus.http.auth.policy.admin-policy1.roles-allowed=admin quarkus.http.auth.permission.roles1.paths=/api/*,/restricted/* quarkus.http.auth.permission.roles1.policy=user-policy1 quarkus.http.auth.permission.roles2.paths=/api/*,/admin/* quarkus.http.auth.permission.roles2.policy=admin-policy1
上記の権限セットの場合、GET /api/foo
は両方の権限セットのパスにマッチするため、user
と admin
の両方のロールが必要です。
1.1.8. アクセスを拒否するための設定プロパティー
次の設定は、ロールベースのアクセス制御 (RBAC) の拒否動作を変更するものです。
quarkus.security.jaxrs.deny-unannotated-endpoints=true|false
-
true に設定すると、すべての Jakarta REST エンドポイントへのアクセスがデフォルトで拒否されます。Jakarta REST エンドポイントにセキュリティーアノテーションがない場合は、エンドポイントのデフォルトが
@DenyAll
動作になります。これにより、保護されているはずのエンドポイントが誤って公開されることを回避できます。デフォルトはfalse
です。 quarkus.security.jaxrs.default-roles-allowed=role1,role2
-
アノテーションのないエンドポイントのデフォルトのロール要件を定義します。
**
ロールは、すべての認証済みユーザーを意味する特別なロールです。これをdeny-unannotated-endpoints
と組み合わせることはできません。代わりにdeny
が有効になるためです。 quarkus.security.deny-unannotated-members=true|false
-
true に設定すると、セキュリティーアノテーションを持たないが、セキュリティーアノテーションを持つメソッドを含むクラスで定義されているすべての CDI メソッドと Jakarta REST エンドポイントへのアクセスが拒否されます。デフォルトは
false
です。
1.1.9. 権限の無効化
次のように、宣言された各権限に対して enabled
プロパティーを設定することで、ビルド時に権限を無効にすることができます。
quarkus.http.auth.permission.permit1.enabled=false quarkus.http.auth.permission.permit1.paths=/public/*,/css/*,/js/*,/robots.txt quarkus.http.auth.permission.permit1.policy=permit quarkus.http.auth.permission.permit1.methods=GET,HEAD
権限は、システムプロパティーまたは環境変数 (例: -Dquarkus.http.auth.permission.permit1.enabled=true
) を使用して実行時に再度有効にできます。
1.1.10. 権限パスと HTTP ルートパス
quarkus.http.root-path
設定プロパティーは、http エンドポイントのコンテキストパス を変更します。
デフォルトでは、quarkus.http.root-path
は設定した権限パスの先頭に自動的に追加されるため、スラッシュを使用しないでください。次に例を示します。
quarkus.http.auth.permission.permit1.paths=public/*,css/*,js/*,robots.txt
この設定は次のものと同等です。
quarkus.http.auth.permission.permit1.paths=${quarkus.http.root-path}/public/*,${quarkus.http.root-path}/css/*,${quarkus.http.root-path}/js/*,${quarkus.http.root-path}/robots.txt
先頭にスラッシュを付けると、設定された権限パスの解釈方法が変わります。設定された URL がそのまま使用され、quarkus.http.root-path
の値が変更されても、パスが調整されません。
例:
quarkus.http.auth.permission.permit1.paths=/public/*,css/*,js/*,robots.txt
この設定は、固定または静的 URL /public
から提供されるリソースにのみ影響します。この URL は、quarkus.http.root-path
が /
以外に設定されていると、アプリケーションリソースとマッチしない可能性があります。
詳細は、Path Resolution in Quarkus を参照してください。
1.1.11. SecurityIdentity
ロールのマッピング
優先されるロールベースのポリシーにより、SecurityIdentity
ロールをデプロイメント固有のロールにマッピングできます。その後、デプロイメント固有のロールを、@RolesAllowed
アノテーションを使用してエンドポイント認可に適用できます。
quarkus.http.auth.policy.admin-policy1.roles.admin=Admin1 1
quarkus.http.auth.permission.roles1.paths=/*
quarkus.http.auth.permission.roles1.policy=admin-policy1
- 1
admin
ロールをAdmin1
ロールにマッピングします。SecurityIdentity
にadmin
とAdmin1
の両方のロールが付与されます。