Skip to content

Commit 83b534c

Browse files
committed
switch to AWS localstack; mock ACM integration; add certificate DNS values; show DNS configs on territory edit
1 parent d906afa commit 83b534c

File tree

15 files changed

+125
-55
lines changed

15 files changed

+125
-55
lines changed

.env.development

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
170170
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
171171
PERSISTENCE=1
172172
SKIP_SSL_CERT_DOWNLOAD=1
173+
LOCALSTACK_ENDPOINT=http://localhost:4566
173174

174175
# tor proxy
175176
TOR_PROXY=http://tor:7050/

api/acm/index.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
1-
import { ACM } from 'aws-sdk'
2-
// TODO: skeleton
1+
import AWS from 'aws-sdk'
2+
// TODO: boilerplate
33

4-
const region = 'us-east-1' // cloudfront ACM is in us-east-1
5-
const acm = new ACM({ region })
4+
AWS.config.update({
5+
region: 'us-east-1'
6+
})
7+
8+
const config = {
9+
s3ForcePathStyle: process.env.NODE_ENV === 'development'
10+
}
611

712
export async function requestCertificate (domain) {
13+
// for local development, we use the LOCALSTACK_ENDPOINT which
14+
// is reachable from the host machine
15+
if (process.env.NODE_ENV === 'development') {
16+
config.endpoint = process.env.LOCALSTACK_ENDPOINT
17+
}
18+
19+
const acm = new AWS.ACM(config)
820
const params = {
921
DomainName: domain,
1022
ValidationMethod: 'DNS',
@@ -20,7 +32,18 @@ export async function requestCertificate (domain) {
2032
return certificate.CertificateArn
2133
}
2234

23-
export async function getCertificateStatus (certificateArn) {
35+
export async function describeCertificate (certificateArn) {
36+
// for local development, we use the LOCALSTACK_ENDPOINT which
37+
// is reachable from the host machine
38+
if (process.env.NODE_ENV === 'development') {
39+
config.endpoint = process.env.LOCALSTACK_ENDPOINT
40+
}
41+
const acm = new AWS.ACM(config)
2442
const certificate = await acm.describeCertificate({ CertificateArn: certificateArn }).promise()
43+
return certificate
44+
}
45+
46+
export async function getCertificateStatus (certificateArn) {
47+
const certificate = await describeCertificate(certificateArn)
2548
return certificate.Certificate.Status
2649
}

api/resolvers/sub.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ export default {
312312
data: {
313313
domain,
314314
dnsState: 'PENDING',
315-
cname: 'todo', // TODO: explore other options
316315
verificationTxt: randomBytes(32).toString('base64'), // TODO: explore other options
317316
sub: {
318317
connect: { name: subName }

api/typeDefs/sub.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export default gql`
1818
sslState: String
1919
certificateArn: String
2020
lastVerifiedAt: Date
21-
cname: String
21+
verificationCname: String
22+
verificationCnameValue: String
2223
verificationTxt: String
2324
}
2425

components/territory-domains.js

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Badge } from 'react-bootstrap'
22
import { Form, Input, SubmitButton } from './form'
33
import { gql, useMutation } from '@apollo/client'
4-
import Info from './info'
54
import { customDomainSchema } from '@/lib/validate'
65
import ActionTooltip from './action-tooltip'
76
import { useToast } from '@/components/toast'
@@ -77,23 +76,6 @@ export default function CustomDomainForm ({ sub }) {
7776
{getStatusBadge(sub.customDomain.dnsState)}
7877
</ActionTooltip>
7978
{getSSLStatusBadge(sub.customDomain.sslState)}
80-
{sub.customDomain.dnsState === 'PENDING' && (
81-
<Info>
82-
<h6>Verify your domain</h6>
83-
<p>Add the following DNS records to verify ownership of your domain:</p>
84-
<pre>
85-
CNAME record:
86-
Host: @
87-
Value: stacker.news
88-
</pre>
89-
</Info>
90-
)}
91-
{sub.customDomain.sslState === 'PENDING' && (
92-
<Info>
93-
<h6>SSL certificate pending</h6>
94-
<p>Our system will issue an SSL certificate for your domain.</p>
95-
</Info>
96-
)}
9779
</div>
9880
</>
9981
)}
@@ -105,6 +87,38 @@ export default function CustomDomainForm ({ sub }) {
10587
{/* TODO: toaster */}
10688
<SubmitButton variant='primary' className='mt-3'>save</SubmitButton>
10789
</div>
90+
{(sub.customDomain.dnsState === 'PENDING' || sub.customDomain.dnsState === 'FAILED') && (
91+
<>
92+
<h6>Verify your domain</h6>
93+
<p>Add the following DNS records to verify ownership of your domain:</p>
94+
<pre>
95+
CNAME:
96+
Host: @
97+
Value: stacker.news
98+
</pre>
99+
<pre>
100+
TXT:
101+
Host: @
102+
Value: ${sub.customDomain.verificationTxt}
103+
</pre>
104+
</>
105+
)}
106+
{sub.customDomain.sslState === 'PENDING' && (
107+
<>
108+
<h6>SSL verification pending</h6>
109+
<p>We issued an SSL certificate for your domain.</p>
110+
<pre>
111+
CNAME:
112+
Host: ${sub.customDomain.verificationCname}
113+
Value: ${sub.customDomain.verificationCnameValue}
114+
</pre>
115+
<pre>
116+
TXT:
117+
Host: @
118+
Value: ${sub.customDomain.verificationTxt}
119+
</pre>
120+
</>
121+
)}
108122
</Form>
109123
)
110124
}

docker-compose.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ services:
136136
labels:
137137
- "CONNECT=localhost:3001"
138138
cpu_shares: "${CPU_SHARES_LOW}"
139-
s3:
140-
container_name: s3
141-
image: localstack/localstack:s3-latest
139+
aws:
140+
container_name: aws
141+
image: localstack/localstack:latest
142142
# healthcheck:
143143
# test: ["CMD-SHELL", "awslocal", "s3", "ls", "s3://uploads"]
144144
# interval: 10s
@@ -156,9 +156,9 @@ services:
156156
expose:
157157
- "4566"
158158
volumes:
159-
- 's3:/var/lib/localstack'
160-
- './docker/s3/init-s3.sh:/etc/localstack/init/ready.d/init-s3.sh'
161-
- './docker/s3/cors.json:/etc/localstack/init/ready.d/cors.json'
159+
- 'aws:/var/lib/localstack'
160+
- './docker/aws/s3/init-s3.sh:/etc/localstack/init/ready.d/init-s3.sh'
161+
- './docker/aws/s3/cors.json:/etc/localstack/init/ready.d/cors.json'
162162
labels:
163163
- "CONNECT=localhost:4566"
164164
cpu_shares: "${CPU_SHARES_LOW}"
@@ -829,7 +829,7 @@ volumes:
829829
lnd:
830830
cln:
831831
router_lnd:
832-
s3:
832+
aws:
833833
nwc_send:
834834
nwc_recv:
835835
tordata:
File renamed without changes.
File renamed without changes.

fragments/subs.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ export const SUB_FIELDS = gql`
4444
sslState
4545
certificateArn
4646
lastVerifiedAt
47-
cname
47+
verificationCname
48+
verificationCnameValue
4849
verificationTxt
4950
}
5051
}`

lib/domains.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { requestCertificate, getCertificateStatus } from '@/api/acm'
1+
import { requestCertificate, getCertificateStatus, describeCertificate } from '@/api/acm'
22
import { promises as dnsPromises } from 'node:dns'
33

44
// TODO: skeleton
@@ -25,7 +25,7 @@ export async function checkCertificateStatus (certificateArn) {
2525
// map ACM statuses
2626
switch (certStatus) {
2727
case 'ISSUED':
28-
return 'ISSUED'
28+
return 'VERIFIED'
2929
case 'PENDING_VALIDATION':
3030
return 'PENDING'
3131
case 'VALIDATION_TIMED_OUT':
@@ -36,7 +36,26 @@ export async function checkCertificateStatus (certificateArn) {
3636
}
3737
}
3838

39-
export async function verifyDomainDNS (domainName, verificationTxt, cname) {
39+
export async function certDetails (certificateArn) {
40+
try {
41+
const certificate = await describeCertificate(certificateArn)
42+
return certificate
43+
} catch (error) {
44+
console.error(`Certificate description failed: ${error.message}`)
45+
return null
46+
}
47+
}
48+
49+
export async function getValidationValues (certificateArn) {
50+
const certificate = await certDetails(certificateArn)
51+
console.log(certificate.DomainValidationOptions)
52+
return {
53+
cname: certificate.DomainValidationOptions[0].ResourceRecord.Name,
54+
value: certificate.DomainValidationOptions[0].ResourceRecord.Value
55+
}
56+
}
57+
58+
export async function verifyDomainDNS (domainName, verificationTxt, cname = 'parallel.soxa.dev') {
4059
const result = {
4160
txtValid: false,
4261
cnameValid: false,

0 commit comments

Comments
 (0)