Amazon EKSをGoogle Workspaceのアカウントで認証する

Amazon Elastic Kubernetes Service(Amazon EKS)のクラスターは、IAMを使って認証するわけですが、IAMはAWS SSOなどを利用することでID情報を外部から取得できます。したがって、Google Workspaceのアカウントなど外部IDでEKSクラスターを認証できます。

実際に運用するには、AWSアカウント構成など考慮点がたくさんあるかと思いますが、この記事では、AWSのルートアカウントでAWS SSOを有効化し、ID情報をGoogle Workspaceから取得して、そのAWSアカウントでEKSクラスターを作成して認証に使ってみます。

## AWS SSOの設定

まず、AWS SSOを設定して、Google Workspaceで管理しているアカウントでAWSのサービスにアクセスできるようにします。

いくつかUIに違いがあるだけで、ほぼ以下のブログに記載があるとおりですが、AWS SSOまわりの設定は後ほど本記事でも補完しようと思います。

https://aws.amazon.com/jp/blogs/security/how-to-use-g-suite-as-external-identity-provider-aws-sso/

## EKSクラスターの作成

### EKSクラスター管理ユーザーの作成

まず、EKSクラスターを構築、管理するユーザーを用意します。[前述のブログ](https://aws.amazon.com/jp/blogs/security/how-to-use-g-suite-as-external-identity-provider-aws-sso/)にある「Manage Users and Permissions」の手順で、手動でアカウントを作成できます。実際の運用では[ssosync](https://github.com/awslabs/ssosync)でアカウントを同期するのがいいと思います。

手動でアカウントを作成する際に一つだけハマったのはAWS SSOのユーザーを追加する部分で、 「`username`をGoogleアカウントのプライマリーメールアドレスにする」です。これを忘れると、ログイン時に`Invalid MFA credentials Your MFA credentials were incorrect. Please check your device and try again.`というエラーが発生します。

eksctlの実行には、AWS管理ポリシー `AdministratorAccess`または[eksctlのサイトに記載がある権限](https://eksctl.io/usage/minimum-iam-policies/)が必要なので、このユーザーに割り当てておきます。

### SSO ログイン

AWS CLI v2では、以下のようにSSOでログインできます。

```bash
## AWS SSOの設定
$ aws configure sso
$ aws sso login
```

詳細は以下をご確認ください。
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html

### EKSクラスターの作成

EKSクラスター管理ユーザーでSSOログインしたら、EKSクラスターを作成します。この記事では[eksctl](https://eksctl.io/)を利用します。
しかし、eksctlは現時点で、[aws configure ssoで作成したAWS SSOログイン情報を理解しない](https://github.com/weaveworks/eksctl/issues/1565)ので、そのままでは以下のようなエラーで利用できません。

```bash
$ eksctl create cluster -f cluster.yaml

[!]  retryable error (RequestError: send request failed
caused by: Put "http://169.254.169.254/latest/api/token": dial tcp 169.254.169.254:80: connect: host is down) from ec2metadata/GetToken - will retry after delay of 3.561742848s
```

この記事では、eksctlをAWS SSO環境下で利用するために[aws2-wrap](https://github.com/linaro-its/aws2-wrap)を使ってみました。このツールは、`terraform`や`eksctl`などの、AWS SSOクレデンシャルに対応していないツールでもAWS SSOクレデンシャルを使えるようにしてくれるラッパーツールです。

```bash
# aws2-wrapのインストール
$ python3 -m pip install aws2-wrap
$ aws2-wrap eksctl create cluster -f ./cluster.yaml

[ℹ]  eksctl version 0.33.0-rc.0
[ℹ]  using region ap-northeast-1
[ℹ]  setting availability zones to [ap-northeast-1c ap-northeast-1d ap-northeast-1a]
[ℹ]  subnets for ap-northeast-1c - public:192.168.0.0/19 private:192.168.96.0/19
[ℹ]  subnets for ap-northeast-1d - public:192.168.32.0/19 private:192.168.128.0/19
[ℹ]  subnets for ap-northeast-1a - public:192.168.64.0/19 private:192.168.160.0/19
[ℹ]  using Kubernetes version 1.18
...
```

これで、AWS SSOを使ってGoogleアカウントでログインしたユーザーでEKSクラスターが作成されました。

```bash
$ kubectl get nodes
NAME                                                STATUS   ROLES    AGE     VERSION
ip-192-168-34-136.ap-northeast-1.compute.internal   Ready    <none>   6m24s   v1.18.9-xxx
ip-192-168-83-237.ap-northeast-1.compute.internal   Ready    <none>   6m39s   v1.18.9-xxx
```

## EKSクラスターに開発者アカウントを追加する

次に、開発者アカウントをこのEKSクラスターに追加してみます。EKSクラスターの管理ユーザーを作成したときと同様、[前述のブログ](https://aws.amazon.com/jp/blogs/security/how-to-use-g-suite-as-external-identity-provider-aws-sso/)にある「Manage Users and Permissions」の手順で、手動でアカウントを作成します。このユーザーにはEKSクラスターのDescribe、EKSクラスター認証のためのトークン取得の権限などが必要です。ここでは、`ReadOnlyAccess`を割り当てますが、実際には、適切に権限を設定する方がいいでしょう。

### 開発者アカウントを、EKSクラスターに追加する

上記で作成したユーザーにはIAMロールが割り当てられています。具体的なIAMロールは、[IAMのコンソール](https://console.aws.amazon.com/iam/home#/roles)から、アクセス権限セットの名前でロールを検索すると表示されます。このIAMロールを、EKSクラスターの`aws-auth`に設定します。
このときセットするロールのフォーマットは、 `arn:aws:iam::<ACCOUND_ID>:role/<ROLE_NAME>`となります。


```bash
$ kubectl -n kube-system edit cm aws-auth
```


```yaml
apiVersion: v1
data:
  mapRoles: |
    ....
    - rolearn: arn:aws:iam::<ACCOUND_ID>:role/<ROLE_NAME>
      username: developer1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
```

### EKS上のユーザーに権限を割り当てる

この開発者アカウントに、`dev1`というNamespaceを管理する権限を割り当ててみます。

```bash
$ kubectl create ns dev1
$ kubectl -n dev1 create rolebinding dev1-developer1 --clusterrole admin --user developer1
```

実際に開発者アカウントでログインし、Kubernetesリソースを作成できることを確認します。

```bash
## 開発者アカウントでのログインを設定
$ aws configure sso

# kubectl更新
$ aws --profile <AWS SSOログイン用プロファイル> eks update-kubeconfig --name <EKSクラスター名>

# Kubernetesリソースを作成してみる
$ kubectl run nginx --image=nginx -n dev1
$ kubectl get pods -n dev1

# 他のリソースにアクセスできないことを確認
$ kubectl get pods -n default
Error from server (Forbidden): pods is forbidden: User "developer1" cannot list resource "pods" in API group "" in the namespace "default"
```

## まとめ

この記事では、Google Workspaceなど、AWS外のIDを利用してEKSクラスターに認証するために、簡単な手順を記載してみました。IAMと連携できる様々なIDプロバイダーも同じように利用できますので、試してみていただければと思います。