2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

external-dns: TXTレコードの暗号化でDNS管理情報をセキュアに保つ

Posted at

前回の記事では、external-dnsを使ってKubernetesリソースからAWS Route53のDNSレコードを自動生成する基本的な方法を紹介しました。その中で、external-dnsが管理に使用するTXTレコードが公開されてしまう点について触れましたが、本記事ではその解決策として、TXTレコードの暗号化機能の実装方法を詳しく解説します。

TXTレコードとRegistryについて

external-dnsは、DNSレコードの管理情報をRegistryと呼ばれる場所に保存します。このRegistryには、TXTレコード以外にもDynamoDBやAWS Service Discoveryなどを使用することができます。

TXT Registryを選択する利点は、これ自身がDNSのプロトコルにしか依存していないおかげで、クラウドベンダー固有のサービスを避けられることです。これによりベンダーロックインを回避しつつ、管理情報を保持することができます。ただし、TXTレコードはパブリックに公開されるため、そのままでは管理情報が外部から見えてしまいます。そこで、TXTレコードの暗号化機能を使用することで、この問題を解決できます。

前提条件

  • Kubernetesクラスターがセットアップされていること
  • 必要なコマンドツールがインストールされていること
    • kubectl
    • helm
    • aws
    • dig
  • AWSアカウントのアクセスキーとシークレットキー

セットアップ手順

1. AWS Route53 Hosted Zoneの作成

まず、AWSの認証情報を環境変数に設定します:

export AWS_ACCESS_KEY_ID=AKIAXXXXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

認証情報が正しく設定されているか確認します:

aws sts get-caller-identity

AWS Route53でHosted Zoneを作成します:

aws route53 create-hosted-zone --name example-tutorial.com --caller-reference external-dns-tutorial-$(date +%s)

Note: caller-referenceは各作成試行で一意である必要があります。ここではタイムスタンプを使用して一意性を確保しています。

2. external-dnsのインストール(TXTレコード暗号化有効)

Bitnamiが提供するHelmチャートを使用します。このチャートは、kubernetes-sigsが提供するものよりもオプションが豊富で、AWS Route53の設定が容易です:

helm install external-dns \
  --set provider=aws \
  --set aws.zoneType=public \
  --set aws.credentials.accessKey="$AWS_ACCESS_KEY_ID" \
  --set aws.credentials.secretKey="$AWS_SECRET_ACCESS_KEY" \
  --set txtOwnerId=example-owner-id-123 \
  --set "domainFilters[0]=example-tutorial.com" \
  --set policy=sync \
  --set "sources[0]=crd" \
  --set crd.create=true \
  --set crd.apiversion=externaldns.k8s.io/v1alpha1 \
  --set crd.kind=DNSEndpoint \
  --set txtEncrypt.enabled=true \
  --set txtEncrypt.aesKey="" \
  oci://registry-1.docker.io/bitnamicharts/external-dns

インストールオプションの説明

オプション 説明
provider=aws AWS Route53を使用することを指定
aws.zoneType=public パブリックゾーンを使用することを指定
aws.credentials.accessKey AWSのアクセスキー
aws.credentials.secretKey AWSのシークレットキー
txtOwnerId TXTレコードのオーナーID(任意の値を指定可能)
domainFilters[0] 監視対象のドメイン
policy=sync DNSレコード同期ポリシー
sources[0]=crd CRDを使用することを指定
crd.create=true CRDの作成を有効化
crd.apiversion CRDのAPIバージョン
crd.kind CRDの種類
txtEncrypt.enabled=true TXTレコードの暗号化を有効化
txtEncrypt.aesKey 暗号化用のAESキー(空文字列の場合は自動生成)

インストール後、external-dnsのログを確認して正常に起動していることを確認します:

kubectl logs -l app.kubernetes.io/name=external-dns -f

次のようなログが表示されれば、暗号化機能が有効な状態で正常に起動しています:

time="2024-11-06T07:03:47Z" level=info msg="config: {...TXTEncryptEnabled:true...}"
time="2024-11-06T07:03:47Z" level=info msg="Instantiating new Kubernetes client"
time="2024-11-06T07:03:47Z" level=info msg="Using inCluster-config based on serviceaccount-token"
time="2024-11-06T07:03:47Z" level=info msg="Created Kubernetes client https://10.43.0.1:443"
time="2024-11-06T07:03:49Z" level=info msg="Applying provider record filter for domains: [example-tutorial.com. .example-tutorial.com.]"

AES暗号化キーが生成され、Secretに保存されていることを確認します:

kubectl get secret external-dns -o yaml

Secretの中に txt_aes_encryption_key フィールドが存在していることを確認できます:

apiVersion: v1
kind: Secret
data:
  txt_aes_encryption_key: Q2NCSUF6c2I1N215SGY4RWZtWmZvWm1keUl2SHBsTDY=  # Base64エンコードされたAESキー
# ... 他のフィールドは省略

3. DNSレコードの作成

external-dnsがDNSレコードを作成することを確認します。今回は実体リソースが不要なCRDのDNSEndpointを使用します:

# test.example-tutorial.com.yaml
apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
  name: test.example-tutorial.com
spec:
  endpoints:
  - dnsName: test.example-tutorial.com
    recordTTL: 180
    recordType: A
    targets:
    - 127.0.0.1

このマニフェストを適用します:

kubectl apply -f test.example-tutorial.com.yaml

しばらくすると、external-dnsがDNSレコードを作成します。ログを確認します:

time="2024-11-06T07:12:52Z" level=info msg="Desired change: CREATE a-test.example-tutorial.com TXT" profile=default zoneID=/hostedzone/Z00418233KGBJI8AZJFPR zoneName=example-tutorial.com.
time="2024-11-06T07:12:52Z" level=info msg="Desired change: CREATE test.example-tutorial.com A" profile=default zoneID=/hostedzone/Z00418233KGBJI8AZJFPR zoneName=example-tutorial.com.
time="2024-11-06T07:12:52Z" level=info msg="2 record(s) were successfully updated" profile=default zoneID=/hostedzone/Z00418233KGBJI8AZJFPR zoneName=example-tutorial.com.

AWS CLIを使用してDNSレコードが作成されたことを確認します:

aws route53 list-resource-record-sets --hosted-zone-id Z00418233KGBJI8AZJFPR

AレコードとTXTレコード(暗号化済み)の両方が確認できます:

{
    "ResourceRecordSets": [
        {
            "Name": "test.example-tutorial.com.",
            "Type": "A",
            "TTL": 180,
            "ResourceRecords": [
                {
                    "Value": "127.0.0.1"
                }
            ]
        },
        {
            "Name": "a-test.example-tutorial.com.",
            "Type": "TXT",
            "TTL": 300,
            "ResourceRecords": [
                {
                    "Value": "\"YwPTDxmRgtKjryuSqYrqA35DoRkFw94ZxoojvZ9goHiyXbd8zYS8wBqS7t3ZtZoqREqDDaLtLcB0wbzTpw9n1+HxgGrJc795b4ISnJXRI03+sJ+DgN71dU7hCCyoPx25w/jYbOX3/zP DP59BmZaAly/OLmCEcDTW7dl697qdj4lsNHBrr+6Z1lAFKHAKfX3pM9w6RFGmpGl4WULtAA==\""
                }
            ]
        }
    ]
}

TXT暗号化を有効にしたことで、TXTレコードの内容はAES暗号化されています。このTXTレコードには従来と同じ管理情報(heritage、owner、resourceなど)が含まれていますが、暗号化されているため外部からの参照はできません。

クリーンアップ

1. DNSレコードの削除

CRDリソースを削除します:

kubectl delete -f test.example-tutorial.com.yaml

external-dnsのログで削除が完了したことを確認できます:

time="2024-11-06T05:48:24Z" level=info msg="Desired change:  DELETE  a-test.example-tutorial.com TXT" profile=default zoneID=/hostedzone/Z08033563HFN15GSXJ766 zoneName=example-tutorial.com.
time="2024-11-06T05:48:24Z" level=info msg="Desired change:  DELETE  test.example-tutorial.com A" profile=default zoneID=/hostedzone/Z08033563HFN15GSXJ766 zoneName=example-tutorial.com.
time="2024-11-06T05:48:24Z" level=info msg="Desired change:  DELETE  test.example-tutorial.com TXT" profile=default zoneID=/hostedzone/Z08033563HFN15GSXJ766 zoneName=example-tutorial.com.
time="2024-11-06T05:48:24Z" level=info msg="3 record(s) were successfully updated" profile=default zoneID=/hostedzone/Z08033563HFN15GSXJ766 zoneName=example-tutorial.com.

2. external-dnsの削除

Helmリリースを削除します:

helm uninstall external-dns

3. Hosted Zoneの削除

Hosted Zoneの一覧を確認し:

aws route53 list-hosted-zones

確認したIDを使用してHosted Zoneを削除します:

aws route53 delete-hosted-zone --id Z00418233KGBJI8AZJFPR

おわりに

本記事では、external-dnsのTXTレコード暗号化機能を使用して、DNS管理情報をセキュアに保つ方法を解説しました。TXTレコードは、クラウドベンダー固有のサービスを避けつつ管理情報を保持できる便利なRegistryですが、そのままでは情報が公開されてしまいます。暗号化機能を使用することで、この問題を解決しつつTXT Registryのメリットを活かすことができます。

前回の記事と合わせて参照いただくことで、より理解が深まるかと思います。ぜひ実際に試してみてください!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?