|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# AWS Secrets Manager retrieval and Proxygen deployment script for GitHub Actions |
| 4 | +# This script fetches secrets, retrieves private key from S3, sets up Proxygen credentials, and deploys |
| 5 | + |
| 6 | +set -euo pipefail |
| 7 | + |
| 8 | +# Define the secret paths (excluding private key which will come from S3) |
| 9 | +SECRETS=( |
| 10 | + "/ftrs-dos/dev/proxygen-key-id" |
| 11 | + "/ftrs-dos/dev/proxygen-client-id" |
| 12 | + "/ftrs-dos/dev/proxygen-public-key" |
| 13 | + "/temp/dev/api-ca-cert" |
| 14 | + "/temp/dev/api-ca-pk" |
| 15 | +) |
| 16 | + |
| 17 | +# Define corresponding output variable names |
| 18 | +OUTPUT_VARS=( |
| 19 | + "PROXYGEN_KEY_ID" |
| 20 | + "PROXYGEN_CLIENT_ID" |
| 21 | + "PROXYGEN_PUBLIC_KEY" |
| 22 | + "API_CA_CERT" |
| 23 | + "API_CA_PK" |
| 24 | +) |
| 25 | + |
| 26 | +# S3 configuration for private key |
| 27 | +S3_BUCKET="" |
| 28 | +S3_PRIVATE_KEY_PATH="ftrs-dos/dev/proxygen-private-key" |
| 29 | +PROXYGEN_PRIVATE_KEY_FILE="/tmp/proxygen-private-key.pem" |
| 30 | + |
| 31 | +# Proxygen configuration |
| 32 | +PROXYGEN_INSTANCE="internal-dev" |
| 33 | +PROXYGEN_SERVICE_NAME="ftrs-search-<workspace>" # not sure how to handle workspace here |
| 34 | +OASPEC_FILE="docs/specification/dos-search.yaml" |
| 35 | +PROXYGEN_CONFIG_FILE="/tmp/proxygen-config.json" |
| 36 | + |
| 37 | +echo "=== Starting Proxygen Deployment Process ===" |
| 38 | + |
| 39 | +# Check if required CLI tools are available |
| 40 | +check_dependencies() { |
| 41 | + local deps=("aws" "proxygen" "yq") |
| 42 | + for dep in "${deps[@]}"; do |
| 43 | + if ! command -v "$dep" &> /dev/null; then |
| 44 | + echo "Error: $dep is not installed or not in PATH" |
| 45 | + exit 1 |
| 46 | + fi |
| 47 | + done |
| 48 | + echo "✓ All dependencies available (including Proxygen CLI and yq)" |
| 49 | +} |
| 50 | + |
| 51 | +# Function to retrieve and output secret |
| 52 | +retrieve_secret() { |
| 53 | + local secret_path="$1" |
| 54 | + local output_var="$2" |
| 55 | + |
| 56 | + echo "Retrieving secret: $secret_path" |
| 57 | + |
| 58 | + # Retrieve the secret value |
| 59 | + local secret_value |
| 60 | + if secret_value=$(aws secretsmanager get-secret-value --secret-id "$secret_path" --query 'SecretString' --output text 2>/dev/null); then |
| 61 | + # Export as environment variable |
| 62 | + export "$output_var"="$secret_value" |
| 63 | + |
| 64 | + # Mask the secret in GitHub Actions logs |
| 65 | + echo "::add-mask::$secret_value" |
| 66 | + echo "$output_var=***MASKED***" >> $GITHUB_ENV |
| 67 | + |
| 68 | + echo "✓ Successfully retrieved $output_var" |
| 69 | + else |
| 70 | + echo "Error: Failed to retrieve secret $secret_path" |
| 71 | + exit 1 |
| 72 | + fi |
| 73 | +} |
| 74 | + |
| 75 | +# Function to retrieve private key from S3 |
| 76 | +retrieve_private_key_from_s3() { |
| 77 | + echo "Retrieving private key from S3: s3://$S3_BUCKET/$S3_PRIVATE_KEY_PATH" |
| 78 | + |
| 79 | + if aws s3 cp "s3://$S3_BUCKET/$S3_PRIVATE_KEY_PATH" "$PROXYGEN_PRIVATE_KEY_FILE" 2>/dev/null; then |
| 80 | + # Set proper permissions for private key |
| 81 | + chmod 600 "$PROXYGEN_PRIVATE_KEY_FILE" |
| 82 | + |
| 83 | + # Export path as environment variable |
| 84 | + export PROXYGEN_PRIVATE_KEY="$PROXYGEN_PRIVATE_KEY_FILE" |
| 85 | + echo "PROXYGEN_PRIVATE_KEY=$PROXYGEN_PRIVATE_KEY_FILE" >> $GITHUB_ENV |
| 86 | + |
| 87 | + echo "✓ Successfully retrieved private key from S3" |
| 88 | + else |
| 89 | + echo "Error: Failed to retrieve private key from S3" |
| 90 | + exit 1 |
| 91 | + fi |
| 92 | +} |
| 93 | + |
| 94 | +# Function to set up Proxygen CLI credentials |
| 95 | +setup_proxygen_auth() { |
| 96 | + echo "Setting up Proxygen CLI credentials..." |
| 97 | + |
| 98 | + # Set Proxygen credentials using the credentials set command |
| 99 | + echo "Running: proxygen credentials set private_key_path $PROXYGEN_PRIVATE_KEY key_id $PROXYGEN_KEY_ID client_id $PROXYGEN_CLIENT_ID" |
| 100 | + |
| 101 | + if proxygen credentials set \ |
| 102 | + private_key_path "$PROXYGEN_PRIVATE_KEY" \ |
| 103 | + key_id "$PROXYGEN_KEY_ID" \ |
| 104 | + client_id "$PROXYGEN_CLIENT_ID"; then |
| 105 | + echo "✓ Proxygen CLI credentials configured successfully" |
| 106 | + |
| 107 | + # Verify credentials are set |
| 108 | + echo "Verifying Proxygen credentials..." |
| 109 | + if proxygen credentials show 2>/dev/null; then |
| 110 | + echo "✓ Credentials verification successful" |
| 111 | + else |
| 112 | + echo "⚠ Could not verify credentials, but set command succeeded" |
| 113 | + fi |
| 114 | + else |
| 115 | + echo "Error: Failed to set Proxygen CLI credentials" |
| 116 | + echo "Command failed: proxygen credentials set private_key_path $PROXYGEN_PRIVATE_KEY key_id $PROXYGEN_KEY_ID client_id $PROXYGEN_CLIENT_ID" |
| 117 | + exit 1 |
| 118 | + fi |
| 119 | +} |
| 120 | + |
| 121 | +# Function to preprocess OAS specification file |
| 122 | +preprocess_oaspec() { |
| 123 | + echo "Preprocessing OpenAPI specification file..." |
| 124 | + |
| 125 | + local workspace="${WORKSPACE:-dev}" |
| 126 | + local backup_file="${OASPEC_FILE}.backup" |
| 127 | + |
| 128 | + # Create backup of original file |
| 129 | + if [[ -f "$OASPEC_FILE" ]]; then |
| 130 | + echo "Creating backup: $backup_file" |
| 131 | + cp "$OASPEC_FILE" "$backup_file" |
| 132 | + else |
| 133 | + echo "Error: OpenAPI spec file '$OASPEC_FILE' not found" |
| 134 | + exit 1 |
| 135 | + fi |
| 136 | + |
| 137 | + # Preprocess the OAS file - prefix title with workspace tag |
| 138 | + echo "Prefixing title with workspace tag: [$workspace]" |
| 139 | + |
| 140 | + if yq eval ".info.title = \"[\" + \"$workspace\" + \"] \" + .info.title" "$backup_file" > "$OASPEC_FILE"; then |
| 141 | + echo "✓ Successfully preprocessed OAS file" |
| 142 | + |
| 143 | + # Show the updated title for verification |
| 144 | + local new_title |
| 145 | + if new_title=$(yq eval '.info.title' "$OASPEC_FILE" 2>/dev/null); then |
| 146 | + echo "Updated title: $new_title" |
| 147 | + fi |
| 148 | + else |
| 149 | + echo "Error: Failed to preprocess OAS file" |
| 150 | + echo "Restoring original file..." |
| 151 | + mv "$backup_file" "$OASPEC_FILE" |
| 152 | + exit 1 |
| 153 | + fi |
| 154 | + |
| 155 | + # Optionally show other info that was modified |
| 156 | + echo "OAS file preprocessing completed successfully" |
| 157 | +} |
| 158 | + |
| 159 | +# Function to validate OpenAPI spec file |
| 160 | +validate_oaspec() { |
| 161 | + echo "Validating OpenAPI specification file..." |
| 162 | + |
| 163 | + if [[ ! -f "$OASPEC_FILE" ]]; then |
| 164 | + echo "Error: OpenAPI spec file '$OASPEC_FILE' not found" |
| 165 | + echo "Please ensure the oaspec.yaml file exists in the current directory" |
| 166 | + exit 1 |
| 167 | + fi |
| 168 | + |
| 169 | + # Basic validation of YAML format |
| 170 | + if ! yq eval '.' "$OASPEC_FILE" > /dev/null 2>&1; then |
| 171 | + echo "Error: OpenAPI spec file has YAML syntax issues" |
| 172 | + exit 1 |
| 173 | + fi |
| 174 | + |
| 175 | + # Validate that required OpenAPI fields exist |
| 176 | + local title version |
| 177 | + title=$(yq eval '.info.title // ""' "$OASPEC_FILE" 2>/dev/null) |
| 178 | + version=$(yq eval '.info.version // ""' "$OASPEC_FILE" 2>/dev/null) |
| 179 | + |
| 180 | + if [[ -z "$title" ]]; then |
| 181 | + echo "Warning: OpenAPI spec missing info.title" |
| 182 | + fi |
| 183 | + |
| 184 | + if [[ -z "$version" ]]; then |
| 185 | + echo "Warning: OpenAPI spec missing info.version" |
| 186 | + fi |
| 187 | + |
| 188 | + echo "✓ OpenAPI specification file validated: $OASPEC_FILE" |
| 189 | + [[ -n "$title" ]] && echo " Title: $title" |
| 190 | + [[ -n "$version" ]] && echo " Version: $version" |
| 191 | +} |
| 192 | + |
| 193 | +# Function to deploy to Proxygen using CLI |
| 194 | +deploy_to_proxygen() { |
| 195 | + echo "Starting deployment to Proxygen using CLI..." |
| 196 | + |
| 197 | + # Expand workspace variable if it exists |
| 198 | + local service_name="$PROXYGEN_SERVICE_NAME" |
| 199 | + if [[ "$service_name" == *"<workspace>"* ]]; then |
| 200 | + # Replace <workspace> with actual workspace value if available |
| 201 | + local workspace="${WORKSPACE:-dev}" |
| 202 | + service_name="${service_name/<workspace>/$workspace}" |
| 203 | + echo "Expanded service name: $service_name" |
| 204 | + fi |
| 205 | + |
| 206 | + echo "Deploying with parameters:" |
| 207 | + echo " Instance: $PROXYGEN_INSTANCE" |
| 208 | + echo " Service: $service_name" |
| 209 | + echo " Spec file: $OASPEC_FILE" |
| 210 | + |
| 211 | + # Execute the Proxygen deployment command |
| 212 | + echo "Running: proxygen instance deploy $PROXYGEN_INSTANCE $service_name $OASPEC_FILE" |
| 213 | + |
| 214 | + if proxygen instance deploy "$PROXYGEN_INSTANCE" "$service_name" "$OASPEC_FILE"; then |
| 215 | + echo "✅ Proxygen deployment completed successfully!" |
| 216 | + |
| 217 | + # Get deployment status |
| 218 | + echo "Checking deployment status..." |
| 219 | + if proxygen instance status "$PROXYGEN_INSTANCE" "$service_name"; then |
| 220 | + echo "✓ Deployment status retrieved successfully" |
| 221 | + else |
| 222 | + echo "⚠ Could not retrieve deployment status, but deployment command succeeded" |
| 223 | + fi |
| 224 | + |
| 225 | + else |
| 226 | + echo "❌ Proxygen deployment failed!" |
| 227 | + echo "Command: proxygen instance deploy $PROXYGEN_INSTANCE $service_name $OASPEC_FILE" |
| 228 | + exit 1 |
| 229 | + fi |
| 230 | +} |
| 231 | + |
| 232 | +# Function to list Proxygen deployments (optional verification) |
| 233 | +list_proxygen_deployments() { |
| 234 | + echo "Listing current Proxygen deployments for verification..." |
| 235 | + |
| 236 | + if proxygen instance list "$PROXYGEN_INSTANCE"; then |
| 237 | + echo "✓ Successfully listed deployments" |
| 238 | + else |
| 239 | + echo "⚠ Could not list deployments, but this is non-critical" |
| 240 | + fi |
| 241 | +} |
| 242 | + |
| 243 | +# Cleanup function |
| 244 | +cleanup() { |
| 245 | + echo "Cleaning up temporary files..." |
| 246 | + rm -f "$PROXYGEN_PRIVATE_KEY_FILE" "$PROXYGEN_CONFIG_FILE" |
| 247 | + |
| 248 | + # Clean up OAS backup file |
| 249 | + local backup_file="${OASPEC_FILE}.backup" |
| 250 | + if [[ -f "$backup_file" ]]; then |
| 251 | + rm -f "$backup_file" |
| 252 | + echo "Removed OAS backup file: $backup_file" |
| 253 | + fi |
| 254 | +} |
| 255 | + |
| 256 | +# Set up cleanup trap |
| 257 | +trap cleanup EXIT |
| 258 | + |
| 259 | +# Main execution flow |
| 260 | +main() { |
| 261 | + echo "=== Phase 1: Dependency Check ===" |
| 262 | + check_dependencies |
| 263 | + |
| 264 | + echo -e "\n=== Phase 2: Retrieving Secrets ===" |
| 265 | + for i in "${!SECRETS[@]}"; do |
| 266 | + retrieve_secret "${SECRETS[$i]}" "${OUTPUT_VARS[$i]}" |
| 267 | + done |
| 268 | + |
| 269 | + echo -e "\n=== Phase 3: Retrieving Private Key from S3 ===" |
| 270 | + retrieve_private_key_from_s3 |
| 271 | + |
| 272 | + echo -e "\n=== Phase 4: Preprocessing OpenAPI Specification ===" |
| 273 | + preprocess_oaspec |
| 274 | + |
| 275 | + echo -e "\n=== Phase 5: Validating OpenAPI Specification ===" |
| 276 | + validate_oaspec |
| 277 | + |
| 278 | + echo -e "\n=== Phase 7: Setting Proxygen CLI Credentials ===" |
| 279 | + setup_proxygen_auth |
| 280 | + |
| 281 | + echo -e "\n=== Phase 8: Deploying to Proxygen ===" |
| 282 | + deploy_to_proxygen |
| 283 | + |
| 284 | + echo -e "\n=== Phase 9: Verification ===" |
| 285 | + list_proxygen_deployments |
| 286 | + |
| 287 | + echo -e "\n🎉 Proxygen deployment process completed successfully!" |
| 288 | + echo "Proxy is now deployed and ready to handle requests." |
| 289 | +} |
| 290 | + |
| 291 | +# Run main function |
| 292 | +main "$@" |
0 commit comments