Skip to content

Commit d8ab123

Browse files
committed
chore(clickbench): remove hardcoded credentials and account-specific defaults from EC2 launch flow
- launch-ec2.sh: replace the fixed root serial-console password baked into user-data with a random per-launch password (openssl rand -hex 12), injected via placeholder substitution and printed to the operator. The serial console connection is key-authenticated via ec2-instance-connect, but the ttyS0 getty still needs a local password login, so password auth stays — just no longer checked into git. - launch-ec2.sh: move AMI / subnet / security group / profile (+ new REGION, INSTANCE_TYPE, VOLUME_SIZE) into an env-overridable, clearly-labeled 'Xata account defaults' block; pass --region to every aws call. - launch-ec2.sh: the cloud-init SSH wait loop now fails loudly (exit 1 with inspect/teardown guidance) instead of printing 'Instance ready' after exhausting its 30 tries. - Makefile: drop the personal EC2_KEY ?= ~/.ssh/tsg.pem default. EC2_KEY now derives from KEY_NAME (~/.ssh/$KEY_NAME.pem, the launch-ec2.sh convention) or must be passed explicitly; ssh/rsync targets abort with a clear error when neither is set. launch targets forward KEY_NAME to the script. AWS_PROFILE default labeled as a Xata account default.
1 parent 8d2bcdc commit d8ab123

2 files changed

Lines changed: 75 additions & 23 deletions

File tree

clickbench/Makefile

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# EC2 ClickBench benchmark workflow
22
#
33
# Lifecycle:
4-
# make launch-ec2 # launch EC2 instance, prints export EC2=<ip>
4+
# make launch-ec2 KEY_NAME=<key> # launch EC2 instance, prints export EC2=<ip>
55
# make bench-full EC2=<ip> # full ClickBench-equivalent run (install + load + queries)
66
# make bench EC2=<ip> # queries-only against an already-loaded DB
77
# make bench-concurrent EC2=<ip> # only the concurrent-QPS test; merges into the latest results JSON
@@ -43,7 +43,18 @@
4343
# make psql EC2=<ip>
4444

4545
EC2 ?=
46-
EC2_KEY ?= ~/.ssh/tsg.pem
46+
# SSH key for the EC2 instance. No personal default — provide either:
47+
# KEY_NAME=<ec2-key-pair> -> uses ~/.ssh/<ec2-key-pair>.pem, same convention
48+
# as launch-ec2.sh
49+
# EC2_KEY=<path-to-pem> -> explicit path
50+
# Targets that don't ssh/rsync (launch-ec2, destroy-ec2, ...) work without it.
51+
KEY_NAME ?=
52+
ifneq ($(strip $(KEY_NAME)),)
53+
EC2_KEY ?= ~/.ssh/$(KEY_NAME).pem
54+
endif
55+
ifeq ($(origin EC2_KEY),undefined)
56+
EC2_KEY = $(error EC2_KEY is not set. Pass KEY_NAME=<your-ec2-key-pair> to use ~/.ssh/<key>.pem, or EC2_KEY=<path-to-pem> directly)
57+
endif
4758
EC2_USER ?= ubuntu
4859
PARQUET ?= 1
4960
EC2_SSH = ssh -i $(EC2_KEY) -o StrictHostKeyChecking=no $(EC2_USER)@$(EC2)
@@ -57,6 +68,7 @@ HISTORY_DIR = $(RESULTS_DIR)/history
5768
CLICKBENCH_DIR ?= $(CURDIR)/../../../ClickBench/pg_deltax
5869
CLICKBENCH_REPO ?= $(CLICKBENCH_DIR)/..
5970

71+
# Xata account default (shared org infra) — override for other AWS accounts.
6072
AWS_PROFILE ?= management
6173
AWS_NAME = clickbench-pg-deltax
6274
REFERENCE_AWS_NAME = clickbench-pg-deltax-reference
@@ -65,8 +77,9 @@ REFERENCE_AWS_NAME = clickbench-pg-deltax-reference
6577

6678
# Launch a new EC2 instance. Aborts if the name is already taken (never
6779
# terminates implicitly); requires KEY_NAME — see launch-ec2.sh.
80+
# Usage: make launch-ec2 KEY_NAME=<your-ec2-key-pair>
6881
launch-ec2:
69-
@bash launch-ec2.sh
82+
@KEY_NAME="$(KEY_NAME)" bash launch-ec2.sh
7083

7184
# Terminate the EC2 instance
7285
destroy-ec2:
@@ -86,7 +99,7 @@ destroy-ec2:
8699
# Launch a separate EC2 instance for the vanilla-PG correctness reference run.
87100
# Uses a different Name tag so it doesn't clobber the bench EC2.
88101
launch-reference-ec2:
89-
@bash launch-ec2.sh --name $(REFERENCE_AWS_NAME) --reference
102+
@KEY_NAME="$(KEY_NAME)" bash launch-ec2.sh --name $(REFERENCE_AWS_NAME) --reference
90103

91104
# Terminate the reference EC2 instance.
92105
destroy-reference-ec2:

clickbench/launch-ec2.sh

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
#!/bin/bash
22
set -euo pipefail
33

4+
INSTANCE_TYPE=${INSTANCE_TYPE:-c6a.4xlarge}
5+
VOLUME_SIZE=${VOLUME_SIZE:-500}
6+
7+
# --- Xata account defaults ---------------------------------------------------
8+
# Shared org infrastructure in the Xata management account (us-east-1). These
9+
# are resource identifiers, not secrets, but they are account-specific:
10+
# override them via env when launching in a different AWS account/region, e.g.
11+
# PROFILE=myprofile REGION=eu-west-1 AMI=ami-... SUBNET=subnet-... SG=sg-... ./launch-ec2.sh
412
PROFILE=${PROFILE:-management}
5-
INSTANCE_TYPE=c6a.4xlarge
6-
AMI=ami-04eaa218f1349d88b
13+
REGION=${REGION:-us-east-1}
14+
AMI=${AMI:-ami-04eaa218f1349d88b} # Ubuntu amd64 image used by the bench boxes
15+
SUBNET=${SUBNET:-subnet-228cc17d}
16+
SG=${SG:-sg-add473b4}
17+
# -----------------------------------------------------------------------------
18+
719
# Personal key pair: no generic default exists, so it must be provided.
820
# KEY_NAME=<your-ec2-key-pair> [KEY_FILE=~/.ssh/<key>.pem] ./launch-ec2.sh
921
KEY_NAME=${KEY_NAME:-}
1022
KEY_FILE=${KEY_FILE:-~/.ssh/${KEY_NAME}.pem}
11-
SUBNET=subnet-228cc17d
12-
SG=sg-add473b4
13-
VOLUME_SIZE=500
1423
# Track whether the name was given explicitly (env or --name): teardown
1524
# refuses to run against the implicit default name.
1625
NAME_EXPLICIT=false
@@ -70,15 +79,15 @@ fi
7079
# multiple people run benches in this account in parallel (e.g. tsg's
7180
# long-lived clickbench/rtabench/jsonbench boxes). Launching requires a
7281
# free name; explicit teardown requires --terminate-only.
73-
EXISTING=$(aws ec2 describe-instances --profile "$PROFILE" \
82+
EXISTING=$(aws ec2 describe-instances --profile "$PROFILE" --region "$REGION" \
7483
--filters "Name=tag:Name,Values=$NAME" "Name=instance-state-name,Values=running,stopped,pending" \
7584
--query 'Reservations[*].Instances[*].InstanceId' --output text)
7685

7786
if $TERMINATE_ONLY; then
7887
if [ -n "$EXISTING" ]; then
7988
echo "Terminating instance(s) named '$NAME': $EXISTING"
80-
aws ec2 terminate-instances --profile "$PROFILE" --instance-ids $EXISTING --output text
81-
aws ec2 wait instance-terminated --profile "$PROFILE" --instance-ids $EXISTING
89+
aws ec2 terminate-instances --profile "$PROFILE" --region "$REGION" --instance-ids $EXISTING --output text
90+
aws ec2 wait instance-terminated --profile "$PROFILE" --region "$REGION" --instance-ids $EXISTING
8291
echo "Terminated."
8392
else
8493
echo "No instance named '$NAME' to terminate."
@@ -97,15 +106,26 @@ fi
97106
# Enable serial console access (idempotent, account-level setting; only
98107
# needed for the launch flow's serial-console fallback)
99108
echo "Ensuring serial console access is enabled..."
100-
aws ec2 enable-serial-console-access --profile "$PROFILE" --region us-east-1 >/dev/null 2>&1 || true
109+
aws ec2 enable-serial-console-access --profile "$PROFILE" --region "$REGION" >/dev/null 2>&1 || true
110+
111+
# Root password for the serial-console emergency login. The serial-console
112+
# *connection* is authenticated by pushing an SSH key via ec2-instance-connect
113+
# (see the hint at the end of this script), but the getty on ttyS0 still
114+
# presents a normal login prompt, which requires a local password — so password
115+
# auth can't be dropped from this flow entirely. Instead of a fixed password
116+
# checked into git, generate a random one per launch and print it at the end.
117+
# It only grants access through the serial console, which itself requires AWS
118+
# credentials; it is not stored anywhere besides the instance's /etc/shadow.
119+
SERIAL_PW=$(openssl rand -hex 12)
101120

102121
# User-data script: OOM diagnostics + serial console access
103122
USER_DATA=$(cat <<'USERDATA'
104123
#!/bin/bash
105124
set -x
106125
107-
# Set root password for serial console login
108-
echo 'root:Cb3nch!s3rial#2026' | chpasswd
126+
# Set root password for serial console login (substituted at launch time;
127+
# random per launch, printed by launch-ec2.sh)
128+
echo 'root:__SERIAL_PW__' | chpasswd
109129
110130
# Enable root login on serial console
111131
mkdir -p /etc/systemd/system/serial-getty@ttyS0.service.d
@@ -142,10 +162,13 @@ sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="console=tty0
142162
update-grub 2>/dev/null || true
143163
USERDATA
144164
)
165+
# Inject the per-launch serial-console password (heredoc is quoted, so this is
166+
# the only substitution that happens in the user-data).
167+
USER_DATA=${USER_DATA//__SERIAL_PW__/$SERIAL_PW}
145168

146169
# Launch new instance
147170
echo "Launching $INSTANCE_TYPE instance..."
148-
INSTANCE_ID=$(aws ec2 run-instances --profile "$PROFILE" \
171+
INSTANCE_ID=$(aws ec2 run-instances --profile "$PROFILE" --region "$REGION" \
149172
--image-id "$AMI" \
150173
--instance-type "$INSTANCE_TYPE" \
151174
--key-name "$KEY_NAME" \
@@ -158,26 +181,42 @@ INSTANCE_ID=$(aws ec2 run-instances --profile "$PROFILE" \
158181

159182
echo "Instance ID: $INSTANCE_ID"
160183
echo "Waiting for instance to be running..."
161-
aws ec2 wait instance-running --profile "$PROFILE" --instance-ids "$INSTANCE_ID"
184+
aws ec2 wait instance-running --profile "$PROFILE" --region "$REGION" --instance-ids "$INSTANCE_ID"
162185

163-
IP=$(aws ec2 describe-instances --profile "$PROFILE" \
186+
IP=$(aws ec2 describe-instances --profile "$PROFILE" --region "$REGION" \
164187
--instance-ids "$INSTANCE_ID" \
165188
--query 'Reservations[0].Instances[0].PublicIpAddress' --output text)
166189

167-
echo "Instance ready: $IP"
190+
echo "Instance running: $IP"
168191
echo ""
169192
echo " ssh -i $KEY_FILE ubuntu@$IP"
170193
echo ""
171194

172-
# Wait for user-data to complete (cloud-init)
195+
# Wait for user-data to complete (cloud-init). Fail loudly if we never get
196+
# through — a half-initialized box must not be reported as ready.
173197
echo "Waiting for cloud-init to finish..."
198+
CLOUD_INIT_OK=false
174199
for i in $(seq 1 30); do
175200
if ssh -i "$KEY_FILE" -o StrictHostKeyChecking=no -o ConnectTimeout=5 "ubuntu@$IP" "cloud-init status --wait" 2>/dev/null; then
201+
CLOUD_INIT_OK=true
176202
break
177203
fi
178204
sleep 5
179205
done
180206

207+
if ! $CLOUD_INIT_OK; then
208+
echo "" >&2
209+
echo "ERROR: could not confirm cloud-init completion on $IP after 30 attempts." >&2
210+
echo "The instance ($INSTANCE_ID) is still running — it was NOT terminated." >&2
211+
echo "Inspect it:" >&2
212+
echo " ssh -i $KEY_FILE ubuntu@$IP" >&2
213+
echo " ssh -i $KEY_FILE ubuntu@$IP 'cloud-init status --long'" >&2
214+
echo "Or tear it down:" >&2
215+
echo " $0 --terminate-only --name $NAME" >&2
216+
echo "Serial-console root password for this launch: $SERIAL_PW" >&2
217+
exit 1
218+
fi
219+
181220
echo ""
182221
echo "Instance ready. Next steps:"
183222
echo ""
@@ -193,6 +232,6 @@ else
193232
fi
194233
echo ""
195234
echo "Serial console (if SSH is down):"
196-
echo " aws ec2-instance-connect send-serial-console-ssh-public-key --profile $PROFILE --instance-id $INSTANCE_ID --serial-port 0 --ssh-public-key file://${KEY_FILE%.pem}.pub --region us-east-1"
197-
echo " ssh -i $KEY_FILE $INSTANCE_ID.port0@serial-console.ec2-instance-connect.us-east-1.aws"
198-
echo " Login: root / Cb3nch!s3rial#2026"
235+
echo " aws ec2-instance-connect send-serial-console-ssh-public-key --profile $PROFILE --instance-id $INSTANCE_ID --serial-port 0 --ssh-public-key file://${KEY_FILE%.pem}.pub --region $REGION"
236+
echo " ssh -i $KEY_FILE $INSTANCE_ID.port0@serial-console.ec2-instance-connect.$REGION.aws"
237+
echo " Login: root / $SERIAL_PW (random, generated for this launch only — note it down if you may need the serial console)"

0 commit comments

Comments
 (0)