コンテンツにスキップ

MongoDB SSH

Last reviewed: over 3 years ago

Cloudflare AccessとCloudflare Tunnelを使用してMongoDBデプロイメントへの接続を保護するためのZero Trustルールを構築できます。Cloudflare Tunnelは、デプロイメントとクライアント側で動作する軽量デーモンcloudflaredを必要とします。

このチュートリアルでは、cloudflaredを実行しているクライアントがKubernetes上で実行されているMongoDBデプロイメントにSSHで接続します。デプロイメントの例は、CompassをMongoDBインスタンスに接続するように構成されています。MongoDB Kubernetesデプロイメントは、MongoDBデータベースサービスと、ジャンプホストのように動作するcloudflaredをイングレスサービスとして実行します。

このチュートリアルでは、以下の内容をカバーします:

  • MongoDBデプロイメントを保護するためのCloudflare Accessルールを作成する
  • デプロイメントのためのStatefulSetとサービス定義を構成する
  • CloudflareのエッジへのCloudflare Tunnel接続を構成する
  • クライアントのためのSSH構成ファイルを作成する

完了までの時間:

50分


Cloudflare Accessの構成

Cloudflare AccessでMongoDBデプロイメントに接続できるユーザーを制御するルールを構築できます。Cloudflare Accessルールはホスト名を中心に構築されます。このデプロイメントはSSH経由でアクセス可能ですが、リソースはCloudflareではホスト名として表されます。たとえば、Cloudflareアカウントにapp.comというウェブサイトがある場合、mongodb.app.comを保護するためのルールを構築できます。

  1. これらの手順に従って、アカウントにCloudflare Accessを設定します。

  2. Zero Trustに移動し、Access > Applicationsを選択します。

  3. Add an applicationを選択し、Self-hostedを選択します。

  4. ユーザーがデプロイメントに接続するサブドメインのアプリケーションを作成します。Nextを選択します。

    MongoDB screen that shows how to add an application

  5. デプロイメントに到達できるユーザーを決定するルールを構築します。組織内の誰でも接続できるルールを構築することも、アイデンティティプロバイダーグループ、多要素認証方法などのシグナルに基づいてより詳細なルールを構築することもできます。

    MongoDB screen that shows how to configure a rule

  6. Nextを再度選択し、アプリケーションを追加します。

Kubernetesデプロイメントの構成

SSH経由でアクセス可能にするために、KubernetesデプロイメントはMongoDBスタンドアロンサービスとSSHプロキシサービスの両方を管理する必要があります。以下の構成では、ポート27017で利用可能なデータベースサービスの1レプリカと、ポート22で利用可能なSSHプロキシをデプロイします。

StatefulSet Configuration

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プロキシサービス)。

Service Definition

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: 22

MongoDBポッドとSSHジャンプホストは、空のディレクトリボリュームを介して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;

Cloudflare Tunnelの構成

次に、cloudflaredを使用してCloudflareのエッジに接続するCloudflare Tunnelを構成できます。まず、Cloudflare Tunnelデーモンcloudflaredをダウンロードしてインストールします。

インストールが完了したら、次のコマンドを実行して、cloudflaredのインスタンスをCloudflareアカウントに認証します。

Terminal window
cloudflared login

このコマンドはブラウザウィンドウを起動し、Cloudflareアカウントでログインするように促します。アカウントに追加したウェブサイトを選択します。

アカウント内のサイトの1つを選択すると、Cloudflareはこのcloudflaredインスタンスを認証するための証明書ファイルcert.pemをダウンロードします。cert.pemファイルは、cloudflaredのインスタンスを認証するための証明書を使用し、DNSレコードの変更などのアクションを実行するためのAPIキーを含みます。

これで、cloudflaredを使用してCloudflareアカウント内のCloudflare Tunnel接続を制御できます。

Download Certificate

トンネルの作成

これで、cloudflaredをCloudflareのエッジに接続するトンネルを作成できます。次のステップでそのトンネルの詳細を構成します。

次のコマンドを実行してトンネルを作成します。mongodbを任意の名前に置き換えることができます。このコマンドはcert.pemファイルを必要とします。

cloudflared tunnel create mongodb

Cloudflareはその名前でトンネルを作成し、そのトンネルのIDと認証情報ファイルを生成します。

New Tunnel

cert.pemファイルの削除

認証情報ファイルはcert.pemファイルとは別です。cert.pemファイルとは異なり、認証情報ファイルは、作成した名前付きトンネルのみを認証するトークンで構成されています。JSON形式のファイルは、Cloudflareアカウントに変更を加えたり、追加のトンネルを作成したりすることはできません。

トンネルの作成が完了したら、cert.pemファイルを削除し、認証情報ファイルのみを残し、CloudflareダッシュボードまたはAPIでDNSレコードを直接管理し続けることができます。2つのファイルの異なる機能に関する追加情報については、有用な用語のリストを参照してください。

JSONファイルをKubernetesシークレットとして保存します。

Cloudflare Tunnelの構成

前のステップでは、cloudflaredを使用してCloudflareアカウントの認証情報ファイルを生成しました。MongoDB Kubernetesデプロイメントと一緒にサービスとして実行する場合、cloudflaredのDockerイメージを使用する必要があります。Cloudflareは公式イメージを提供していますDockerHubで。

以下の構成では、MongoDBおよびSSHプロキシサービスとともに、cloudflaredの単一レプリカをイングレスポイントとして実行します。cloudflaredはSSHプロキシサービスにトラフィックをプロキシします。cloudflaredインスタンスは、異なる名前空間で独自のデプロイメントとして実行され、ネットワークポリシーが許可されている場合、Kubernetesノード内の任意のサービスにイングレスします。

cloudflared Configuration

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と一致する必要があります。

Terminal window
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に接続するように設定できます。