LoginSignup
2
0

More than 1 year has passed since last update.

IBM API Connect 関連メモ - (5)Secure Gateway経由でのz/OS Connectとの連携

Last updated at Posted at 2020-08-20

はじめに

IBM Cloud上のAPI Connectを試してみた時の作業ログです。
オンプレミスのサーバー上にREST APIでアクセスできるサービスがあってそれをAPI Connectで外部公開したい、というシナリオを想定します。
その場合、API Connect(IBM Cloud)とオンプレのサーバーをセキュアに接続する必要がありますが、そこを実現してくれるSecure Gatewayというサービスサービスがあります。今回はそのSecure Gatewayを使ってみます。
バックエンドのサービスはz/OS Connect(z/OS上のサービスを公開するためのコンポーネント)で公開されたCICSアプリケーションを想定します。

Secure Gateway Client用のマシンにはWindows10を使用します。

関連記事

IBM API Connect 関連メモ - (1)既存REST APIの取り込み
IBM API Connect 関連メモ - (2)API Connectツールキットを使用したNode.jsアプリ作成(Loopback)
IBM API Connect 関連メモ - (3)カタログ、開発者ポータルの構成
IBM API Connect 関連メモ - (4)各種APIの管理
IBM API Connect 関連メモ - (5)Secure Gateway経由でのz/OS Connectとの連携
IBM API Connect 関連メモ - (6)API Connect-z/OS Connect間TLS接続
IBM API Connect 関連メモ - (7)z/OS Connect 基本認証 + ID伝播
IBM API Connect 関連メモ - (8)z/OS Connect 連携におけるインターフェースの浄化
IBM API Connect 関連メモ - (9)z/OS Connect 連携まとめ

事前調査

参考: Secure Gateway 概説

以下の図が全体像を理解するのに有用です。
image.png

IBM Cloud上のアプリケーション(今回の場合API Connectを想定)と、オンプレ上のリソース(今回の場合REST APIでアクセスできるサービスを想定)をつなために、IBM Cloud上にSecure Gateway Serviceを立てて、オンプレ環境とのつなぎとなるサーバーにSecure Gateway Clientを立て、論理的な接続経路を構成することになります。

「IBM Cloud => オンプレ」、「IBM Cloud <= オンプレ」の両方向の通信がサポートされますが、今回のケースでは前者の構成をとることになります。

バックエンド・サービス情報

オンプレ環境にバックエンドのサービスがあって、そのAPIをIBM Cloud上のAPI Connectで管理したいという前提です。
バックエンドのサービスの実装はなんでもよいのですが、ここでメインフレーム上のサービス(実体としてはCICSのアプリをz/OS Connect EEでREST APIで呼び出せるようにしたもの)を想定します。

このバックエンドのサービスを呼び出すためのエンドポイントは、"eplexa:30681"とします。
(例えば、オンプレ環境のネットワークからは、http://eplexa:30681/showroomdemo/v1/isecics/stock/CITRというようなURLでアクセスできるものとします。)
このエンドポイントはあくまでオンプレのネットワーク上でのみ有効なものであり、インターネット向けに外部に公開しているものではない、というのが前提です。

Secure Gateway環境構築

Secure Gateway Serviceの追加

参考:ゲートウェイの追加

IBM CloudのカタログからSecure Gateway を選択
image.png

無料のEssentialsプランを選択して作成
image.png

Cloud FoundryサービスにSecure Gatewayが作成されるのでこれをクリック
image.png

ゲートウェイの追加ボタンを押します
image.png

名前を指定してゲートウェイの追加
image.png

ゲートウェイが作成されました。
image.png

ゲートウェイ名の右の設定アイコンをクリックし、編集をクリックします
image.png

ここでセキュリティートークンと、有効期限が確認できます。
image.png

クライアントの追加

参考: クライアントの追加

上で作成したゲートウェイの管理画面から、クライアントの接続ボタンをクリックします。
image.png

WindowsマシンをSecure Gateway Clientとするので、Windowsのインストーラーをダウンロードします。
image.png

ダウンロードしたインストーラーを実行します。
参考: クライアントのインストール
image.png

image.png

image.png

image.png

ゲートウェイIDとセキュリティートークンを指定してNext
image.png

※本当はここでACLファイルを作成してそのファイル名を指定する必要があったらしいのですが、最初不要かと思ってスルーしちゃってました。後述の「クライアントにACL設定追加」の節を参照のこと。

そのままInstall
image.png

Windowsのサービスのウィンドウを開いて、IBM Cloude Secure Gateway Serviceが稼働していることを確認します。
また、サービスとして実行するのはよいですが、自動実行されるのは鬱陶しいので、手動実行に変えておきます。
image.png

Windowsのサービスが実行中になっていることを確認後、IBM CloudのSecure Gateway Serviceの画面を見ると、以下のようなアイコンが表示されて、クライアントとの接続がされたことが確認できます。
image.png

宛先の追加

参考: 宛先の追加

Secure Gateway Serviceの宛先タブから、+ボタンをクリック
image.png

リソースの場所はオンプレミスを指定して次へ
image.png

バックエンドのサービスのホスト名、ポート番号を指定して次へ
image.png

Cloudアプリケーション(API Connect)とSecure Gateway Server間プロトコルはHTTPを選択して次へ
最初あまり考えずにHTTPにしてしまったが、後々APIConnect - z/OS Connect間をTLSとかで接続することを考えるとTCPでよい(後で修正)。
image.png

Secure Gateway Client - バックエンドサービス間の認証はNoneを選択して次へ
image.png

IPテーブルで接続できるIPを絞ったりすることができるようですが、ここでは一旦そのまま次へ
image.png

名前を指定して追加
image.png

宛先が追加されました。
image.png

作成された宛先の設定アイコンをクリックすると、クラウド側のホスト:ポートなどが確認できます。
image.png

これで、ここに示されているホスト名:ポートにアクセスすると、宛先リソースにフォワードされるのかなと思ったのですが、リクエスト投げても繋がらない...

右上に赤い手のマークが出て、「ACLによりアクセスがブロックされています」と出てますが、これのせい?
image.png

補足: Secure Gatewayの位置づけについて

参考: Secure Gateway Service: FAQ

Secure Gateway Serviceは、OSIモデルの第4層にあたります。

上の記述にあるように、Secure GatewayはOSIモデルの第4層(トランスポート層)に相当します。TCP/UDPのレイヤーですね。つまり、SSHトンネリング等と同じような位置づけだと考えればよさそうです。
それなのに、上のプロトコルでTLSだとかHTTPだとかが選べるのでそれが何を意味するのか混乱したのですが、どうやら、クラウドアプリ - Secure Gateway Server 間、および、オンプレ上のSecure Gateway Client - バックエンドサーバー間をセキュアな構成にするっていうのができるっぽいです。
End to End (クラウドアプリ-バックエンドサーバー間)でセキュアな構成を考えて、Secure Gateway部分は単なる経路として扱うのであれば、とりあえずSecure Gatewayのレベルでのセキュリティは考えなくてもよいかと思います。

クライアントにACL設定追加 その1 / NG編

クライアントの追加のステップで、スルーしてしまっていたACLの設定を追加してみます。

参考: 対話式クライアント・セッションの開始

クライアントには、<InstDir>\ibm\securegateway\client\secgw.cmdを実行して起動されるツールがあるようなので使ってみます。こいつを実行すると...
image.png

なんかローカルでWebアプリ的なものが動いてブラウザが起動してきました。
image.png

ログを見てみます。
image.png
やっぱりACLではじかれてたっぽい。

アクセス制御リストを選択してみます。
ここの"アクセスを許可"の欄に、バックエンドサービスのホスト名:ポートを追加してみます。
image.png

反映の仕方がよく分からないので、Windowsのサービスを再起動してみました。
が、その後も状況は変わらず。
image.png

イマイチ反映方法が分からなかったのであきらめました。

クライアントにACL設定追加 その2 / OK編

上のやり方がNGだったので、別の方法を試します。
<InstDir>\ibm\securegateway\client\SampleACLFile.txtというのが提供されていたので、これをACLFile.txtという名前でコピーして、以下のように編集します。

ACLFile.txt
acl allow eplexa:30681

で構成ファイルが同ディレクトリのsecuregw_service.configに保持されているようなので、こいつを編集して上のACLFile.txtをACL_FILE=に指定します。

securegw_service.config
#Config file for Secure Gateway Client, to start as a Windows Service.
#PLEASE AVOID ANY RESIDUAL WHITE SPACES

#Enter the gateway ids separated by single spaces
GATEWAY_ID=xxxxx

#Enter the security tokens separated by --
SECTOKEN=xxxxxx

#Enter the ACL files separated by --
ACL_FILE=ACLFile.txt

# Enter the proxy info if you want to start the client with the proxy
PROXY=

#Enter the log levels separated by --
LOGLEVEL=INFO

#Enter if you want to use client UI (Y/N)
USE_UI=

#Enter the port for client UI
PORT=9003

#Enter the password for client UI
PWD=

#Enter the language for command line interface; acceptable values are en, de, es, fr, it, ja, ko, pt-BR, zh, zh-TW
LANGUAGE=ja

#Enter the startup options separated by single spaces, no "" is needed
#Accepted values are mentioned in this document
#https://cloud.ibm.com/docs/services/SecureGateway?topic=securegateway-client-interacting#startup-args
SECGW_ARGS=

これでSecure Gateway ClientのWindowsサービスを再起動してみます。

赤い手のアイコンが消えた!!!
image.png

Secure Gatewayのクラウド側のホスト:ポートにアクセスしてみると、意図した通り、バックエンドサービスが呼び出せるようになりました!

API Connect からSecure Gateway経由でのバックエンド・サービス連携

さて、これでIBM Cloud上のAPI Connectから、Secure Gateway経由でオンプレ上のサービスにアクセスするパスは作れました。
いよいよ、バックエンドサービスのAPIをAPI Connectで管理できるようにしてみましょう。

目指す環境の全体像としてはこんなイメージです。
image.png

バックエンドアクセス情報の整理

一旦、管理対象とするバックエンドサービスのAPIについて整理しておきます。
z/OS Connectは公開したAPI仕様をSwagger文書として生成してくれるので、これをAPI Connectに取り込めばよさそうです。
また、サービスのエンドポイントとしては実際にはeplexa:30681ですが、API Connectから見るとSecure Gatewayを介してのアクセスになりますので、Secure Gatewayが新たに生成したエンドポイントを使用することになります。

今回取り込むSwagger文書はこちらです。

CICSSwagger.json
{
  "swagger" : "2.0",
  "info" : {
    "description" : "",
    "version" : "1.0.0",
    "title" : "cicsstockrestfulservice"
  },
  "host" : "localhost:8080",
  "basePath" : "/showroomdemo/v1/isecics",
  "schemes" : [ "https", "http" ],
  "consumes" : [ "application/json" ],
  "produces" : [ "application/json" ],
  "paths" : {
    "/order" : {
      "post" : {
        "tags" : [ "cicsstockrestfulservice" ],
        "operationId" : "postCICSStockOrderService",
        "parameters" : [ {
          "in" : "body",
          "name" : "postCICSStockOrderService_request",
          "description" : "request body",
          "required" : true,
          "schema" : {
            "$ref" : "#/definitions/postCICSStockOrderService_request"
          }
        } ],
        "responses" : {
          "400" : {
            "description" : "Bad Request",
            "schema" : {
              "$ref" : "#/definitions/postCICSStockOrderService_response_400"
            }
          },
          "200" : {
            "description" : "OK",
            "schema" : {
              "$ref" : "#/definitions/postCICSStockOrderService_response_200"
            }
          }
        }
      }
    },
    "/stock/{groupCode}" : {
      "get" : {
        "tags" : [ "cicsstockrestfulservice" ],
        "operationId" : "getCICSStockCheckService",
        "parameters" : [ {
          "name" : "groupCode",
          "in" : "path",
          "required" : true,
          "type" : "string",
          "maxLength" : 4
        } ],
        "responses" : {
          "400" : {
            "description" : "Bad Request",
            "schema" : {
              "$ref" : "#/definitions/getCICSStockCheckService_response_400"
            }
          },
          "200" : {
            "description" : "OK",
            "schema" : {
              "$ref" : "#/definitions/getCICSStockCheckService_response_200"
            }
          }
        }
      }
    }
  },
  "definitions" : {
    "getCICSStockCheckService_response_400" : {
      "type" : "object",
      "properties" : {
        "stockCheck" : {
          "type" : "object",
          "properties" : {
            "returnCode" : {
              "type" : "integer",
              "minimum" : 0,
              "maximum" : 99
            },
            "responseMessage" : {
              "type" : "string",
              "maxLength" : 80
            }
          }
        }
      }
    },
    "getCICSStockCheckService_response_200" : {
      "type" : "object",
      "properties" : {
        "stockCheck" : {
          "type" : "object",
          "properties" : {
            "returnCode" : {
              "type" : "integer",
              "minimum" : 0,
              "maximum" : 99
            },
            "responseMessage" : {
              "type" : "string",
              "maxLength" : 80
            },
            "itemList" : {
              "type" : "array",
              "items" : {
                "type" : "object",
                "properties" : {
                  "itemId" : {
                    "type" : "string",
                    "maxLength" : 8
                  },
                  "itemName" : {
                    "type" : "string",
                    "maxLength" : 66
                  },
                  "itemPrice" : {
                    "type" : "integer",
                    "minimum" : 0,
                    "maximum" : 9999999
                  },
                  "stored" : {
                    "type" : "string",
                    "maxLength" : 1
                  },
                  "shipFrom" : {
                    "type" : "string",
                    "maxLength" : 64
                  }
                }
              },
              "maxItems" : 6,
              "minItems" : 6
            }
          }
        }
      }
    },
    "postCICSStockOrderService_request" : {
      "type" : "object",
      "properties" : {
        "stockOrder" : {
          "type" : "object",
          "properties" : {
            "orderList" : {
              "type" : "array",
              "items" : {
                "type" : "object",
                "properties" : {
                  "itemId" : {
                    "type" : "string",
                    "maxLength" : 8
                  },
                  "itemQuantity" : {
                    "type" : "integer",
                    "minimum" : 0,
                    "maximum" : 9999999
                  }
                }
              },
              "maxItems" : 6,
              "minItems" : 6
            }
          }
        }
      }
    },
    "postCICSStockOrderService_response_400" : {
      "type" : "object",
      "properties" : {
        "stockOrder" : {
          "type" : "object",
          "properties" : {
            "returnCode" : {
              "type" : "integer",
              "minimum" : 0,
              "maximum" : 99
            },
            "responseMessage" : {
              "type" : "string",
              "maxLength" : 80
            }
          }
        }
      }
    },
    "postCICSStockOrderService_response_200" : {
      "type" : "object",
      "properties" : {
        "stockOrder" : {
          "type" : "object",
          "properties" : {
            "returnCode" : {
              "type" : "integer",
              "minimum" : 0,
              "maximum" : 99
            },
            "responseMessage" : {
              "type" : "string",
              "maxLength" : 80
            },
            "stockOfItemList" : {
              "type" : "array",
              "items" : {
                "type" : "object",
                "properties" : {
                  "itemId" : {
                    "type" : "string",
                    "maxLength" : 8
                  },
                  "stockYN" : {
                    "type" : "string",
                    "maxLength" : 1
                  },
                  "stockNum" : {
                    "type" : "integer",
                    "minimum" : 0,
                    "maximum" : 9999999
                  }
                }
              },
              "maxItems" : 6,
              "minItems" : 6
            }
          }
        }
      }
    }
  }
}

商品の在庫確認(参照系)とオーダー(更新系)の2種類のオペレーションがあります。

参照系のURL: GET http://eplexa:30681/showroomdemo/v1/isecics/stock/{groupCode}
更新系のURL: POST http://eplexa:30681/showroomdemo/v1/isecics/order

curlでの実行例

参照系
curl -X GET --header 'Accept: application/json' 'http://eplexa:30681/showroomdemo/v1/isecics/stock/CITR'`
更新系
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{"stockOrder":{"orderList":[{"itemId":"CIWH0001","itemQuantity":1},{"itemId":"CIWH0002","itemQuantity":2}]}}' 'http://eplexa:30681/showroomdemo/v1/isecics/order'

API ConnectへSwagger文書の取り込み

ドラフト - API - 追加ボタン - ファイルまたはURLからAPIをインポートを選択して、上のSwaggerファイルを指定してインポートします。
image.png

"cicsstockrestfulservice 1.0.0"というAPIが作成されました。
image.png

アセンブリーの作成

アセンブルタブで、アセンブリーの作成ボタンをクリック
image.png

操作切り替えをドラッグ&ドロップし、ケース0,1にそれぞれgetCICSStockCheckService, postCICSStockOrderServiceを割り当てます。
image.png

呼び出しをそれぞれ割り当て、タイトル、URL、メソッドを指定します。
image.png

それぞれ以下のように指定します。(URLはSecure Gatewayのホスト名:ポートを指定)

項目 StockCheck StockOrder
タイトル invoke-stockCheck invoke-stockOrder
URL http://xxxx.securegateway.appdomain.cloud:nnnnn/showroomdemo/v1/isecics/stock/$(request.parameters.groupCode) http://xxxx.securegateway.appdomain.cloud:nnnnn/showroomdemo/v1/isecics/order
HTTPメソッド GET POST

最後に保存。

スキームの確認

取り込んだSwagger文書ではhttp,https両方有効になっていますが、API Connectではhttpは受け付けないようです。そのままの設定でAPIを公開しようとすると以下のように怒られることになるので、スキームの設定を変更します。
image.png

設計からスキームを選択し、httpのチェックをはずしておきます。
image.png

セキュリティー設定

以前実施した以下の手順に従って、APIキーを設定しておきます。
参考: セキュリティーの定義

image.png

image.png

製品の作成/公開

右上のメニューからデフォルト製品の生成を選択
image.png

image.png

製品の生成、公開までうまくいったようです。
image.png

一応ダッシュボード - カタログ"Sandbox"を選択して製品のステータス見てみます。
image.png

公開済みになってます。

アセンブルからテスト

API呼び出しのテストしてみる。=> OKでした。
image.png

開発者ユーザーによるテスト

開発ユーザーでSandboxの開発者ポータルにログインし、API製品からcicsstockrestfulservice product 1.0.0を選択
サブスクライブ(配信登録)します
image.png

image.png

cicsstockrestfulserviceから、API呼び出しを試してみます。
クライアントID、シークレットは、この開発ユーザーがアプリケーションを作成した時に生成されたものを使用します。
参考: 開発者ポータルでのアプリケーション作成
image.png

操作の呼び出しをクリックして、正常応答が返ればOKです。
(汎用的なREST Clientからもリクエスト投げられるはず)

これで一通り、API Connect - Secure Gateway 経由でバックエンドのサービスを呼び出すところまで確認できました!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0