Teleportによるゼロトラスト・インフラアクセス:SSHとKubernetesクラスター管理の一元化

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

背景と導入理由:静的SSHキーからの脱却

50台のクラウドインスタンスと3つのKubernetesクラスターに公開鍵を配布するのは、誰かがノートPCを紛失するまでは簡単に思えるかもしれません。当初はAnsibleやcloud-initを使ってエンジニアの公開鍵を~/.ssh/authorized_keysに配置するだけでも問題なく動作します。しかし、やがて技術的負債が重くのしかかってきます。秘密鍵は暗号化されないまま個人のマシンに放置され、チーム内で鍵がローテーションされることは稀で、退職時のアクセス権削除(オフボーディング)は数十台のホストを巡る面倒な探し回し作業と化します。

Kubernetesのアクセス管理でも全く同じ悪夢が起こります。90日間有効なトークンを含む静的な管理者用kubeconfigファイルを配布すると、一元化されたIDプロバイダー(IdP)をバイパスしてしまい、コンプライアンス要件を満たせなくなります。もしエンジニアのワークステーションが侵害された場合、攻撃者はそのYAMLファイルに記録されたすべての本番クラスターへの直接アクセス権をそのまま手に入れてしまいます。

Teleportは、ID認識型アクセスプロキシと内部認証局(CA)を導入することでこの問題を解決します。静的な認証情報に依存する代わりに、エンジニアはSSO、GitHub、またはOktaを通じて認証を行います。認証後、Teleportは8〜12時間だけ有効な暗号化X.509証明書およびSSH証明書を発行します。その有効期間が終了すると認証情報は自動的に失効するため、エンドポイント上に永続的な鍵が残ることは一切ありません。

インストール:Teleport ProxyおよびAuthサーバーのセットアップ

ここでは、2 vCPUと4 GBのRAMを搭載したUbuntu 22.04 LTSホスト上にTeleport Community Editionをデプロイします。この単一ホストで、証明書を発行するAuth Serviceと、受信するHTTPSおよびSSHトラフィックをルーティングするProxy Serviceの両方を担います。

まず、公式のGravitationalリポジトリを追加し、Teleportパッケージを取得します:

# Teleportの公開鍵をダウンロードしてインストール
sudo curl https://apt.releases.teleport.dev/gpg \
  -o /usr/share/keyrings/teleport-archive-keyring.asc

# 安定版v15リポジトリを追加
source /etc/os-release
echo "deb [signed-by=/usr/share/keyrings/teleport-archive-keyring.asc] \
  https://apt.releases.teleport.dev/${ID?} ${VERSION_CODENAME?} stable/v15" \
  | sudo tee /etc/apt/sources.list.d/teleport.list > /dev/null

# パッケージリストを更新してteleportをインストール
sudo apt-get update
sudo apt-get install -y teleport

次にベースとなる設定ファイルを生成します。Teleportには、既存のTLS証明書を使用してプロキシおよび認証エンジンを関連付けるCLIヘルパーが用意されています:

sudo teleport configure \
  --cluster-name=teleport.example.com \
  --public-addr=teleport.example.com:443 \
  --cert-file=/var/lib/teleport/fullchain.pem \
  --key-file=/var/lib/teleport/privkey.pem \
  --output=file:///etc/teleport.yaml

既存の証明書がない場合は、ファイルフラグを--acme [email protected]に置き換えて、Let’s Encryptで自動的に検証を行うように設定できます。systemdサービスを有効化して起動します:

sudo systemctl enable --now teleport
sudo systemctl status teleport

続いて、rootおよびubuntuシステムアカウントへのアクセス権限を持つ最初の管理者ユーザーを作成します:

sudo tctl users add devops-admin \
  --roles=editor,access \
  --logins=root,ubuntu

ターミナルに1回限りの登録用URLが表示されます。ブラウザでそのリンクを開き、WebAuthnハードウェアキー(YubiKeyなど)を登録するか、認証アプリ(1PasswordやGoogle Authenticatorなど)を設定します。

設定:LinuxノードとKubernetesクラスターの接続

プロキシが起動したら、インフラを連携させることができます。Teleportはアウトバウンドのリバーストンネルを使用するため、対象サーバーのポート22をパブリックインターネットに公開する必要は一切ありません。

1. 外部SSHノードの参加

Teleport認証ホストから1時間有効な参加トークンを生成します:

sudo tctl tokens add --type=node --ttl=1h

生成されたトークンとCAピンハッシュを控えておきます。対象のワーカーノードで先ほどのapt手順を使ってTeleportパッケージをインストールし、以下の設定を/etc/teleport.yamlに保存します:

version: v3
teleport:
  nodename: worker-node-01
  auth_token: "生成した参加トークン"
  auth_servers:
    - "teleport.example.com:443"
auth_service:
  enabled: "no"
proxy_service:
  enabled: "no"
ssh_service:
  enabled: "yes"
  labels:
    environment: production
    tier: backend

サービスを起動します:sudo systemctl enable --now teleport。ノードは自動的にteleport.example.com:443へ向けてアウトバウンド接続を行います。これにより、インバウンドのSSHファイアウォールルールは今すぐ完全に塞ぐことができます。

2. Kubernetesクラスターの参加

Kubernetesクラスターの接続は、わずか数個のHelmコマンドで完了します。Teleportサーバーからクラスター参加トークンを取得します:

sudo tctl tokens add --type=kube --ttl=1h

対象クラスターへの管理者アクセス権を持つワークステーションに切り替え、teleport-kube-agentをインストールします:

helm repo add teleport https://charts.releases.teleport.dev
helm repo update

helm upgrade --install teleport-kube-agent teleport/teleport-kube-agent \
  --namespace teleport \
  --create-namespace \
  --set kubeClusterName="production-eks" \
  --set proxyAddr="teleport.example.com:443" \
  --set authToken="取得したKUBE参加トークン"

エージェントがTeleportへのアウトバウンドトンネルを確立します。エンジニアがプロキシ経由でリクエストを送信すると、Teleportは実行時に対象ユーザーのIDを対応するKubernetes RBACグループへ動的にマッピングします。

検証とモニタリング:アクセスのテストとセッションの監査

素のsshコマンドや静的な設定ファイルとは決別しましょう。エンジニアは統合されたtshクライアントを通じてすべてを操作するようになります。

クライアントCLIによる認証

コマンドラインからログインします:

tsh login --proxy=teleport.example.com:443 --user=devops-admin

パスワードとMFAの入力が求められます。認証に成功すると、Teleportはローカル環境に短命のSSH証明書と更新されたkubeconfigコンテキストを配置します。

SSHターゲットへのアクセス

メタデータラベルを使用してサーバーを検出し、シェルセッションを開始します:

# 本番環境(production)に登録されているすべてのノードを一覧表示
tsh ls environment=production

# 一時証明書を使用してSSHシェルを開く
tsh ssh ubuntu@worker-node-01

Kubernetesへのアクセス

利用可能なクラスターを確認し、コンテキストを本番環境に向けます:

# プロキシ配下の全クラスターを検出
tsh kube ls

# 対象クラスターへコンテキストを切り替え
tsh kube login production-eks

# 通常どおり標準のkubectlコマンドを実行
kubectl get nodes
kubectl get pods -n kube-system

クラウドプロバイダーのIAMキーやハードコードされたサービスアカウントのシークレットを共有する必要は一切ありませんでした。Teleportが個々のkubectl API呼び出しをその場で都度認証します。

監査とセッションリプレイ

TeleportはインタラクティブなSSHセッションを記録し、生のKubernetes API呼び出しをすべて追跡します。アクティブなセッションの確認や、記録されたターミナル出力の再生はシェルから直接実行できます:

# アクティブなSSHセッションを確認
tsh status

# 過去のターミナルセッションをフレーム単位でリプレイ
tsh play <セッションID>

実行されたすべてのコマンド、ファイル変更、Podに対する実行リクエストは、構造化JSONとして/var/lib/teleport/logに記録されます。深夜2時にセキュリティインシデントが発生した場合でも、スタック全体の全キーストロークが改ざん不能な監査ログとして残されているため、日々の開発業務のスピードを落とすことなく強固なゼロトラストコンプライアンスを実現できます。

Share: