【10分でできる】grpc + Python + Authentication のチュートリアル

**@kenmaro**です。
普段は主に**秘密計算、準同型暗号などの記事について投稿しています**。
秘密計算に関連するまとめの記事に関しては以下をご覧ください。

> - [秘密計算エンジニアを始めて２年半が経った。](https://qiita.com/kenmaro/items/48059dd60f79e80f5ef8)
> - [秘密計算エンジニアを始めて3年が経った。](https://qiita.com/kenmaro/items/a1d90a074d552b7bf886)


## 概要


今回の記事の内容は、**grpc をPython で使う際**の

- **SSL/TLS をgrpcに実装する**
- **SSL/TLS + token によるAPIへのアクセスコントロールを実装する**

の２種類となっています。


コードはこちらに上げています。

https://github.com/kenmaro3/grpc_auth


結局のところ公式ドキュメント

https://grpc.io/docs/guides/auth/#base-case---no-encryption-or-authentication-4

をなぞっているだけです。

しかし今回のチュートリアルレポジトリでは
鍵の作成方法なども含めてレポジトリにはまとめているので、
**１０分くらいで動作確認できると思います。**


また、この記事は以前に書いた

https://qiita.com/kenmaro/items/8517c78d5207252c229a

この記事を改良したものとなっています。


## auth の種類

公式ドキュメントより、４つのauthenticationがサポートされているようです。

- **SSL/TLS auth**
- **Google auth with JWT**
- **Google auth with Oauth2**
- **SSL/TLS + custom header token auth**


今回は、このうち1番目と４番目の

- **SSL/TLS auth**
- **SSL/TLS + custom header token auth**

について試してみます。


## SSL/TLS auth

まず、クローンしてレポジトリを落としてきます。

```
git clone https://github.com/kenmaro3/grpc_auth.git
cd grpc_auth
```

次に、鍵を生成します。


```
sh keygen.sh
```


**ここで、注意点として、
`Common Name`　セクションに　`localhost`
と入力してください。他は空欄で大丈夫です。**

![Screen Shot 2022-06-21 at 12.21.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/b67d20a3-ceec-389a-e598-031b0a7b7e8f.png)


できた鍵（server.crt, server.key）をコピーします。


```
cp server.crt ssl_auth/
cp server.key ssl_auth/
```

次に、grpcサービスに必要なファイルを生成します。

```
cd proto && mkdir grpc_service && python gen.py && cp sed.sh grpc_service && cd grpc_service && sh sed.sh
```

このとき、`sed.sh`はあとから server, client のコードを走らせるときのパスの調整で行っています。

次に、grpc_service フォルダを `grpc_auth`の下にコピーします。（このgrpc_service フォルダをservice, client からimport します。）

```
cp -r grpc_service ../
```

これで準備完了です。

実際にserver を立ち上げます。

```
cd ssl_auth && python controller.py
```

別ターミナルで client を実行してみます。

```
python client.py
```

```
hello, world
res: done!
```

と出れば接続できています。お疲れ様でした。



## SSL/TLS + custom header token auth

このauth方法でも、同様に上述した同じ方法を用い、SSL/TLS通信に必要な鍵の作成、
およびgrpc 通信に必要なモジュールを追加します。

SSL/TLSの手法と一つだけ違うところは、
client は、server 側が指定したトークンを、コネクションを確立するときに渡す必要があることです。


```
custom_header_token/controller.py
custom_header_token/client.py
```

を見ると、`access_key`
と書いてあると思いますが、これがサーバ側が指定したトークンです。

```
AuthInterceptor
```
の実装を見ればわかる通り、APIが呼ばれたとき、ヘッダーにトークンがなかった場合denyするようになっています。

実際に、トークンによってAPIへの接続が制限されていることを確認しましょう。

```
cd custom_header_token
```

```
python controller.py
```

でサーバーを立ち上げ、別ターミナルで

```
python client.py
```

とすると、

```
hello, world
res: done!
```

となり、APIから結果が返ってきているのがわかります。


次に、client のtokenの内容を書き換えてみます。

client.py の

```client.py
        grpc.metadata_call_credentials(
            GrpcAuth('access_key')
        )
```

の記述を、

```client.py
        grpc.metadata_call_credentials(
            GrpcAuth('access_key_changed')
        )
```

にしてみましょう。

今回は、

```
python client.py
```

の結果が

```
status = StatusCode.UNAUTHENTICATED
```

となりrejectされていることがわかります。


チュートリアルは以上となります。お疲れ様でした。


## まとめ

今回は、**grpc + python + authentication** として、

- **SSL/TLS でのauth**
- **SSL/TLS + token によるauth**

の２種類を実際に動かしてみました。

特に２つ目の実装を使えば、APIにアクセス制限をかけることができます。
今回は実装したAPI、トークンはそれぞれ１種類だったのですが、
次回は複数のトークンを発行し、
ユーザに対してアクセスできるAPIを分ける、

みたいなことをやってみたいと思います。



今回はこの辺で。


@kenmaro