导入由Python脚本在Terraform上创建的DNS记录

问题描述 投票:0回答:1

我的 terraform 配置为 Web 应用程序设置了 AWS 基础设施,包括所需的常用服务。 terraform 设置完成后,Jenkins 运行一个 Python 脚本,更新 Porkbun 上的名称服务器以指向 AWS 名称服务器。此外,在 Terraform 设置过程中,还会生成 ACM 证书。 python 脚本将带有 ACM 证书给出的质询的 CNAME 记录添加到应用程序托管区域记录中。

问题是当我执行 terraform destroy 时,因为 Python 代码添加了 CNAME 记录,Terraform 无法销毁该区域,因为那里生成的条目不受 Terraform 管理。

我想了解我的方法是否错误,或者是否有适当的解决方案。我想“最短”的方法是将脚本所做的更改导入到 terraform 中?

当然,当我手动删除 CNAME 条目时,Terraform 能够销毁它创建的所有资源。理想情况下,我希望导入 terraform 函数能够在同一脚本中动态发生。

dns.tf配置如下:

resource "aws_route53_zone" "main" {
  name = var.domain_name
}

resource "aws_route53_record" "www" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "www.${var.domain_name}"
  type    = "A"
  ttl     = "300"
  records = [aws_instance.resume-app-ec2-instance.public_ip]
}

resource "aws_route53_record" "root" {
  zone_id = aws_route53_zone.main.zone_id
  name    = var.domain_name
  type    = "A"
  ttl     = "300"
  records = [aws_instance.resume-app-ec2-instance.public_ip]
}

这是我正在运行的自定义 Python 脚本,它动态获取 Terraform 为特定托管区域创建的名称服务器,并通过 API 更新 Porkbun 名称服务器。然后,它获取同样通过 Terraform 配置的 ACM 证书质询,并为域创建 CNAME 记录。

import requests
import json
import boto3
import time

print("Firing up domain changes...")
time.sleep(3)

# AWS Secret Manager details
secret_name = "aws-pork-dns-ns"
region_name = "us-east-1"

# Porkbun Domain Name
domain_name = "redacted :)"

# Initialize a Secrets Manager client
client = boto3.client('secretsmanager', region_name=region_name)

# Retrieve Porkbun API credentials from AWS Secret Manager
response = client.get_secret_value(SecretId=secret_name)
secret_dict = json.loads(response['SecretString'])
pork_api_key = secret_dict['pork_api_key']
pork_api_secret = secret_dict['pork_api_secret']

# Retrieve name servers from Route 53
route53_client = boto3.client('route53')
response = route53_client.list_hosted_zones_by_name(DNSName=domain_name)
hosted_zone_id = response['HostedZones'][0]['Id'].split('/')[-1]
response = route53_client.get_hosted_zone(Id=hosted_zone_id)
name_servers = response['DelegationSet']['NameServers']

# Construct the request body to update name servers according to the Porkbun API documentation
request_body = {
    "apikey": pork_api_key,
    "secretapikey": pork_api_secret,
    "ns": name_servers
}

# Update name servers on Porkbun
url = f"https://porkbun.com/api/json/v3/domain/updateNs/{domain_name}"
headers = {"Content-Type": "application/json"}
response = requests.post(url, headers=headers, json=request_body)

# Check the response for name server update
if response.status_code == 200:
    print("Name servers updated successfully.")
    print(response.json())
else:
    print("Failed to update name servers.")
    print("Status Code:", response.status_code)
    print("Response:", response.json())

# Wait for a few seconds for DNS propagation
print("Hold on, waiting for records to propagate before continuing...")
time.sleep(30)

# Get ACM certificate ARN
acm_client = boto3.client('acm')
response = acm_client.list_certificates()
certificate_arn = None
for certificate in response['CertificateSummaryList']:
    if certificate['DomainName'] == domain_name:
        certificate_arn = certificate['CertificateArn']
        break

if certificate_arn:
    # Get DNS validation options
    response = acm_client.describe_certificate(CertificateArn=certificate_arn)
    validation_options = response['Certificate']['DomainValidationOptions']
    for option in validation_options:
        if option['ValidationMethod'] == 'DNS':
            dns_record_name = option['ResourceRecord']['Name']
            dns_record_value = option['ResourceRecord']['Value']

            # Create CNAME record in Route 53
            response = route53_client.change_resource_record_sets(
                HostedZoneId=hosted_zone_id,
                ChangeBatch={
                    'Changes': [{
                        'Action': 'UPSERT',
                        'ResourceRecordSet': {
                            'Name': dns_record_name,
                            'Type': 'CNAME',
                            'TTL': 300,
                            'ResourceRecords': [{'Value': dns_record_value}]
                        }
                    }]
                }
            )

            print("CNAME record created successfully.")
            print("DNS Record Name:", dns_record_name)
            print("DNS Record Value:", dns_record_value)
            break
else:
    print("ACM certificate not found for domain:", domain_name)

acm.tf如下:

resource "aws_acm_certificate" "resume-app-cert" {
  domain_name       = var.domain_name
  validation_method = "DNS"

  tags = {
    Name = "resume-app-ssl-cert"
  }
}

amazon-web-services terraform amazon-route53
1个回答
0
投票

这可能不是最佳实践,正如其他人指出的那样,最佳实践是通过 terraform 管理一切

但是如果你只是需要一个简单的出路。这应该可以作为解决方案

force_destroy = true
添加到您的 Hosted_zone

resource "aws_route53_zone" "private" {
  name          = "example.com"
  force_destroy = true
}
© www.soinside.com 2019 - 2024. All rights reserved.