dbtのドキュメントをホスティングするAWS環境をTerraformで構築
この記事では、dbtのドキュメントをホスティングするAWS環境をTerraformで構築する方法を紹介します。S3にアップロードされたdbtドキュメントをCloudFrontを経由して確認できるようにします。また、CloudFrontには、Lambda@Edgeを利用してBasic認証をかけます。
Terraformコード
Terraformのコードは次のGitHubレポジトリで確認することができます。
ディレクトリ構成
次のディレクトリ構成となっています。
.
├── backend.tf
├── cloudfront.tf
├── iam.tf
├── lambda.tf
├── lambda_edge
│ └── index.py
├── lambda_edge_archive
├── provider.tf
├── s3.tf
└── variables.tf
構築のステップ
次の順でdbt DocsをAWSにホスティングする環境を構築します。
- Lambda@Edgeの関数を記述
- Terraformでインフラを構築
Lambda@Edgeの関数を記述
次のようにBasic認証用のLambda@Edgeのコードをindex.py
に記述します。
"""
Lambda@Edge for authentication
"""
import base64
def authenticate(user, password):
return user == "admin" and password == "passW0rd"
def handler(event, context):
request = event["Records"][0]["cf"]["request"]
headers = request["headers"]
error_response = {
"status": "401",
"statusDescription": "Unauthorized",
"body": "Authentication Failed",
"headers": {
"www-authenticate": [
{
"key": "WWW-Authenticate",
"value": 'Basic realm="Basic Authentication"',
}
]
},
}
if "authorization" not in headers:
return error_response
try:
auth_values = headers["authorization"][0]["value"].split(" ")
auth = base64.b64decode(auth_values[1]).decode().split(":")
(user, password) = (auth[0], auth[1])
return request if authenticate(user, password) else error_response
except Exception:
return error_response
Terraformでインフラを構築
Terraformを使用してインフラの構築を行います。
ソースコードの記述
Terraformのコードを記述します。ソースコードは次のレポジトリを参照してください。
ここでは、ポイントとなる点のみを解説します。
マルチリージョン
provider.tf
にはAWSプロバイダーが記述されています。今回、Lambda@Edgeを使用するため、Lambda関数はバージニアリージョンにデプロイする必要があります。そのため、us-east-1
リージョンのプロバイダーを定義し、Lambdaの定義時に参照しています。
provider "aws" {
region = "ap-northeast-1"
default_tags {
tags = {
Env = "dev"
App = "my-app"
ManagedBy = "Terraform"
}
}
}
provider "aws" {
alias = "virginia"
region = "us-east-1"
default_tags {
tags = {
Env = "dev"
App = "my-app"
ManagedBy = "Terraform"
}
}
}
resource "aws_lambda_function" "cloudfront_auth" {
provider = aws.virginia
.
.
.
}
LambdaのZip化
lambda.tf
のarchive_file
というデータソースを使うと指定のディレクトリのZipファイルを生成することができます。
data "archive_file" "function_source" {
type = "zip"
source_dir = "lambda_edge"
output_path = "lambda_edge_archive/function.zip"
}
生成されるZipファイルをLambda定義時に参照しています。
resource "aws_lambda_function" "cloudfront_auth" {
.
.
.
filename = data.archive_file.function_source.output_path
source_code_hash = data.archive_file.function_source.output_base64sha256
}
Lambdaのバージョニング
CloudFrontではLambdaのバージョンを指定する必要があります。Lambdaのバージョンニングについては次の記事を参照ください。
Lambda定義時にpublish=true
とするとバージョニングが行われます。
resource "aws_lambda_function" "cloudfront_auth" {
.
.
.
publish = true
}
CloudFrontではバージョンを指定したLambdaが参照されています。
resource "aws_cloudfront_distribution" "main" {
.
.
.
lambda_function_association {
.
.
lambda_arn = aws_lambda_function.cloudfront_auth.qualified_arn
}
}
Terraform Apply
terraform apply
を実行して環境構築します。
dbtドキュメントをS3に格納
dbtのプロジェクトのディレクトリにて、次のコマンドでS3にdbtドキュメントをアップロードします。
$ dbt docs generate
$ aws s3 cp target/manifest.json s3://<s3 bucket name created by terraform>/
$ aws s3 cp target/run_results.json s3://<s3 bucket name created by terraform>/
$ aws s3 cp target/index.html s3://<s3 bucket name created by terraform>/
$ aws s3 cp target/catalog.json s3://<s3 bucket name created by terraform>/
ドキュメントの確認
CloudFrontのディストリビューションドメインにアクセスしてみると、Basic認証がかかっていることが確認できます。
認証後、ドキュメントを見ることができるようになります。
また、S3に直接アクセスすると、拒否されることも確認できます。