Cloud Composer で GCS から SFTP サーバ にファイル転送してみた 〜鍵認証編〜

2022.12.18

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

本記事はGCP(Google Cloud Platform) Advent Calendar 2022 18日目の記事です。

こんにちは!エノカワです。

Cloud Composer は、Apache Airflow で構築されたフルマネージドのワークフローオーケストレーションサービスです。
Apache Airflow のオープンソース プロジェクトを基に構築されており、Python プログラミング言語を使用して動作します。

下記エントリでは、Cloud Composer で Cloud Storage にあるファイルをSFTPサーバに転送するワークロードを紹介しました。

前回はパスワード認証でしたが、今回は鍵認証で同様のワークロードを試してみたのでご紹介します。

なお、[SFTPサーバをたてる][Cloud Composer 環境を作成]の箇所は前回と同様となりますので、詳細については上記エントリを参照ください。

SFTPサーバをたてる

ファイル転送先のSFTPサーバをたてます。

前回と同様、test-sftp-serverという名前で、東京リージョン、最小のマシン構成を選択し、他はデフォルトのままで作成しました。

[SSH]リンクからインスタンスに接続し、sftp_userユーザーの追加とuploadフォルダの作成もしておきます。

転送ファイルをアップロード

SFTPサーバに転送するファイルを Cloud Storage にアップロードします。

今回はtest-gcs-sftpバケットにfile_key.txtをアップロードしました。

鍵認証の設定

SFTPサーバで鍵認証するための設定を行います。

SSH鍵ペアを生成

Cloud Shell からssh-keygenコマンドを使用して、SSH鍵ペアを生成します。

$ ssh-keygen -t rsa -m PEM -N "" -C "sftp_user@test-sftp-server" -f test_sftp
Generating public/private rsa key pair.
Your identification has been saved in test_sftp
Your public key has been saved in test_sftp.pub
The key fingerprint is:
SHA256:S3nJDUkM3TR6fY0V3OyzfJbaChifZ18C5Q0o2gZqLkM sftp_user@test-sftp-server
The key's randomart image is:
+---[RSA 3072]----+
|        .+.oo .o+|
|         .oo.+ ++|
|        . = o =.o|
|       . * * o =.|
|    E o S.* o o =|
|   . o . ++ .. +o|
|    o . .. + o+.o|
|     o      +..o.|
|             ... |
+----[SHA256]-----+

秘密鍵と公開鍵が作成されました。

$ ls
test_sftp  test_sftp.pub

公開鍵test_sftp.pubを開いて、内容をコピーします。

公開鍵を登録

test-sftp-serverインスタンスの編集画面に入り、[SSH 認証鍵]項目に先ほどコピーした公開鍵の内容を登録します。

これでSFTPサーバの準備が整いました。

Secret Manager に 秘密鍵を保存

Cloud Composer から SFTP サーバにアクセスする際に使用する秘密鍵を Secret Manager に保存します。

以下のコマンドで、シークレットを作成し、秘密鍵を保管するシークレットとバージョンを作成します。

gcloud secrets create sftp_user-key
gcloud secrets versions add sftp_user-key --data-file="./test_sftp"

作成したシークレットにアクセスするために、Compute Engine のデフォルトのサービスアカウントに Secret Manager のシークレット アクセサー (roles/secretmanager.secretAccessor)のロールを付与しておきます。

gcloud secrets add-iam-policy-binding sftp_user-key \
    --member="serviceAccount:{PROJECT_ID}-compute@developer.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"

※プロジェクトIDの箇所は{PROJECT_ID}に置き換えています。

この後に作成する Cloud Composer では Compute Engine のデフォルトのサービスアカウントを使用します。

Cloud Composer 環境を作成

DAGを動かす Cloud Composer 環境を作成します。

前回と同様、test-composerという名前で、東京リージョン、最新のイメージバージョンを選択し、サービスアカウントなど他はでデフォルトのままで作成しました。

今回もgcs_to_sftpオペレータを使用しますので、apache-airflow-providers-sftpパッケージもインストールしておきまます。

DAG を作成

Cloud Composer 環境で実行する DAGを作成します。

以下の記事を参考にさせていただきました!

転送元にはtest-gcs-sftpバケットとアップロードしたfile_key.txtファイル、転送先にはtest-sftp-serverインスタンスに作成したuploadフォルダを指定しました。

GCSToSFTPOperatorのSFTPサーバへの接続IDsftp_conn_idには Secret Manager から取得した秘密鍵を設定した接続IDgcs_sftpを指定しています。

copy_file_from_gcs_to_sftp_key.py

import json
import os
from datetime import datetime
from google.cloud import secretmanager_v1beta1
from airflow import DAG
from airflow.models import Connection
from airflow.providers.google.cloud.transfers.gcs_to_sftp import GCSToSFTPOperator

# Secret Managerから秘密鍵を取得
client = secretmanager_v1beta1.SecretManagerServiceClient()
name = client.secret_version_path("{PROJECT_ID}", "sftp_user-key", "latest")
response = client.access_secret_version(name)
private_key = response.payload.data.decode("UTF-8")

# Airflow接続を作成
extra_secret = {
    "private_key": private_key,
}
conn = Connection(
    conn_id="gcs_sftp",
    conn_type="sftp",
    host="test-sftp-server",
    login="sftp_user",
    port=22,
    extra=json.dumps(extra_secret),
)
os.environ["AIRFLOW_CONN_GCS_SFTP"] = conn.get_uri()


with DAG(
    dag_id="example_gcs_to_sftp_key",
    start_date=datetime.now(),
    schedule_interval=None,
) as dag:

    copy_file_from_gcs_to_sftp = GCSToSFTPOperator(
        task_id="file-copy-gsc-to-sftp_key",
        sftp_conn_id="gcs_sftp",
        source_bucket="test-gcs-sftp",
        source_object="file_key.txt",
        destination_path="/home/sftp/upload/",
    )

※プロジェクトIDの箇所は{PROJECT_ID}に置き換えています。

DAGフォルダにファイルをアップロードしてDAGをデプロイします。

DAG を実行

デプロイしたDAGを実行してみましょう。

前回と同様、DAG詳細画面右上の[再生マーク]ボタンからTrigger DAGをクリックして、手動でDAGをトリガーします。

DAGが実行され、file-copy-gsc-to-sftp_keyタスクが緑色のsuccessでマークされました。

転送ファイルを確認

SFTPサーバにファイルが転送されているか確認してみましょう。

test-sftp-serverインスタンスに接続して、uploadフォルダ配下をチェックします。

file_key.txtファイルが居てました。
ファイル転送成功です!

まとめ

以上、Cloud Composer で GCS から 鍵認証で SFTP サーバ にファイル転送してみました。

前回のパスワード認証と同じく、gcs_to_sftpオペレータを使用するだけというシンプルなDAGですが、今回は鍵認証のために秘密鍵へのアクセスが必要です。
秘密鍵 の管理を Secret Manager で行い、DAGファイル内で SFTPサーバへの接続ID 組み立てるというのが今回のポイントでした。

今回は Secret Manager API を直接使用しましたが、Secret Manager をバックエンドに構成して変数としてシークレットにアクセスする方法もありますので、次回はこちらを紹介したいと思います!

参考