Skip to content

Commit f12b93f

Browse files
committed
changes from PR feedback: refactored to build config file rather than mount one in
1 parent 52b8f0f commit f12b93f

File tree

3 files changed

+47
-48
lines changed

3 files changed

+47
-48
lines changed

custom-domain/dstack-ingress/DNS_PROVIDERS.md

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ NAMECHEAP_CLIENT_IP=your-client-ip
7878

7979
```bash
8080
DNS_PROVIDER=route53
81-
AWS_PROFILE=your-injected-aws-profile
81+
AWS_ACCESS_KEY_ID=service-account-key-that-can-assume-role
82+
AWS_SECRET_ACCESS_KEY=service-account-secret-that-can-assume-role
83+
AWS_ROLE_ARN=role-that-can-mod-route53
84+
AWS_REGION=your-closest-region
8285
```
8386

8487
**Required Permissions:**
@@ -103,7 +106,7 @@ PolicyDocument:
103106
**Important Notes for Route53:**
104107
- The certbot plugin uses the format `certbot-dns-route53` package
105108
- CAA will merge AWS & Let's Encrypt CA domains to existing records if they exist
106-
- It is recommended that the AWS service account can only assume the limited role. See cloudformation example.
109+
- It is essential that the AWS service account used can only assume the limited role. See cloudformation example.
107110

108111
## Docker Compose Examples
109112

@@ -171,37 +174,20 @@ services:
171174
- cert-data:/etc/letsencrypt
172175
ports:
173176
- 443:443
174-
configs:
175-
- source: aws_config
176-
target: /root/.aws/config
177-
mode: 0600
178-
- source: aws_credentials
179-
target: /root/.aws/credentials
180-
mode: 0600
181177
environment:
182178
DNS_PROVIDER: route53
183179
DOMAIN: app.example.com
184180
GATEWAY_DOMAIN: _.${DSTACK_GATEWAY_DOMAIN}
185181
182+
AWS_REGION: ${AWS_REGION}
183+
AWS_ROLE_ARN: ${AWS_ROLE_ARN}
184+
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
185+
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
186+
186187
CERTBOT_EMAIL: ${CERTBOT_EMAIL}
187188
TARGET_ENDPOINT: http://backend:8080
188-
189-
AWS_PROFILE: certbot
190189
SET_CAA: 'true'
191190
192-
configs:
193-
aws_config:
194-
content: |
195-
[profile certbot]
196-
role_arn=${ROUTE53_AWS_ROLE_ARN}
197-
source_profile=certbot-source
198-
region=${AWS_REGION}
199-
200-
aws_credentials:
201-
content: |
202-
[certbot-source]
203-
aws_access_key_id=${ROUTE53_AWS_ACCESS_KEY_ID}
204-
aws_secret_access_key=${ROUTE53_AWS_SECRET_ACCESS_KEY}
205191
```
206192

207193
## Migration from Cloudflare-only Setup

custom-domain/dstack-ingress/scripts/certman.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ def _build_certbot_command(self, action: str, domain: str, email: str) -> List[s
291291
if os.environ.get("CERTBOT_STAGING", "false") == "true":
292292
base_cmd.extend(["--staging"])
293293

294-
if getattr(self.provider, 'CERTBOT_PROPAGATION_SECONDS') and self.provider.CERTBOT_PROPAGATION_SECONDS is not None:
294+
if getattr(self.provider, 'CERTBOT_PROPAGATION_SECONDS'):
295295
propagation_seconds = self.provider.CERTBOT_PROPAGATION_SECONDS
296296
propagation_param = f"--dns-{self.provider_type}-propagation-seconds={propagation_seconds}"
297297
base_cmd.extend([propagation_param])

custom-domain/dstack-ingress/scripts/dns_providers/route53.py

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Route53DNSProvider(DNSProvider):
2525
CERTBOT_PACKAGE = "certbot-dns-route53==5.1.0"
2626
CERTBOT_PROPAGATION_SECONDS = None
2727
AWS_CREDENTIALS_FILE = "~/.aws/credentials"
28+
AWS_CONFIG_FILE = "~/.aws/config"
2829

2930
def __init__(self):
3031
super().__init__()
@@ -40,10 +41,6 @@ def __init__(self):
4041
"Install with: pip install boto3"
4142
)
4243

43-
# Initialize Route53 client
44-
# boto3 automatically uses environment variables:
45-
# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN (optional)
46-
# It also supports IAM roles when running on AWS infrastructure
4744
try:
4845
self.client = self.boto3.client("route53")
4946
except Exception as e:
@@ -55,12 +52,14 @@ def __init__(self):
5552
def setup_certbot_credentials(self) -> bool:
5653
"""Setup AWS credentials file for certbot.
5754
58-
certbot-dns-route53 uses standard AWS credentials from:
59-
1. Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
60-
2. ~/.aws/credentials file
61-
3. IAM roles (when running on AWS)
55+
This container will be provided with aws credentials purely for the purpose
56+
of assuming a role. Doing so will enable the boto platform to provision
57+
temporary access key and secret keys on demand!
6258
63-
If credentials are in environment variables, we'll create the credentials file.
59+
Using this strategy we can impose least permissive and fast expiring access
60+
to our domain.
61+
62+
Credentials are in environment variables, we'll create the credentials file.
6463
"""
6564
aws_access_key = os.getenv("AWS_ACCESS_KEY_ID")
6665
aws_secret_key = os.getenv("AWS_SECRET_ACCESS_KEY")
@@ -71,31 +70,45 @@ def setup_certbot_credentials(self) -> bool:
7170
return True
7271

7372
credentials_file = os.path.expanduser(self.AWS_CREDENTIALS_FILE)
73+
config_file = os.path.expanduser(self.AWS_CONFIG_FILE)
74+
75+
aws_role_arn = os.getenv('AWS_ROLE_ARN')
76+
aws_region = os.getenv('AWS_REGION', 'us-east-1')
77+
7478
credentials_dir = os.path.dirname(credentials_file)
7579

7680
try:
7781
# Create credentials directory
7882
os.makedirs(credentials_dir, exist_ok=True)
7983

80-
# Check if credentials file already exists
8184
if os.path.exists(credentials_file):
8285
print(f"AWS credentials file already exists: {credentials_file}")
83-
return True
8486

85-
# Write credentials file in AWS INI format
86-
with open(credentials_file, "w") as f:
87-
f.write("[default]\n")
88-
f.write(f"aws_access_key_id = {aws_access_key}\n")
89-
f.write(f"aws_secret_access_key = {aws_secret_key}\n")
87+
else:
88+
# Write credentials file in AWS INI format
89+
with open(credentials_file, "w") as f:
90+
f.write("[certbot-source]\n")
91+
f.write(f"aws_access_key_id = {aws_access_key}\n")
92+
f.write(f"aws_secret_access_key = {aws_secret_key}\n")
93+
94+
# Set secure permissions
95+
os.chmod(credentials_file, 0o600)
96+
print(f"AWS credentials file created: {credentials_file}")
9097

91-
# Add session token if available
92-
aws_session_token = os.getenv("AWS_SESSION_TOKEN")
93-
if aws_session_token:
94-
f.write(f"aws_session_token = {aws_session_token}\n")
98+
if os.path.exists(credentials_file):
99+
print(f"AWS config file already exists: {config_file}")
95100

96-
# Set secure permissions
97-
os.chmod(credentials_file, 0o600)
98-
print(f"AWS credentials file created: {credentials_file}")
101+
else:
102+
# Write config file in AWS INI format
103+
with open(config_file, "w") as f:
104+
f.write("[profile certbot]\n")
105+
f.write(f"role_arn={aws_role_arn}\n")
106+
f.write("source_profile=certbot-source\n")
107+
f.write(f"region={aws_region}\n")
108+
109+
# Set secure permissions
110+
os.chmod(credentials_file, 0o600)
111+
print(f"AWS config file created: {config_file}")
99112

100113
# Pre-fetch hosted zone ID if we have a domain
101114
domain = os.getenv("DOMAIN")

0 commit comments

Comments
 (0)