こんにちは!インフラやクラウドのセキュリティの世界へようこそ。
新人のIT担当者や、これからクラウドセキュリティをしっかり学んでいきたいという開発者の皆さんに向けて、日々の業務に直結する大切なテーマをお届けしますね。
今日は、現代のクラウドインフラで主流となっているコンテナ環境、その中でも特に重要な「Pod単位でのIAM権限の付与(EKSのIRSAやGKEのWorkload Identity)」について、一緒に紐解いていきましょう。
小難しいセキュリティ用語が出てくると、どうしても身構えてしまいますよね。「IAMって何?」「ノードとかPodってどう違うの?」と不安になるかもしれませんが、大丈夫です。身近な「お家の防犯」に例えながら、一歩ずつ優しく解説していきますので、リラックスして読んでいってくださいね。
—
1. なぜ「コンテナの権限管理」が重要なのか?(お家の防犯に例えてみよう)
皆さんが暮らす家を想像してみてください。
昔のクラウド(古い仮想サーバーの運用など)は、一戸建ての家に例えるなら「家族全員が、家中のすべての部屋の合鍵を1本ずつポケットに入れて持ち歩いている状態」でした。
リビングのテレビを見るのも、お父さんの書斎に入るのも、お母さんの宝箱を開けるのも、ぜーんぶ同じ1本の鍵で開けられちゃいます。これって、もしその鍵をうっかり玄関に置き忘れたり、泥棒に盗まれたりしたら……家全体の財産がすべて危険にさらされてしまいますよね。
これが、従来の「ノード(サーバー自体)単位で強大な権限を持たせていた時代」のセキュリティリスクです。
コンテナ環境(Pod)と現代の防犯
現代のKubernetes(EKSやGKE)の世界では、1つの家(サーバー)の中に、たくさんの小部屋(Podというコンテナ)がギュッと詰まっています。
ここで私たちが目指すべきなのは、「Aの部屋の住人は、Aの部屋の鍵しか持っていない。お隣のBの部屋には絶対に入れない」という、徹底した部屋ごとの鍵の管理(最小権限の原則)です。
もし万が一、Aの部屋の住人が悪者に乗っ取られてしまっても、持っているのは「Aの部屋の鍵」だけなので、他の大切な部屋(例えば、データベースや顧客情報が眠るストレージなど)には指一本触れることができません。
この仕組みを実現するのが、AWSならIRSA(IAM Roles for Service Accounts)、GCPならWorkload Identityと呼ばれる機能なんです!
—
2. 攻撃者はどこを狙うのか?(甘い権限設定の罠)
では、もしこの権限の切り分けをサボって、サーバー(ノード)全体に強い権限をドカンと与えたままでいると、攻撃者にはどのように狙われてしまうのでしょうか?
攻撃者の手口はこうです。
1. アプリケーションのちょっとしたプログラムの隙(脆弱性)を突いて、特定のコンテナ(Pod)の中に侵入します。
2. そのコンテナの中で「おや、このサーバーにはどんな権限が設定されているかな?」と、クラウドの管理用バケツ(S3バケットなど)のドアをノックしてみます。
3. もしノード全体に「何でもできるスーパー権限」が与えられていたら、攻撃者はコンテナから一歩外に出るだけで、クラウド上のすべてのデータを自由に覗き見したり、改ざんしたりできるようになってしまうのです。
「うちのアプリは大丈夫だよ」と思っていても、外部から読み込んでいるライブラリに思わぬ穴が見つかることは、エンジニアの現場ではよくあることです。だからこそ、「万が一侵入されても、被害をその部屋だけで食い止める(=権限を絞る)」という防壁が必要不可欠になります。
—
3. 実践!EKS (IRSA) と GKE (Workload Identity) の仕組み
それでは、具体的にどうやって「部屋ごとの鍵」を渡すのか、その仕組みと設定のポイントを見ていきましょう。
3-1. AWS EKSの場合:IRSA(IAM Roles for Service Accounts)
EKSでは、Kubernetesの「サービスアカウント(ServiceAccount)」という概念と、AWSの「IAMロール」をガチャンと結びつけます。
これによって、特定のServiceAccountを使って立ち上がったPodだけが、指定された特定のIAMロール(=特定のAWSリソースを操作する権限)を一時的に借りることができるようになります。
設定のサンプルコード(Kubernetesのマニフェスト)
実際にKubernetes上で動かすマニフェストファイルの書き方を見てみましょう。ポイントは、annotations(注釈)の部分で「どのIAMロールを使うか」を指名することです。
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-app-service-account # Kubernetes側のサービスアカウント名
namespace: default
annotations:
# ここでAWSのIAMロールのARN(住所のようなもの)を紐付けます
eks.amazonaws.com/role-arn: "arn:aws:iam::123456789012:role/my-secure-s3-read-role"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
# 上で定義したサービスアカウントをこのPodに割り当てます
serviceAccountName: my-app-service-account
containers:
- name: web-app
image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest
ports:
- containerPort: 8080
この設定をしておけば、このPodの中で動くアプリケーションプログラムは、特別なパスワードなどをコードに書かなくても、安全にAWSのS3などにアクセスできるようになります。
—
3-2. GCP GKEの場合:Workload Identity
GKEの場合も考え方は同じです。GKEのクラスター上で動くKubernetesのサービスアカウントと、GCPのIAMサービスアカウントをバインド(結びつけ)します。
こちらも、ノード自体には強い権限を持たせず、Podが必要最小限のGCPリソース(Cloud StorageやBigQueryなど)にだけアクセスできるように設定します。
設定の流れ(コマンドのイメージ)
実務では、以下のような手順でGoogle Cloudの安全な橋渡しを作ります。
# 1. Kubernetes側でサービスアカウントを作成する
kubectl create serviceaccount k8s-service-account --namespace default
# 2. GCP側のIAMサービスアカウントに対して、K8sのサービスアカウントになりすます権限を許可する
gcloud iam service-accounts add-iam-policy-binding \
gcp-iam-sa@my-project-id.iam.gserviceaccount.com \
--role="roles/iam.workloadIdentityUser" \
--member="serviceAccount:my-project-id.svc.id.goog[default/k8s-service-account]"
# 3. Kubernetesのサービスアカウントに、GCP側のIAMサービスアカウントをアノテーションで紐付ける
kubectl annotate serviceaccount k8s-service-account \
--namespace default \
iam.gke.io/gcp-service-account=gcp-iam-sa@my-project-id.iam.gserviceaccount.com
このように、クラウドプラットフォームの機能を正しく使うことで、「どのPodが、どのクラウドサービスへアクセスして良いか」を完全にコントロールできるようになります。
—
4. 現場のホワイトハッカーから皆さんへ:セキュリティを楽しむコツ
いかがでしたでしょうか?
「Pod単位でのIAM権限の割り当て」と言われると難しく聞こえますが、要するに「それぞれのアプリに、必要最低限の合鍵だけを渡すことで、もしもの時の被害を最小限にする防犯テクニック」です。
新人のうちは、「とりあえず動かすために、強い権限を全部のせてしまおう!」と焦ってしまうこともあるかもしれません。ですが、そんな時こそ一歩立ち止まって、
- 「このアプリケーションは、本当にすべてのデータに触る必要があるだろうか?」
- 「もっと権限を絞ることはできないだろうか?」
と考えてみるクセをつけてみてくださいね。
セキュリティの基本は、こうした「ちょっとした気配りの積み重ね」にあります。
今日学んだ知識を武器に、ぜひ皆さんの開発現場やインフラ環境をより安全で強固なものにしていってください。応援しています!
コメント