ノート:
- このチュートリアルでは、Oracle Cloudへのアクセスが必要です。無料アカウントにサインアップするには、Oracle Cloud Infrastructure Free Tierの開始を参照してください。
- Oracle Cloud Infrastructureの資格証明、テナンシおよびコンパートメントに例の値を使用します。演習を完了するときは、これらの値をクラウド環境に固有の値に置き換えます。
OCI APIゲートウェイ、ファンクションおよび可観測性を使用したJSONコンテンツの検証とAPIヘッダーおよび本体の監視
イントロダクション
特にマイクロサービスに基づくアーキテクチャで分散アプリケーションを開発する場合、その実行において適切にスケーリングおよびパフォーマンスを発揮するコンポーネントが必要です。非常に複雑なアーキテクチャ、他のコンポーネントを実行するコンポーネント、他のコンポーネントなどを無限のコール数で実行します。
それぞれをどのように開発するかは大きな課題です。Kubernetesクラスタ上に構築されたマイクロサービスは、Oracle Cloud Infrastructure API Gateway (OCI API Gateway)を通じて公開できます。コール認証および認可の実行、データ検証およびコール最適化の実行など、いくつかの機能があります。また、既存の方法ではニーズを解決するのに十分でない場合に、パーソナライズされた認証および認可メカニズムを作成することを目的として、OCI Functionsでコールを実行する可能性もあります。
このチュートリアルでは、カスタム・メカニズムを使用して、次のようなユースケースを検証する方法を示します。
-
JSONパラメータ・データのサイズを検証します。
-
JSON項目の最大数を検証します。
OCI APIゲートウェイでの認証および認可のメカニズムであるにもかかわらず、次のような他のニーズにも役立ちます。
-
HEADER、問合せパラメータまたはRESTコールの本文からデータを取得します。
-
問題のデバッグを容易にすることを目的として、このデータをOCI Observabilityに送信します。これは、この情報がないと検出できないことがよくあります。
ノート:データを可観測性に送信する場合は、コードで、パスワードや機密データなどのHEADERまたはBODYコンテンツに対するリダクションの使用をベスト・プラクティスとして検討してください。別の方法として、デバッグ目的でファンクションのオン/オフを切り替える方法もあります。
目的
-
APIデプロイメントを構成します。
-
APIリクエストからHEADERおよびBODYを取得するOCIファンクションを開発します。
-
本文のJSONデータを検証します。
-
HEADERおよびBODY情報をOCI Observabilityに送信します。
前提条件
-
運用中のOracle Cloudテナント。US$300.00の無料のOracle Cloudアカウントを1か月間作成して、このチュートリアルを試すことができます。無料Oracle Cloudアカウントの作成を参照してください。
-
OCI APIゲートウェイ・インスタンスが作成され、インターネットに公開されます。Oracle Cloudでの最初のAPIゲートウェイの作成を参照してください。
タスク1: OCI Observabilityの構成
-
OCIテナンシにログを作成して、ファンクションからログを取り込みます。「監視および管理」に移動し、OCIコンソールで「ログ」を選択します。
-
「カスタム・ログの作成」をクリックします。
-
「カスタム・ログ名」フィールドに名前を入力し、適切なコンパートメントおよびログ・グループを選択します。
ノート: ログのOCIDを取得することが重要です。コードにはこれが必要です。
タスク2: APIリクエストからHEADERおよびBODYを取得するOCIファンクションの作成
次のステップを実行するには、function.zipからコードをダウンロードします。
-
APIリクエストからHEADERおよびBODYを取得します。
-
本体JSONデータを検証します。各配列のアイテム数を検証する方法があります。
-
HEADERおよびBODY情報をOCI Observabilityに送信します。
import io import json import logging import requests import oci from fdk import response from datetime import timedelta def count_items(dictData): counting = 0 for item in dictData: if type(dictData[item]) == list: counting += len(dictData[item]) else: if not type(dictData[item]) == str: counting += count_items(dictData[item]) return counting def handler(ctx, data: io.BytesIO = None): jsonData = "API Error" c = 0 try: config = oci.config.from_file("./config","DEFAULT") logging = oci.loggingingestion.LoggingClient(config) rdata = json.dumps({ "active": True, "context": { "requestheader": data.getvalue().decode('utf-8'), }, }) jsonData = data.getvalue().decode('utf-8') # Get the body content from the API request body = dict(json.loads(data.getvalue().decode('utf-8')).get("data"))["body"] body = dict(json.loads(body)) # Count the number of items on arrays inside the JSON body c = count_items(body) # If JSON body content has more than 1 item in arrays, block the authorization for the API backend if (c > 1): # Send a log to observability with out of limit of items in array put_logs_response = logging.put_logs( log_id="ocid1.log.oc1.iad.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", put_logs_details=oci.loggingingestion.models.PutLogsDetails( specversion="EXAMPLE-specversion-Value", log_entry_batches=[ oci.loggingingestion.models.LogEntryBatch( entries=[ oci.loggingingestion.models.LogEntry( data="out of limit of items in array " + str(c), id="ocid1.test.oc1..00000001.EXAMPLE-id-Value")], source="EXAMPLE-source-Value", type="EXAMPLE-type-Value")])) return response.Response( ctx, status_code=401, response_data=json.dumps({"active": False, "wwwAuthenticate": "API Gateway JSON"}) ) # Send a log to observability with HEADERs and BODY content put_logs_response = logging.put_logs( log_id="ocid1.log.oc1.iad.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", put_logs_details=oci.loggingingestion.models.PutLogsDetails( specversion="EXAMPLE-specversion-Value", log_entry_batches=[ oci.loggingingestion.models.LogEntryBatch( entries=[ oci.loggingingestion.models.LogEntry( data=jsonData, id="ocid1.test.oc1..00000001.EXAMPLE-id-Value")], source="EXAMPLE-source-Value", type="EXAMPLE-type-Value")])) return response.Response( ctx, response_data=rdata, status_code=200, headers={"Content-Type": "application/json"} ) except(Exception) as ex: jsonData = 'error parsing json payload: ' + str(ex) + ", " + json.dumps(jsonData) pass return response.Response( ctx, status_code=401, response_data=json.dumps({"active": False, "wwwAuthenticate": jsonData}) )
コードの理解
このコードは、function.zipにあります。
ノート: APIゲートウェイでファンクションを開発およびコールする方法がわからない場合は、APIゲートウェイを使用したファンクションのコールを参照してください。
-
JSON構造内の任意の配列のアイテムをカウントするために使用されるcount_itemsメソッド。
-
この部分のコードでは、OCI SDK for Pythonを使用して構成ファイルおよび秘密キーをロードし、OCIテナンシにアクセスします。
-
rdataは、リクエストからパラメータを取得し、APIゲートウェイ構成のバックエンドをコールするファンクションを認可するレスポンスを準備します。
active
=True
は認可を実行します。 -
jsonDataは、HEADERおよびBODYコンテンツをOCI Observabilityに生成するために使用されます。
-
このコードは、リクエストからBODY JSON構造のみを取得します。
-
次のコードでは、BODY JSON構造内の配列の項目をカウントします。アイテム数が複数のアイテムを超過した場合、「アクティブ」は「偽」に設定され、エラー・ログは「OCI可観測性」に送信されます。ログを送信するには、Python OCI SDKを使用する必要があります。
ノート: log_id変数を、タスク1で生成されたOCIDログに置き換えます。
カウントが1以下の場合、リクエストHEADERおよびBODYコンテンツを含むログがOCI Observabilityで生成されます。log_id変数をOCIDログに置き換えてください。
ノート: 異なるOCIログでログを生成できます。このチュートリアルでは、1つのログのみが作成されましたが、さらにログを作成できます。
-
エラーの場合は、ここでエラーのメッセージが生成されます。
OCIへのSDK認証の構成
構成ファイルをOCIにデプロイする前に、構成ファイルを構成し、OCI秘密キーおよびフィンガープリントをファンクションとともに配置する必要があります。Oracle Cloud Infrastructureコマンドライン・インタフェース(OCI CLI)のインストールおよび構成でconfigおよび秘密キー・ファイルを生成する必要があります。
OCI CLIをインストールおよび構成するには、OCI CLIのインストールを参照してください。このインストールと構成では、2つのファイルが生成されます。configおよび private keyファイルを見つけます(デフォルトは oci_api_key.pem)。フォルダ・パスはインストール手順で通知されます。
function.zipをダウンロードして、コード、構成ファイルおよび秘密キーを確認します。構成および秘密キー・ファイルをOCI CLIファイルに置き換えます。
OCI関数の構築とデプロイ
このステップでは、OCI CLIを使用してOCI関数を作成し、コードをテナンシにデプロイする必要があります。OCIファンクションを作成するには、OCIファンクションQuickStartを参照し、Pythonオプションを検索します。次の情報を使用してファンクションを作成する必要があります:
- アプリケーション: fn_apigw_json
ファンクションをデプロイしたコンパートメントを覚えておいてください。OCI APIゲートウェイ・デプロイメントを構成するには、この情報が必要になります。
タスク3: APIゲートウェイでのOCIファンクションの構成
APIをデプロイし、OCI Functionsと統合してリクエスト・パラメータ(ヘッダーおよびBODY)を検証し、OCI Observabilityに送信しましょう。OCI APIゲートウェイでバックエンドを公開する方法がわからない場合は、OCI APIゲートウェイ: APIの設定、作成およびデプロイを参照してください。
-
「デプロイメントの編集」を開きます。
-
「Authentication」セクションをクリックします。
-
「単一認証」をクリックし、「認可プロバイダ・ファンクション」を選択します。
-
(ファンクションをデプロイした場所)ファンクション・コンパートメントを選択し、fn_apigw_jsonアプリケーションおよびファンクションpython-json-headerを選択します。
-
HEADERおよび BODYを取得するように関数引数を構成します。headerと header2という名前の HEADER、および bodyという名前の BODYコンテンツを取得します。
-
「ルート」をクリックし、ヘッダー変換を構成します。この構成はオプションであり、リクエスト・データ(HEADERおよびBODYコンテンツ)またはリクエストで生成されたエラーを含むレスポンス・コンテンツを表示します。ファンクションのデバッグに役立ちます。
タスク4: リクエストのテスト
ノート: APIデプロイメントでは、認可プロバイダ・ファンクションを構成してファンクション引数を設定すると、ファンクション引数のキャッシュがアクティブ化されます。キャッシュされるデータ型を設定できます。問合せパラメータまたはヘッダーのキャッシュは構成できますが、本文コンテンツには構成できません。
APIリクエストをテストできます。本文の配列に1つの項目のみを使用してテストします。
curl --location 'https://xxxxxxxxxxxxxxxxxxxx.apigateway.us-ashburn-1.oci.customer-oci.com/path_index/path' \
--header 'Content-Type: text/plain' \
--header 'header: header' \
--header 'header2: header2' \
--header 'header3: header3' \
--data '{"data": {"clientID": "xxxxxxxxxxxxxxxxxxx", "secretID": "xxxxxxxxxxxxxxxxxxx", "jList":[{"added_by":"Ani","description":"example description.","start_date":"2014-10-10","mark":255,"id":975}]}}' -i
header3は送信されましたが、OCI APIゲートウェイでファンクション引数として構成されていないため、ログに表示されました。BODY JSON配列には1つの項目しかないため、有効な認可リクエストです。
配列とテストに、もう1つの項目を入れてみましょう。
curl --location 'https://xxxxxxxxxxxxxxxxxxxx.apigateway.us-ashburn-1.oci.customer-oci.com/path_index/path' \
--header 'Content-Type: text/plain' \
--header 'header: header' \
--header 'header2: header2' \
--header 'header3: header3' \
--data '{"data": {"clientID": "xxxxxxxxxxxxxxxxxxx", "secretID": "xxxxxxxxxxxxxxxxxxx", "jList":[{"added_by":"Ani","description":"example description.","start_date":"2014-10-10","mark":255,"id":975}, {"added_by":"Ani","description":"example description.","start_date":"2014-10-10","mark":255,"id":975}]}}' -i
関連リンク
確認
- 著者 - Cristiano Hoshikawa (Oracle LAD Aチーム・ソリューション・エンジニア)
その他の学習リソース
docs.oracle.com/learnの他のラボをご覧いただくか、Oracle Learning YouTubeチャネルで無料のラーニング・コンテンツにアクセスしてください。また、education.oracle.com/learning-explorerにアクセスしてOracle Learning Explorerになります。
製品ドキュメントは、Oracle Help Centerを参照してください。
Use OCI API Gateway, Functions and Observability to Validate JSON Content and Monitor API Headers and Body
F89782-01
November 2023
Copyright © 2023, Oracle and/or its affiliates.