仮想マシンからプライベートCloud Functionsの呼び出し

## はじめに

この記事は、
　[Calling a private Cloud Function from a virtual machine](https://www.youtube.com/watch?v=IVOp5TL5cK4)
という動画を視聴し『実際にやってみた』という記事になります。

## この記事でできるようになる事。
Compute Engine の VMインスタンス から、
SSH接続で、Cloud Functions を `curl` する。

## Cloud Functions について簡単に理解しておく。
Cloud Functionsは、『イベント駆動』と呼ばれる、
特定のイベントやトリガーに応答して実行されるもので、
アプリケーションやサービスのバックエンドロジックを
サーバレスに実行する事が可能です。

このサーバーレスの特性により、開発者は関数のロジックにのみ
集中でき、インフラやサーバーの管理に関する手間が
大幅に減少し、開発の簡素化を実現することができます。

また、トラフィックの増減に応じたオートスケーリングや、
短い実行時間を持つ小さなタスク処理にも最適だとされています。

## Google Cloud API を有効化
GCPプロジェクトのコンソールへ接続。

`Compute Engine API`
`Cloud Functions API`
`Cloud Run Admin API`
`Cloud Build API`
`Cloud Logging API`
`Cloud Pub/Sub API`

これらのAPIを有効化。
その他、APIの有効化は、必要に応じて、適宜行ってください。

## 仮想マシンがプライベートCloud Functions と通信できるようにするメリット。
- セキュリティ向上:
プライベートCloud Functionsは、公開されていないプライベートな
環境で実行されるため、外部からの不正なアクセスを避けることができる。
仮想マシンからの専用通信路を利用することで、
通信内容の保護やデータ漏洩のリスクを低減できます。

- レイテンシの低減:
同一のクラウドプロバイダ内で通信が行われる場合、
ネットワークの遅延が最小限に抑えられ、より迅速な応答が期待できる。

- データの一貫性:
仮想マシンとCloud Functionsの間での直接の通信は、
データの整合性や同期を維持しやすくなります。

- コスト削減:
公開されているエンドポイントに対する
外部トラフィックのコストが不要になる場合がある。
特に、大量のデータを頻繁にやり取りする場合、
このメリットは顕著になる可能性がある。

- 簡単な管理:
プライベート接続を利用することで、
公開エンドポイントの管理や、
その他の公開に関する複雑さを排除できます。

- 拡張性:
仮想マシンとプライベートCloud Functions間の通信は、
システムの拡張やスケーリングが必要になった場合に、
迅速かつ簡単に対応できるようになります。

## 内部トラフィックのリクエストのみを許可するCloud Functions を Deploy する。
まず、始めに、VMインスタンスが、プライベートCloud Functions を
呼び出せることを検証する為、内部トラフィックの
リクエストのみを許可するCloud Functions を Deploy します。

今回は、デフォルトのHello World 関数を使ってテストします。

Cloud Functions　に移動して、ファンクションを作成をクリック。
![cloudfunction-create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/20366b38-3a25-93f4-03a7-39c0d0848b00.png)

ファンクションの関数名の決定、およびリージョンの選択を行う。
![cloudfunction-create-name.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/78a81643-f5b8-88f8-851f-fe7f3ce65a68.png)

トリガーはデフォルトで、HTTPSが選択されているので、
そのまま、『認証が必要』を選択する。
![cloudfunction-trigger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/6161584e-be5d-3c1c-b247-f66d79bfd7e9.png)

外部リクエストをブロックする為、接続は『内部トラフィックのみを許可する』を選択。
![cloudfunction-create-traffic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/289f324a-97c8-85bc-b0d0-536e13a240bc.png)

その他はデフォルトのまま、Cloud Functions の Deployを実行してください。

正常にDeployされたら、Cloud Functions の URL を
クリックして、リクエストが拒否される事を確認。
![cloudfunction-url.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/02def4af-27b2-a728-ead2-ca8b7e919b8b.png)

リクエストが拒否されていれば成功です。
![cloudfunction-url-req.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/e585bfbb-5440-811b-33a1-a38ead1c0846.png)

## GSAを作成して、適切なIAMロールを付与する。
動画では、デフォルトのサービスアカウントを使用していますが、
プラクティスは、編集者ロールや管理者ロールなどの強い権限を
付与するのではなく、その目的にあったカスタムロールを付与するのが
最良の選択ですので、必要最低限の権限の原則に基づいて、
サービスアカウントを作成し、必要なロールを付与します。

IAMと管理に移動して、『サービスアカウント』を作成をクリック。
![sa-create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/5e50a75d-5be8-6bdc-e8c1-9cc7acfaf29b.png)

『サービスアカウト名』と『サービスアカウントの説明』を
入力して、『作成して続行』をクリック。
![sa-create-describe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/fd5084e8-eb75-ffe3-26af-224fc18c939a.png)
ロールを付与する。
必要最低限の権限の原則に基づいて、
ロールは、
『`Cloud Functions 起動元`』
『`Cloud Run 起動元`』
を続けて選択して、『続行』をクリック、GSAを作成。
![sa-create-roll.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/d2baf348-7797-3b8e-c29a-c039f7ce2dc7.png)
`Cloud Functions 第2世代`では、
`Cloud Run 起動元 ロール`が必要になります。

これは、`Cloud Functions V2` の実行環境が内部的に
Cloud Run上で動いている事が理由に挙げられます。

## 仮想マシンからプライベートCloud Functions を呼び出す。
内部トラフィックのみを許可するように、Cloud Functions を
作成したら、仮想マシンから内部トラフィックを送信できるかを確認します。

Compute Engine から『インスタンスを作成』をクリック。
![compute-create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/486c51b8-b44f-3462-b46d-7aeb940e92af.png)
VMインスタンスの名前とリージョン、ゾーンを選択。

リージョンとゾーンは最寄りを選択する事。
リージョンとゾーンはVM作成後は変更できないので注意が必要。
![compute-create-name.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/abf52340-9cbd-faa7-1f50-09be4a80bb99.png)

適切なサービスアカウントを選択し、
その他はデフォルトのまま、作成を実行してください。
![compute-create-gsa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/8c8a0fa1-1619-4060-6cd3-0b3751f2f399.png)

正常にVMインスタンスがDeployされればOK。
![compute-create-done.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/51696845-5f10-d3c8-1007-52caa8b2f065.png)

## VMインスタンスをSSHで接続し、Cloud Functions を curl する。
SSHをクリック。
![vm-ssh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/89ba1ff2-2b0a-3fd7-24d7-64490d94bf2b.png)
ブラウザでのSSHによるVMへの接続を許可。
![vm-ssh-auth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/0f45d79d-ac56-369f-e926-32abe788a0d3.png)
DeployしたCloud Functions のURLをコピーしてください。
![cloudfunction-url.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/cfbc182c-7fa8-8755-01a9-7ebca9f40854.png)

`curl` の後に続けて、先ほどコピーしたCloud Functions の
URLをペーストして、コマンドを実行してください。

サンプル
```
curl https://[REGION]-[PROJECT_ID].cloudfunctions.net/[FUNCTION_NAME]
```

ただし、この実行では、403エラーが返されます。
![vm-curl-error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/edb2daa9-f589-9e8f-e6f8-f87009c6a28f.png)
これは、`Authorization ヘッダー` による認証方法が選択されていない為です。
認証方法はいくつかありますが、今回は、『`Bearerトークン`』を使用します。

`Bearerトークン` については、詳細な説明は省きますが、
OAuth 2.0認証スキームの一部として使用されるアクセストークンの一つです。

詳しくは、こちらの記事を参考にしてください。

https://apidog.com/jp/blog/what-is-bearer-token/


`Authorization ヘッダー` で、認証方法に`Bearerトークン`を
選択して、再度 `curl` コマンドを実行してください。

サンプル
```
curl https://[REGION]-[PROJECT_ID].cloudfunctions.net/[FUNCTION_NAME]　-H "Authorization: Bearer $(gcloud auth print-identity-token)"
```

『Hello World!』が表示されましたら、
仮想マシンからプライベートCloud Functionsの呼び出しは成功になります。
![cloudfunction-run.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/6cbaf08c-989d-a22d-bb62-a4cf627b3500.png)

## 終わりに
今回の記事は、動画を視聴しまして、
実際に『手を動かしてみた』という内容でまとめました。

Cloud Functions でプライベート接続を
試してみようと思われていましたら、
参考にしていただけると幸いです。

あとで『じっくり読みたい』、『繰り返し読みたい』と
思ってくれましたら、『`ストック`』へ登録、
この記事が読まれている方にとって、
参考になる記事となりましたら、『`いいね`』を
付けていただけますと、励みになりますので、
よろしくお願いします。