ACM: describe_certificate() should return a DomainValidationOption for each SAN (#7144)

This commit is contained in:
Bert Blommers 2023-12-19 22:04:21 -01:00 committed by GitHub
parent 34a0c20d03
commit 0bbe1f1717
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 126 additions and 16 deletions

View File

@ -82,6 +82,10 @@ jobs:
needs: lint
uses: ./.github/workflows/tests_sdk_ruby.yml
terraformexamplestest:
needs: lint
uses: ./.github/workflows/tests_terraform_examples.yml
test:
needs: [lint]
if: "!contains(github.event.pull_request.labels.*.name, 'java')"

View File

@ -0,0 +1,33 @@
# Small, self contained Terraform examples
# Scripts should be placed in:
# other_langs/terraform/service
name: Terraform Examples
on: [workflow_call]
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
service: ["acm"]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python 3.8
uses: actions/setup-python@v5
with:
python-version: "3.8"
- name: Start MotoServer
run: |
pip install build
python -m build
docker run --rm -t --name motoserver -e TEST_SERVER_MODE=true -e AWS_SECRET_ACCESS_KEY=server_secret -e AWS_ACCESS_KEY_ID=server_key -v `pwd`:/moto -p 5000:5000 -v /var/run/docker.sock:/var/run/docker.sock python:3.10-slim /moto/scripts/ci_moto_server.sh &
python scripts/ci_wait_for_server.py
- name: Run tests
run: |
mkdir ~/.aws && touch ~/.aws/credentials && echo -e "[default]\naws_access_key_id = test\naws_secret_access_key = test" > ~/.aws/credentials
cd other_langs/terraform/${{ matrix.service }} && terraform init && terraform apply --auto-approve

2
.gitignore vendored
View File

@ -37,3 +37,5 @@ other_langs/tests_java/target
other_langs/tests_dotnet/ExampleTestProject/bin
other_langs/tests_dotnet/ExampleTestProject/obj
other_langs/tests_ruby/Gemfile.lock
other_langs/terraform/*/.terraform*
other_langs/terraform/*/terraform*

View File

@ -337,25 +337,32 @@ class CertBundle(BaseModel):
"ExtendedKeyUsages": [],
"RenewalEligibility": "INELIGIBLE",
"Options": {"CertificateTransparencyLoggingPreference": "ENABLED"},
"DomainValidationOptions": [{"DomainName": self.common_name}],
}
}
domain_names = set(sans + [self.common_name])
validation_options = []
if self.status == "PENDING_VALIDATION":
result["Certificate"]["DomainValidationOptions"][0][
"ValidationDomain"
] = self.common_name
result["Certificate"]["DomainValidationOptions"][0][
"ValidationStatus"
] = self.status
result["Certificate"]["DomainValidationOptions"][0]["ResourceRecord"] = {
"Name": f"_d930b28be6c5927595552b219965053e.{self.common_name}.",
"Type": "CNAME",
"Value": "_c9edd76ee4a0e2a74388032f3861cc50.ykybfrwcxw.acm-validations.aws.",
}
result["Certificate"]["DomainValidationOptions"][0][
"ValidationMethod"
] = "DNS"
for san in domain_names:
resource_record = {
"Name": f"_d930b28be6c5927595552b219965053e.{san}.",
"Type": "CNAME",
"Value": "_c9edd76ee4a0e2a74388032f3861cc50.ykybfrwcxw.acm-validations.aws.",
}
validation_options.append(
{
"DomainName": san,
"ValidationDomain": san,
"ValidationStatus": self.status,
"ValidationMethod": "DNS",
"ResourceRecord": resource_record,
}
)
else:
validation_options = [{"DomainName": name} for name in domain_names]
result["Certificate"]["DomainValidationOptions"] = validation_options
if self.type == "IMPORTED":
result["Certificate"]["ImportedAt"] = datetime_to_epoch(self.created_at)
else:

View File

@ -0,0 +1,42 @@
locals {
domain_name = "test.co"
}
resource "aws_route53_zone" "test" {
name = local.domain_name
}
resource "aws_acm_certificate" "certificate" {
domain_name = local.domain_name
validation_method = "DNS"
subject_alternative_names = ["*.${local.domain_name}"]
lifecycle {
create_before_destroy = true
}
}
resource "aws_route53_record" "certificate_validation" {
for_each = {
for dvo in aws_acm_certificate.certificate.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = aws_route53_zone.test.zone_id
}
resource "aws_acm_certificate_validation" "validation" {
certificate_arn = aws_acm_certificate.certificate.arn
validation_record_fqdns = [
for record in aws_route53_record.certificate_validation : record.fqdn
]
}

View File

@ -0,0 +1,15 @@
provider "aws" {
region = "us-east-1"
s3_use_path_style = true
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
endpoints {
acm = "http://localhost:5000"
route53 = "http://localhost:5000"
}
access_key = "my-access-key"
secret_key = "my-secret-key"
}

View File

@ -385,7 +385,7 @@ def test_request_certificate():
@mock_acm
def test_request_certificate_with_tags():
def test_request_certificate_with_optional_arguments():
client = boto3.client("acm", region_name="eu-central-1")
token = str(uuid.uuid4())
@ -402,6 +402,13 @@ def test_request_certificate_with_tags():
assert "CertificateArn" in resp
arn_1 = resp["CertificateArn"]
cert = client.describe_certificate(CertificateArn=arn_1)["Certificate"]
assert len(cert["SubjectAlternativeNames"]) == 3
assert len(cert["DomainValidationOptions"]) == 3
assert {option["DomainName"] for option in cert["DomainValidationOptions"]} == set(
cert["SubjectAlternativeNames"]
)
resp = client.list_tags_for_certificate(CertificateArn=arn_1)
tags = {item["Key"]: item.get("Value", "__NONE__") for item in resp["Tags"]}
assert len(tags) == 2