Cloudflare Access と Cloudflare Tunnel を使い、MongoDB デプロイへの接続を保護する Zero Trust ルールを構築できます。Cloudflare Tunnel には、デプロイのそばとクライアント側の両方で動く軽量デーモン cloudflared が必要です。
このチュートリアルでは、cloudflared を動かすクライアントが、Kubernetes 上の MongoDB デプロイへ SSH で接続します。デプロイ例は、Compass ↗ を MongoDB インスタンスに接続する構成です。MongoDB の Kubernetes デプロイは、MongoDB データベースサービスと、ジャンプホストのように動く ingress サービスとしての cloudflared の両方を実行します。
このチュートリアルで扱う内容:
- MongoDB デプロイを保護する Cloudflare Access ルールを作成する
- デプロイ用の StatefulSet とサービス定義を設定する
- Cloudflare のエッジへの Cloudflare Tunnel 接続を設定する
- クライアント用の SSH 設定ファイルを作成する
所要時間:
50 分
Cloudflare Access で、MongoDB デプロイへの接続者を制御するルールを作れます。Cloudflare Access のルールはホスト名を中心に組み立てます。このデプロイは SSH でアクセスしますが、Cloudflare 上ではホスト名として表されます。たとえば、Cloudflare アカウントに Web サイト app.com がある場合、mongodb.app.com を保護するルールを作れます。
-
Cloudflare ダッシュボード ↗ で、Zero Trust > Access controls > Applications を開きます。
-
Create new application を選択します。
-
Self-hosted and private を選択します。
-
Add public hostname を選択し、ユーザーがデプロイに接続するサブドメイン(例:
mongodb.app.com)を入力します。 -
デプロイに到達できる人を制御する Access ポリシー を追加します。組織の全員を許可するポリシーも、アイデンティティプロバイダーのグループ、多要素認証の方式、国 などのシグナルに基づく、より細かいポリシーも作れます。
-
残りの セルフホストアプリケーション作成手順 に従い、アプリケーションを公開します。
SSH でアクセスできるようにするには、Kubernetes デプロイが MongoDB スタンドアロンサービスと SSH プロキシサービスの両方を管理する必要があります。次の構成は、ポート 27017 で利用できるデータベースサービス 1 レプリカと、ポート 22 で利用できる SSH プロキシをデプロイします。
StatefulSet の構成
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongodb-standalone
namespace: mongodb
spec:
serviceName: database
replicas: 1
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
selector: mongodb-standalone
spec:
containers:
- name: mongodb-standalone
image: mongo
command: ["mongod"]
args: ["--config=/config/mongod.conf"]
ports:
- containerPort: 27017
protocol: TCP
name: mongod
volumeMounts:
- name: mongodb-conf
mountPath: /config
readOnly: true
- name: mongodb-data
mountPath: /data/db
- name: tls
mountPath: /etc/tls
- name: mongodb-socket
mountPath: /socket
- name: ssh-proxy
image: ubuntu:20.04
command: ["/scripts/entrypoint.sh"]
ports:
- containerPort: 22
protocol: TCP
name: ssh-port
volumeMounts:
- name: mongodb-socket
mountPath: /socket
- name: scripts
mountPath: /scripts
readOnly: true
- name: ssh-authorized-keys
mountPath: /config/ssh
readOnly: true
resources:
requests:
cpu: 20m
memory: 32Mi
volumes:
- name: mongodb-socket
emptyDir: {}
- name: mongodb-conf
configMap:
name: mongodb-standalone
items:
- key: mongod.conf
path: mongod.conf
- name: tls
secret:
secretName: tls
- name: mongodb-data
persistentVolumeClaim:
claimName: mongodb-standalone
- name: scripts
configMap:
name: scripts
items:
- key: entrypoint.sh
path: entrypoint.sh
mode: 0744
- name: ssh-authorized-keys
configMap:
name: ssh-proxy-config
items:
- key: authorized_keys
path: authorized_keys
mode: 0400対応するサービス定義でも、コンテナ(この場合はデータベースサービスと SSH プロキシサービス)のポートとターゲットポートを指定する必要があります。
サービスの定義
apiVersion: v1
kind: Service
metadata:
name: database
namespace: mongodb
labels:
app: database
spec:
clusterIP: None
selector:
app: database
ports:
- protocol: TCP
port: 27017
targetPort: 27017
---
apiVersion: v1
kind: Service
metadata:
name: ssh-proxy
namespace: mongodb
labels:
app: database
spec:
selector:
app: database
ports:
- protocol: TCP
port: 22
targetPort: 22MongoDB ポッドと SSH ジャンプホストは、emptyDir ボリューム上の Unix ソケットを共有します。ジャンプホストが実行する entrypoint.sh(以下は例)は、OpenSSH サーバーを起動します。
#!/bin/sh
export TZ=America/Chicago
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
apt-get update -y && apt-get install -y openssh-server
mkdir /root/.ssh
cp /config/ssh/authorized_keys /root/.ssh/authorized_keys
chmod 400 /root/.ssh/authorized_keys
service ssh start
while true;
do sleep 30;
done;次に、cloudflared を使い、Cloudflare Tunnel で Cloudflare のエッジに接続できます。まず Cloudflare Tunnel デーモン cloudflared を ダウンロードしてインストール します。
インストール後、次のコマンドを実行し、この cloudflared インスタンスを Cloudflare アカウントに認証します。
cloudflared loginこのコマンドはブラウザーを開き、Cloudflare アカウントでのログインを求めます。アカウントに追加済みの Web サイトを選びます。
サイトを選ぶと、Cloudflare はこの cloudflared インスタンスを認証する証明書ファイル cert.pem をダウンロードします。cert.pem は cloudflared インスタンスの認証に証明書を使い、DNS レコード変更などの操作を行うためのアカウント API キーも含みます。
これで、cloudflared を使い、Cloudflare アカウント内の Cloudflare Tunnel 接続を制御できます。
cloudflared を Cloudflare のエッジに接続する トンネルを作成 できます。トンネルの詳細は次の手順で設定します。
次のコマンドを実行してトンネルを作成します。mongodb は任意の名前に置き換えられます。このコマンドには cert.pem ファイルが必要です。
cloudflared tunnel create mongodb
Cloudflare はその名前でトンネルを作成し、そのトンネル用の ID と認証情報ファイルを生成します。
認証情報ファイルは cert.pem ファイルとは別です。cert.pem と異なり、認証情報ファイルは、今作成した Named Tunnel だけを認証するトークンで構成されます。JSON 形式で、Cloudflare アカウントの変更や追加のトンネル作成はできません。
トンネルの作成が終わったら、cert.pem ファイルを削除し、認証情報ファイルだけを残し、DNS レコードは Cloudflare ダッシュボードまたは API で直接管理し続けられます。2 つのファイルの役割の違いについては、用語一覧 を参照してください。
JSON ファイルは Kubernetes の Secret として保存します。
前の手順では、cloudflared で Cloudflare アカウント用の認証情報ファイルを生成しました。MongoDB の Kubernetes デプロイと並べてサービスとして動かす場合は、cloudflared の Docker イメージが必要です。Cloudflare は DockerHub で 公式イメージ ↗ を提供しています。
次の構成は、MongoDB および SSH プロキシサービスと並べて、ingress ポイントとして cloudflared を 1 レプリカで動かします。cloudflared は SSH プロキシサービスへトラフィックをプロキシします。cloudflared インスタンスは別ネームスペースの独自 Deployment として動き、ネットワークポリシーが許せば、Kubernetes ノード内の任意のサービスへ ingress できます。
cloudflared の構成
cloudflared の構成apiVersion: apps/v1
kind: Deployment
metadata:
name: dashboard-tunnel
namespace: argotunnel
labels:
app: dashboard-tunnel
spec:
replicas: 1
selector:
matchLabels:
app: dashboard-tunnel
template:
metadata:
labels:
app: dashboard-tunnel
spec:
containers:
- name: dashboard-tunnel
# Image from https://hub.docker.com/r/cloudflare/cloudflared
image: cloudflare/cloudflared:2020.11.11
command: ["cloudflared", "tunnel"]
args: ["--config", "/etc/tunnel/config.yaml", "run"]
ports:
- containerPort: 5000
livenessProbe:
tcpSocket:
port: 5000
initialDelaySeconds: 60
periodSeconds: 60
volumeMounts:
- name: dashboard-tunnel-config
mountPath: /etc/tunnel
- name: tunnel-credentials
mountPath: /etc/credentials
volumes:
- name: dashboard-tunnel-config
configMap:
name: dashboard-tunnel-config
- name: tunnel-credentials
secret:
secretName: tunnel-credentials
---
apiVersion: v1
kind: ConfigMap
metadata:
name: dashboard-tunnel-config
namespace: argotunnel
data:
config.yaml: |
tunnel: 9a00ef26-4997-4de2-83db-631efc74245c
credentials-file: /etc/credentials/k8s-dashboard.json
metrics: :5000
protocol: http2
no-autoupdate: true
ingress:
- hostname: mongodb.widgetcorp.tech
originRequest:
bastionMode: true
- service: http_status:404デプロイ後、クライアント側で cloudflared を動かし、MongoDB デプロイに接続できます。SSH 設定ファイルに次の行を追加し、例を自分のホスト名と詳細に置き換えます。--destination の値は、先ほど設定した SSH プロキシサービスの URL と一致させてください。
Host mongodb
ProxyCommand /usr/local/bin/cloudflared access ssh --hostname mongodb.widgetcorp.tech --destination ssh-proxy.mongodb.svc.cluster.local:22
LocalForward 27000 /socket/mongodb-27017.sock
User root
IdentityFile /Users/username/.ssh/id_rsaこれは一度だけの手順です。次回デプロイへ SSH 接続しようとすると、cloudflared がブラウザーを開き、認証を求めます。有効なセッションがあれば、認証後に接続されます。トンネルが確立すると、マシン上の localhost:27000 へのすべてのリクエストは、SSH プロキシコンテナ上の /socket/mongodb-27017.sock へ転送されます。
その後、MongoDB Compass を localhost:27000 に接続するよう設定できます。