Setting the file. One moment. Db2client Airgap · RDS Db2 · aws/agent-toolkit-for-aws · Skills Docs70
Creating Amazon Aurora Db Cluster With Instances
93
Routing Traffic With Route53 And CloudFront
Resilience Program Design
Creating API Gateway Stage
Shellscripts/db2client-airgap.sh
Shell·335 lines·14 KB
11
12# Db2 version selection — set DB2_VER before running:
13# DB2_VER=11.5 (default) → downloads Db2 11.5.9 RT client + db211.5.9-tools.zip
14# DB2_VER=12.1 → downloads Db2 12.1.3 RT client + db212.1-tools.zip
15DB2_VER=${DB2_VER:-"11.5"}
16
17case "$DB2_VER" in
18 11.5)
19 DRIVER_RT="v11.5.9_linuxx64_rtcl.tar"
20 TOOLS_ZIP="db211.5.9-tools.zip"
21 ;;
22 12.1)
23 DRIVER_RT="v12.1.4_linuxx64_rtcl.tar"
24 TOOLS_ZIP="db212.1-tools.zip"
25 ;;
26 *)
27 echo "ERROR: Unsupported DB2_VER='${DB2_VER}'. Valid values: 11.5, 12.1" >&2
28 exit 1
29 ;;
30esac
31
32# =============================================================================
33# db2client-airgap.sh — Populate private bucket for air-gapped deployments
34# =============================================================================
35# MODE: download — download all artifacts to ./db2client-artifacts/ (needs internet)
36# MODE: upload — create bucket and upload from ./db2client-artifacts/ (needs AWS)
37# MODE: both — download then upload in one shot (default)
38#
39# Usage:
40# ./$SCRIPT_AIRGAP --mode download --region us-east-1 # step 1: laptop with internet
41# ./$SCRIPT_AIRGAP --mode upload --region us-east-1 # step 2: machine with AWS access
42# ./$SCRIPT_AIRGAP --mode both --region us-east-1 # download + upload in one shot
43#
44# NOTE: --region is required for all modes. It determines the RDS SSL certificate
45# filename (e.g. us-east-1-bundle.pem).
46# =============================================================================
47
48if [ -z "$BASH_VERSION" ]; then exec bash "$0" "$@"; fi
49set -eo pipefail
50export AWS_PAGER=""
51
52RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
53BLUE='\033[0;34m'; NC='\033[0m'
54log_info() { echo -e "${BLUE}[ INFO]${NC} $(date '+%H:%M:%S') - $1" >&2; }
55log_success() { echo -e "${GREEN}[SUCCESS]${NC} $(date '+%H:%M:%S') - $1" >&2; }
56log_warning() { echo -e "${YELLOW}[WARNING]${NC} $(date '+%H:%M:%S') - $1" >&2; }
57log_error() { echo -e "${RED}[ ERROR]${NC} $(date '+%H:%M:%S') - $1" >&2; }
58
59SOURCE_BUCKET="aws-blogs-artifacts-public"
60SOURCE_PREFIX="artifacts/DBBLOG-4900"
61SOURCE_URL="https://${SOURCE_BUCKET}.s3.amazonaws.com/${SOURCE_PREFIX}"
62ARTIFACTS_DIR="./db2client-artifacts"
63MODE=${MODE:-"both"}
64
65# --- Curl-pipe detection ---
66CURL_PIPE=false
67detect_curl_pipe() {
68 local src="${BASH_SOURCE[0]:-}"
69 if [[ -z "$src" || "$src" == "/dev/fd/"* || "$src" == "/dev/stdin" || ! -f "$src" ]]; then
70 CURL_PIPE=true
71 fi
72}
73
74handle_curl_pipe_download() {
75 log_info "Downloading ${SCRIPT_AIRGAP} ..."
76 curl -fsSL "${SOURCE_URL}/${SCRIPT_AIRGAP}" -o "./${SCRIPT_AIRGAP}" && chmod +x "./${SCRIPT_AIRGAP}"
77 log_success "Saved: ./${SCRIPT_AIRGAP}"
78
79 log_info "Downloading ${SCRIPT_CLIENT} ..."
80 curl -fsSL "${SOURCE_URL}/${SCRIPT_CLIENT}" -o "./${SCRIPT_CLIENT}" && chmod +x "./${SCRIPT_CLIENT}"
81 log_success "Saved: ./${SCRIPT_CLIENT}"
82
83 echo
84 echo "============================================================="
85 echo " Downloaded. Steps for air-gapped deployment:"
86 echo "============================================================="
87 echo
88 echo "STEP 1a — Download all artifacts on this machine (needs internet):"
89 echo " ./$SCRIPT_AIRGAP --mode download --region <your-region>"
90 echo
91 echo "STEP 1b — Copy $SCRIPT_AIRGAP, $SCRIPT_CLIENT and db2client-artifacts/"
92 echo " to a machine with AWS access (private subnet). Then upload:"
93 echo " ./$SCRIPT_AIRGAP --mode upload --region <your-region>"
94 echo
95 echo " Or if this machine also has AWS access, run both in one shot:"
96 echo " ./$SCRIPT_AIRGAP --mode both --region <your-region>"
97 echo
98 echo "STEP 2 — On the target Linux machine, pull the install script and run it:"
99 echo " aws s3 cp s3://db2client-artifacts-<account>-<region>/$SCRIPT_CLIENT . && chmod +x $SCRIPT_CLIENT"
100 echo " BUCKET=db2client-artifacts-<account>-<region> ./$SCRIPT_CLIENT --region <your-region>"
101 echo "============================================================="
102}
103
104# --- Argument parsing ---
105while [[ $# -gt 0 ]]; do
106 case $1 in
107 --mode) MODE="$2"; shift 2 ;;
108 --region) REGION="$2"; shift 2 ;;
109 --profile) PROFILE="$2"; shift 2 ;;
110 -h|--help)
111 echo "Usage: $SCRIPT_AIRGAP --mode download|upload|both --region REGION [--profile PROFILE]"
112 echo " --region is required: determines the RDS SSL certificate filename."
113 exit 0 ;;
114 *) log_error "Unknown option: $1"; exit 1 ;;
115 esac
116done
117
118# --- Curl-pipe detection (must precede the mandatory --region check, since
119# a curl|bash bootstrap has no args and only needs handle_curl_pipe_download) ---
120detect_curl_pipe
121if $CURL_PIPE; then
122 handle_curl_pipe_download
123 exit 0
124fi
125
126# --- Enforce mandatory --region ---
127if [ -z "${REGION:-}" ]; then
128 log_error "--region is required. Example: $SCRIPT_AIRGAP --mode download --region us-east-1"
129 exit 1
130fi
131
132# --- AWS setup (required for upload/both) ---
133set_credentials_airgap() {
134 # If creds already exported in environment, use them as-is
135 if [ -n "${AWS_ACCESS_KEY_ID:-}" ] && [ -n "${AWS_SECRET_ACCESS_KEY:-}" ]; then
136 log_info "Using AWS credentials from environment variables"
137 CREDS_FROM_METADATA=false
138 return
139 fi
140
141 if curl -s --connect-timeout 1 http://127.0.0.1:1338/latest/meta-data/ >/dev/null 2>&1; then
142 log_info "Detected AWS CloudShell environment"
143 local token creds
144 token=$(curl -sX PUT "http://127.0.0.1:1338/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
145 creds=$(curl -s -H "Authorization: $token" "http://127.0.0.1:1338/latest/meta-data/container/security-credentials")
146 export AWS_ACCESS_KEY_ID=$(echo "$creds" | python3 -c "import sys,json; print(json.load(sys.stdin)['AccessKeyId'])")
147 export AWS_SECRET_ACCESS_KEY=$(echo "$creds" | python3 -c "import sys,json; print(json.load(sys.stdin)['SecretAccessKey'])")
148 export AWS_SESSION_TOKEN=$(echo "$creds" | python3 -c "import sys,json; print(json.load(sys.stdin)['Token'])")
149 CREDS_FROM_METADATA=true
150 return
151 fi
152 if curl -s --connect-timeout 1 http://169.254.169.254/latest/meta-data/ >/dev/null 2>&1; then
153 log_info "Detected EC2 environment"
154 local token role creds
155 token=$(curl -sX PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
156 role=$(curl -s -H "X-aws-ec2-metadata-token: $token" http://169.254.169.254/latest/meta-data/iam/security-credentials/)
157 creds=$(curl -s -H "X-aws-ec2-metadata-token: $token" "http://169.254.169.254/latest/meta-data/iam/security-credentials/$role")
158 export AWS_ACCESS_KEY_ID=$(echo "$creds" | python3 -c "import sys,json; print(json.load(sys.stdin)['AccessKeyId'])")
159 export AWS_SECRET_ACCESS_KEY=$(echo "$creds" | python3 -c "import sys,json; print(json.load(sys.stdin)['SecretAccessKey'])")
160 export AWS_SESSION_TOKEN=$(echo "$creds" | python3 -c "import sys,json; print(json.load(sys.stdin)['Token'])")
161 CREDS_FROM_METADATA=true
162 return
163 fi
164 CREDS_FROM_METADATA=false
165}
166
167setup_aws() {
168 PROFILE=${PROFILE:-"default"}
169 CREDS_FROM_METADATA=false
170 set_credentials_airgap
171
172 if [ -n "${AWS_ACCESS_KEY_ID:-}" ] && [ -n "${AWS_SECRET_ACCESS_KEY:-}" ]; then
173 PROFILE_ARG=""
174 else
175 PROFILE_ARG="--profile $PROFILE"
176 fi
177
178 if [ "$CREDS_FROM_METADATA" = "false" ]; then
179 if ! aws sts get-caller-identity $PROFILE_ARG --region "$REGION" >/dev/null 2>&1; then
180 log_error "AWS credentials invalid. Run 'aws configure' or set AWS_ACCESS_KEY_ID/SECRET."
181 exit 1
182 fi
183 fi
184 ACCOUNT_ID=$(aws sts get-caller-identity $PROFILE_ARG --region "$REGION" --query Account --output text 2>/dev/null)
185 if [ -z "$ACCOUNT_ID" ] || [ "$ACCOUNT_ID" = "None" ]; then
186 log_error "Could not determine AWS Account ID. Check credentials."
187 exit 1
188 fi
189 TARGET_BUCKET="db2client-artifacts-${ACCOUNT_ID}-${REGION}"
190 log_success "AWS ready | Account: $ACCOUNT_ID | Region: $REGION"
191}
192
193# =============================================================================
194# STEP 1 — Download all artifacts to ARTIFACTS_DIR (internet-connected laptop)
195# =============================================================================
196do_download() {
197 mkdir -p "${ARTIFACTS_DIR}/scripts" "${ARTIFACTS_DIR}/drivers" "${ARTIFACTS_DIR}/ssl"
198
199 log_info "Downloading jq static binary ..."
200 curl -fsSL "https://github.com/jqlang/jq/releases/download/${JQ_VERSION}/${JQ_BINARY}" \
201 -o "${ARTIFACTS_DIR}/scripts/jq"
202 log_success "Downloaded: scripts/jq"
203
204 log_info "Downloading DB2 client scripts from s3://${SOURCE_BUCKET}/${SOURCE_PREFIX}/ ..."
205 for f in "$FILE_FUNCTIONS" "$FILE_README"; do
206 curl -fsSL "https://${SOURCE_BUCKET}.s3.amazonaws.com/${SOURCE_PREFIX}/${f}" \
207 -o "${ARTIFACTS_DIR}/scripts/${f}"
208 log_success "Downloaded: scripts/${f}"
209 done
210 if [ "$INCLUDE_LICENSED_TOOLS" = "TRUE" ]; then
211 curl -fsSL "https://${SOURCE_BUCKET}.s3.amazonaws.com/${SOURCE_PREFIX}/${TOOLS_ZIP}" \
212 -o "${ARTIFACTS_DIR}/scripts/${TOOLS_ZIP}"
213 log_success "Downloaded: scripts/${TOOLS_ZIP}"
214 else
215 log_info "Skipping tools zip (${TOOLS_ZIP}) — set INCLUDE_LICENSED_TOOLS=TRUE to enable"
216 fi
217
218 log_info "Downloading ${SCRIPT_CONFIGURE} ..."
219 curl -fsSL "${SOURCE_URL}/${SCRIPT_CONFIGURE}" \
220 -o "${ARTIFACTS_DIR}/scripts/${SCRIPT_CONFIGURE}"
221 chmod +x "${ARTIFACTS_DIR}/scripts/${SCRIPT_CONFIGURE}"
222 log_success "Copied: scripts/${SCRIPT_CONFIGURE}"
223
224 log_info "Downloading DB2 driver packages (large files, this may take a while) ..."
225 curl -fsSL "https://${SOURCE_BUCKET}.s3.amazonaws.com/${SOURCE_PREFIX}/${DRIVER_RT}" \
226 -o "${ARTIFACTS_DIR}/drivers/${DRIVER_RT}"
227 log_success "Downloaded: drivers/${DRIVER_RT}"
228
229 log_info "Downloading RDS SSL certificate for region: $REGION ..."
230 local pem_file="${REGION}-bundle.pem"
231 if ! curl -fsSL "https://truststore.pki.rds.amazonaws.com/${REGION}/${pem_file}" \
232 -o "${ARTIFACTS_DIR}/ssl/${pem_file}"; then
233 log_error "Failed to download SSL certificate for region $REGION."
234 return 1
235 fi
236 log_success "Downloaded: ssl/${pem_file}"
237
238 echo
239 log_success "All artifacts saved to: ${ARTIFACTS_DIR}/"
240 echo
241 echo " Next: copy ${SCRIPT_CLIENT}, ${SCRIPT_AIRGAP} and"
242 echo " directory ${ARTIFACTS_DIR}/ to your system (private subnets) that has aws configured. Run:"
243 echo " ./$SCRIPT_AIRGAP --mode upload --region $REGION"
244 echo
245}
246
247# =============================================================================
248# STEP 2 — Create bucket and upload from ARTIFACTS_DIR (AWS-connected machine)
249# =============================================================================
250do_upload() {
251 setup_aws
252
253 if [ ! -d "$ARTIFACTS_DIR" ]; then
254 log_error "Artifacts directory not found: $ARTIFACTS_DIR"
255 log_error "Run './$SCRIPT_AIRGAP --mode download' first, then copy the directory here."
256 exit 1
257 fi
258
259 # --- Create target bucket if needed ---
260 if ! aws s3api head-bucket --bucket "$TARGET_BUCKET" --region "$REGION" $PROFILE_ARG 2>/dev/null; then
261 log_info "Creating bucket: $TARGET_BUCKET"
262 if [ "$REGION" = "us-east-1" ]; then
263 aws s3api create-bucket --bucket "$TARGET_BUCKET" --region "$REGION" $PROFILE_ARG >/dev/null
264 else
265 aws s3api create-bucket --bucket "$TARGET_BUCKET" --region "$REGION" $PROFILE_ARG \
266 --create-bucket-configuration LocationConstraint="$REGION" >/dev/null
267 fi
268 aws s3api put-bucket-versioning --bucket "$TARGET_BUCKET" \
269 --versioning-configuration Status=Enabled --region "$REGION" $PROFILE_ARG >/dev/null
270 log_success "Bucket created: $TARGET_BUCKET"
271 else
272 log_info "Bucket already exists: $TARGET_BUCKET"
273 fi
274
275 # --- Upload all artifacts ---
276 log_info "Uploading artifacts to s3://${TARGET_BUCKET}/ ..."
277 aws s3 sync "${ARTIFACTS_DIR}/" "s3://${TARGET_BUCKET}/" \
278 --region "$REGION" $PROFILE_ARG --quiet
279 log_success "Upload complete"
280
281 # --- Copy scripts to bucket so private subnet machines can pull via S3 GW ---
282 log_info "Copying scripts to s3://${TARGET_BUCKET}/ ..."
283 local script_dir
284 script_dir="$(dirname "$(realpath "$0")")"
285 aws s3 cp "${script_dir}/${SCRIPT_AIRGAP}" "s3://${TARGET_BUCKET}/${SCRIPT_AIRGAP}" \
286 --region "$REGION" $PROFILE_ARG --quiet
287 aws s3 cp "${script_dir}/${SCRIPT_CLIENT}" "s3://${TARGET_BUCKET}/${SCRIPT_CLIENT}" \
288 --region "$REGION" $PROFILE_ARG --quiet
289 aws s3 cp "${ARTIFACTS_DIR}/scripts/${SCRIPT_CONFIGURE}" "s3://${TARGET_BUCKET}/scripts/${SCRIPT_CONFIGURE}" \
290 --region "$REGION" $PROFILE_ARG --quiet
291 log_success "Scripts uploaded to s3://${TARGET_BUCKET}/"
292
293 # --- Verify ---
294 log_info "Verifying uploads..."
295 local missing=false
296 for key in \
297 scripts/jq \
298 "scripts/${FILE_FUNCTIONS}" \
299 "scripts/${FILE_README}" \
300 "scripts/${SCRIPT_CONFIGURE}" \
301 "drivers/${DRIVER_RT}" \
302 "ssl/${REGION}-bundle.pem"; do
303 if aws s3api head-object --bucket "$TARGET_BUCKET" --key "$key" \
304 --region "$REGION" $PROFILE_ARG &>/dev/null; then
305 log_success "OK: s3://${TARGET_BUCKET}/${key}"
306 else
307 log_warning "Missing: s3://${TARGET_BUCKET}/${key}"
308 missing=true
309 fi
310 done
311 [ "$missing" = "true" ] && log_warning "Some artifacts missing — check errors above."
312
313 echo
314 echo "============================================================="
315 echo " Bucket ready : s3://${TARGET_BUCKET}"
316 echo " SSL cert : s3://${TARGET_BUCKET}/ssl/${REGION}-bundle.pem"
317 echo
318 echo " STEP 1b (continued) — On the private subnet machine, download the install script:"
319 echo " aws s3 cp s3://${TARGET_BUCKET}/${SCRIPT_CLIENT} . && chmod +x ${SCRIPT_CLIENT}"
320 echo
321 echo " STEP 2 — Install the DB2 client:"
322 echo " export BUCKET=${TARGET_BUCKET} REGION=${REGION}"
323 echo " ./$SCRIPT_CLIENT"
324 echo "============================================================="
325}
326
327# =============================================================================
328# Main
329# =============================================================================
330case "$MODE" in
331 download) do_download ;;
332 upload) do_upload ;;
333 both) do_download; do_upload ;;
334 *) log_error "Unknown mode: $MODE. Use download, upload, or both."; exit 1 ;;
335esac