この記事は chillSAP 夏の自由研究2022、8/6の記事として執筆しています。
はじめに
この記事は、Kyma runtimeのCommunity Code Challengeをやってみたシリーズの3回目です。このシリーズでは、Kyma runtimeのCode Challengeに参加して、開発の方法やその裏の仕組みについてわかったことをまとめていきます。
Week3の課題
Week3の課題は以下のようになっています。Week3の目的は、Week2で作成したサービスに認証を追加することです。
リンク:Week 3 (July 20th, 2022 - July 27th, 2022)
- 公式ドキュメントExpose and Secure a Workload with a JSON Web Tokenを読む
- Week2で作成したサービスに認証をつけて公開する
Week3で学んだこと
1. APIに認証を追加する方法
Kyma runtimeのアプリケーションに認証を追加するには、API RuleにaccessStrategiesを設定します。以下の例ではリクエストヘッダに渡されたJWTを使用して認証が行われる設定になっています。アプリケーションのコードを変更することなく、設定だけで認証が追加できるのです。この仕組みはApprouterにも似ているのかなと思いましたが、こちらの方が簡単ですね。
apiVersion: gateway.kyma-project.io/v1alpha1
kind: APIRule
metadata:
name: httpbin
namespace: $NAMESPACE
spec:
service:
name: httpbin
port: 8000
host: httpbin.$DOMAIN_TO_EXPOSE_WORKLOADS
gateway: kyma-system/kyma-gateway
rules:
- accessStrategies:
- handler: jwt
config:
jwks_urls:
- $JWKS_URI
methods:
- GET
path: /.*
2. JWTを発行する方法
公式ドキュメントの"Prerequisites"を読んだ時点で、「これってトライアルではできないのでは?」と思いました。
You have an SAP Cloud Identity Services - Identity Authentication tenant.
ドキュメントに書かれていた方法はIASに作成したアプリケーションにJWTを発行させるというものだったからです。しかし、JWTを発行する方法は複数あったので大丈夫でした。
①OpenID Connectに準拠したIdentity Providerを使う
JWTの発行および認証には、OpenID Connectに準拠したIdentity Providerを使用することができます。IASでなくても問題ありません。こちらのブログにはPingOne、Okta、XSUAAを使った例が載っていました。
私はまずXSUAAを使ってやってみました。jwks_urlsに指定するのは、<XSUAAサービスインスタンスのキーにあるurl>
+ /token_keys
です。/token_keys
というエンドポイントの存在を初めて知りましたが、ここにアクセスするとXSUAAの公開鍵が見られます。この公開鍵を使ってJWTの認証が行われるようです。
apiVersion: gateway.kyma-project.io/v1alpha1
kind: APIRule
metadata:
name: my-service
spec:
gateway: kyma-gateway.kyma-system.svc.cluster.local
service:
name: my-service
port: 8081
host: my-service
rules:
- path: /.*
methods: ["GET"]
accessStrategies:
- handler: jwt
config:
jwks_urls:
- https://xxxxxtrial.authentication.eu10.hana.ondemand.com/token_keys
認証の設定後にAPIに直接アクセスすると、以下のようなUnauthorizedの画面が出ます。
アクセスするためにはXSUAAサービスインスタンスのクライアントID、シークレットを使用してトークンを取得し、リクエストヘッダに渡す必要があります。Posmanで実行する場合は以下のようにAuthorizationを設定します。
項目 | 設定値 |
---|---|
Type | OAuth2.0 |
Grant Type | Client Credentials |
Access Token URL | サービスキーに設定されたurl + /oauth/token |
Client ID | サービスキーに設定されたclientid |
Client Secret | サービスキーに設定されたclientsecret |
(補足)Kyma runtimeでのXSUAAサービスインスタンスの作り方
Cloud Foundryと同じように、Kyma runtimeでもXSUAAサービスインスタスを作ることができます。以下のUIから作る方法と、設定ファイルをもとにkubectlで作成する方法があります。今回はkubectlを使って作成してみます。
手順はCode Challengeのこちらの投稿を参考にしました。まずXSUAAのサービスインスタンスを作り、次にサービスバインディングを作成します。サービスバインディングはCloud Foundryでいうところのサービスキーだと理解しました。
-
サービスインスタンスの作成
以下のyamlファイルを作成します。ファイル名は任意です。
apiVersion: services.cloud.sap.com/v1
kind: ServiceInstance
metadata:
name: my-service-xsuaa
spec:
serviceOfferingName: xsuaa
servicePlanName: application
デプロイします。
kubectl apply -f my-service\xsuaa-instance.yaml
-
サービスバインディングの作成
以下のyamlファイルを作成します。ファイル名は任意です。
apiVersion: services.cloud.sap.com/v1
kind: ServiceBinding
metadata:
name: xsuaa-service-binding
spec:
serviceInstanceName: my-service-xsuaa
secretName: xsuaa-service-binding
デプロイします。
kubectl apply -f my-service\xsuaa-binding.yaml
Kyma runtimeにサービスインスタンスとサービスバインディングが登録されます。
サービスバインディングを開き、シークレットをクリックします。
clientidやclientsecretが表示されます。この画面ではBase64でエンコードされているので、デコードして使います。なお、認証用のURLはCloud Foundryで作成したインスタンスと同じでした。
②Kyma runtimeのOAuth2 Clientを使う
Week3の課題を提出した他の人が使っていた方法がこちらでした。画面ショットを見ると、accessStrategies>handlerの設定がjwt
ではなくoauth2_introspection
になっています。また、URLの指定もありません。
こちらの方法では、Kyma runtimeに登録したOAuth2 Clientを使って認証を行います。
deployment.yamlの設定は以下のようになります。
apiVersion: gateway.kyma-project.io/v1alpha1
kind: APIRule
metadata:
name: my-service
spec:
gateway: kyma-gateway.kyma-system.svc.cluster.local
service:
name: my-service
port: 8081
host: my-service
rules:
- path: /.*
methods: ["GET"]
accessStrategies:
- handler: oauth2_introspection
OAuth2 Clientを作成します。
以下のように入力します。Scopeが必須のため設定していますが、今回は使用していません。
作成されたOAuth2 Clientにclient_id, client_secretが表示されます。Base64でエンコードされているので、デコードして使います。
Postmanからアクセスするには、以下のように2ステップでリクエストを実行します。
タブ | 項目 | 設定値 |
---|---|---|
- | URL | ※下記参照 |
- | メソッド | POST |
Authorization | Grant Type | Basic Auth |
Username | OAuth2 Clientのclient_id | |
Password | OAuth2 Clientのclient_secret | |
Headers | Content-Type | application/x-www-form-urlencoded |
Body | grant_type=client_credentials |
※トークン取得用のURLは以下のようになります。
APIのURLがhttps://my-service.a2985eb.kyma.shoot.live.k8s-hana.ondemand.com
の場合
-
my-service
をoauth2
に変更 - 末尾に
/oauth2/token
を追加する
結果:https://oauth2.a2985eb.kyma.shoot.live.k8s-hana.ondemand.com/oauth2/token
上記リクエストを実行すると、access_tokenが返ってきます。