Coursera の "Securing and Integrating Components of your Application" を受講したメモ (IAM, IAP, Pub/Sub, Cloud Endpoint, Cloud Function, etc)

Coursera の [Securing and Integrating Components of your Application](https://www.coursera.org/learn/securing-integrating-components-app) を受講したメモである。


## 関連記事

- [Getting Started With Application Development(Datastore, Bigtable, Cloud Spanner, etc)](https://qiita.com/kudojp/items/9891c8491f8bea264cd0) 
- 🌟 [Securing and Integrating Components of your Application(IAM, IAP, Pub/Sub, Cloud Endpoint, Cloud Function, etc)](https://qiita.com/kudojp/items/08103d1e8fdb565cb27b)
- [App Deployment, Debugging, and Performance(Cloud Build, App Engine, Cloud Monitoring, etc)](https://qiita.com/kudojp/items/9e0795219c81e848febe)



## IAM concepts

https://qiita.com/os1ma/items/df01080dfa81c185357e がわかりやすいので、これをみてほしい。(完)

policyはリソースベースで以下のようにbindingの集合として作成される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/f80063f1-8df8-5e50-de6b-1046930fa7ca.png)



role は permission の集合で以下の３種類。

<details>
<summary>basic role</summary><div>

(昔はprimitive roleと呼ばれていた)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/8627b4c8-3d4e-0e78-773d-5638cbce8bee.png)

</div></details>


<details>
<summary>predefined role</summary><div>



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/89d2f2bb-4e45-6a4a-31f2-235632d2c37f.png)

</div></details>

- cutsom role


### service account


- Google uses credentials to identify your application for quota and billing and to authorize access to GCP APIs, resources, and features.

- GCPのclientはcredentialを、`環境変数GOOGLE_APPLICATION_CREDENTIALS`→`default service account(GCE, GKE, で動いている場合見つかる)`の順に探し、見つからなかったらエラーを吐く


- Use Cloud Audit Logging to regularly audit changes to your IAM policy and export logs to Cloud Storage.


## IAP(Identity Aware Proxy)

IAP とは、ウェブサイトへのリクエストをインターセプトし、リクエストを送信したユーザーを認証して、認証されたユーザーにのみサイトへのアクセスを許可する、という一連の処理を行うサービスです。

IAP allows you to establish a central authorization layer for applications accessed by https. IAP led to adopt an application-level access control model instead of relying on network-level firewalls. 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/88712fe7-efbb-db0b-4b0c-8e530972fdf9.png)


Applications and resources protected by IAP can only be accessed through the Proxy by users and groups with the correct Cloud IAM role.

他に開発者がやらなければいけないことは、 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/f61fcf69-56df-acce-6097-136419e745b8.png)




## Pub/Sub

- pull型だと、一つのsubscriptionを複数のsubscriberに紐づけることもできる(? -> https://googleapis.dev/python/pubsub/latest/index.html#subscribing)
    - subscriber = 各サービスのpub/subクライアントという認識

- pub/subは、at least onceなので、
    - subscriber側で処理をidempotentにする
    - publisher側でunique idを指定し、subscriber側で(DataStore, Cloud Bigtableなどを使い)既に受け取ったメッセージは処理しないようにする

- pub/subはmessage orderingが保障されていないので、
    - messageの処理順には意味はあるべきではない。(messageの順序に意味はあっていい)
    - (が)messageの処理順を保障した場合には、例えば以下のいずれかの方法が使えそう。
        - messageのidを連番にしておき、subscriber側で処理した最新のidを保存しておく。これによって、subscriberが新しく取得したmessageのidが、最新のid+1になっていない場合はそのmessageをpendingとして、cloud datastoreに保存する。もし、最新のid+1ならそこで処理する、かつpendingのmessageで続いて処理できるものを処理する。
        - subscriberでは受け取ったメッセージをまずはdatastoreに保存する。この前提の上で(定期的に??messageを受け取った時に??)subscriberは、cloud monitoringのmetricsを見にいき、そのtopicにおける最古の**unacknowledged** messageのpublished_atを取得する。datastoreに保存されているメッセージのうち、このpublished_atよりも古いpublished_atのmessageはsubscriberが確実に受け取ってdatastoreに保存していることが保障されている。このようなmessageをpublished_atが古い順に処理し、なおかつdatastoreからそれらを取り除く。

- cloud storageへのアップロードをpub/subのmessageにするには
    - See: https://cloud.google.com/storage/docs/pubsub-notifications

- pub/subをcloud functionのtriggerにするには、
    - There is a single Pub/Sub event used by Cloud Functions, and it has the trigger type value `google.pubsub.topic.publish`. This event is sent when a message is published to a Pub/Sub topic that is specified when a function is deployed. Every message published to this topic will trigger function execution with message contents passed as input data.


## Cloud Function

- triggerは以下など。
    - Cloud Pub/Sub topic
    - Cloud Storage bucket
    - HTTP trigger
- functionのコードのファィルは(staging locationとして)Cloud Storageに保存される

- 非同期的に実行されるものはbackground function、同期的に実行されるものはHTTP functionと呼ばれる。
    - background functionの例としては、`storageにuploadされる → それをtriggerとしてcloud functionが実行され、その実行結果を他のDBに保存する → それをtriggerとして、また他のcloud functionが実行される`....



- Node.jsの場合の使用法をメモる
    - `index.js`に実行関数を書く。
    - package.jsonにdependenciesを書く。
    - 一時的なファイルは `/temp`(インメモリ)に保存できる
    - functionはgloudコマンドか、GCPコンソールでデプロイできる
    - 発されたエラーはError Reportingに送信される


## Cloud Endpoints と APIGee

API管理サービス。既存のバックエンドサービスのAPIの前段にAPI Gateway(Proxy)を作る。このProxyにより、以下が可能になる。(API Gatewayと言っても、BFFのように複数のマイクロサービスを叩き得られたデータをがっちゃんするものではない)。


### Cloud Endpoints

- 後段のAPIエンドポイントが**GCP上にある場合のみ**使用できる。
- 後段に置けるのは以下。
    - `Open API エンドポイント` (前段にExtensible Service Proxyが置かれる)
    - `gRPC エンドポイント` (前段にExtensible Service Proxyが置かれる)
    - `App Engine Standard` の Python2.7/Java8 ランタイム環境 (Endpoints Frameworksに組み込まれ、前段に Proxy(not ESPという認識)が置かれる)

- APIの呼び出し回数に応じて課金される。
- NGINX ベースのプロキシと分散型アーキテクチャ


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/7547b8ae-d62b-9139-0b15-cb02b9dca70b.png)
(https://cloud.google.com/endpoints/docs/grpc/about-grpc?hl=ja より画像を引用)

以下の機能が提供される

- API の保護
    - JSON Web Token と Google API キーを使用して、API にアクセスできるユーザーを制御し、すべての呼び出しを検証します。また、Auth0 および Firebase Authentication と統合されているので、ウェブ アプリケーションまたはモバイルアプリのユーザーを識別できます。

- ロギングとモニタリング
    - トラフィック、エラー率、レイテンシをモニタリングし、Cloud Logging でログを確認できる
    - Cloud Trace でパフォーマンスを詳しく調べられる



<details>
<summary>開発方法</summary><div>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/687cee3c-d5c8-f942-493f-8eedac60e1f7.png)
(deploy api configurationは、GCP cloud endpointsにおいてサービスとして作成する。ここで発行されたconfig idとservice nameを、App Engine flexibleを使用しているならバックエンドのapp.yamlに指定し、そのバックエンドサーバをdeployする)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/70def9b4-b4f3-3b57-2932-ff0266b8b24e.png)
</div></details>





### APIGee

- 後段のAPIエンドポイントが**GCP上にない場合にも**使用できる。(オンプレミスのエンドポイントの前段で使用できる)
- 後段に置けるのは`Open API`。
- ビジネス上の問題にフォーカスしており、サービスの収益化に重点を置いていて、APIが叩かれるレート制限や、詳細な分析ができるようになっている








## Cloud Tasks

Cloud Tasksとは、完全マネージド型のメッセージキューサービスです。 大量のタスクの分散実行や配信管理、リトライ処理を行うことが可能です。AWSでいうSQS。https://zenn.dev/nananaoto/articles/bd1584c77e46f128a41a がわかりやすい。

- タスク
    - RailsでいうとActiveJob(~~ただし中身はただのメッセージ~~ タスクなのかも)
    - アプリケーションでタスクを作成するには、クライアントライブラリを使用する。実行したいタスクの内容を定義し、送信したいキューを指定するだけ。また、コマンド上でコマンドラインツールを使用して作成することもできる(maxAttemptsとか指定できる)。
    - 内部的には、Cloud Tasks サーバーへHTTPSリクエストを送信し、それがキューに追加されている。
    - タスクにタスクIDを指定することで、重複したタスクが同一のキューに追加されなくなる。
- キュー
    - RailsでいうとSidekiqがjobの保存のために使用しているRedis
- タスクハンドラ
    - RailsでいうとSidekiqのバックグランドワーカー
    - キューからHTTPリクエストを受け取ることで発動される(push型という認識)。
    - Cloud Function, Clout Run, App Engineなどを使用できそう。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/78b5e1f5-55b4-3c52-81ca-aa77106b0d01.png)

- Pub/Subとの違いとして、queue -> subscriber の通知方法が push しかないことがありそう。


## Cloud Scheduler

GCP上でcronjobのスケジューリングができる。


## その他雑多なメモ

api2swaggerコマンドでapi.jsonを始めて作成した、この時の標準出力を以下にメモる。

```
api2swagger -e https://xxx.yyy.com/api/quizzes/places -o ./quiz-api.json
? Title of Swagger Spec ? Quite Interesting Quiz API
? Description of Swagger Spec ? An API for the Quite Interesting Quiz
? Terms of Service URL ? http://example.com/about/terms
? Version of your API Program ? 0.0.1
? Contact Name? API Docs
? Contact URL ? http://example.com/contact
? Contact Email ? apidocs@example.com
? License Name ? Apache 2.0
? License URL ? http://example.com
? Does your API support http ? Yes
? Pick Base Path from your API ? /api/quizzes
? A verbose explanation of the operation behavior.  ? API Method Description
? A short summary of what the operation does. ? Get quiz questions
? Additional external documentation for this operation. ? http://docs.example.com/management/apis/get/entities
? Unique string used to identify the operation. ? getQuizQuestions
? A list of tags for API documentation control.  ? api2swagger
Making an API Call & fetching more details...Please stay tuned..
? API Path has any dynamic parameters ? Yes
? Choose Dynamic Params in URL ?
{
  "swagger": "2.0",
  "host": "xxx.yyy.com",
  "schemes": [
    "https",
    "http"
  ],
  "info": {
    "description": "An API for the Quite Interesting Quiz",
    "title": "Quite Interesting Quiz API",
    "version": "0.0.1",
    "termsOfService": "http://example.com/about/terms",
    "contact": {
      "name": "API Docs",
      "url": "http://example.com/contact",
      "email": "apidocs@example.com"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "http://example.com"
    }
  },
  "basePath": "/api/quizzes",
  "paths": {}
}
Swagger JSON File successfully generated in : ./quiz-api.json
```