View a markdown version of this page

Get started with Marketplace Buyer using the CLI - AWS SDK Code Examples

There are more AWS SDK examples available in the AWS Doc SDK Examples GitHub repo.

Get started with Marketplace Buyer using the CLI

The following code example shows how to:

  • Use ec2 AuthorizeSecurityGroupIngress

  • Use ec2 CreateKeyPair

  • Use ec2 CreateSecurityGroup

Bash
AWS CLI with Bash script
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials repository.

#!/bin/bash # AWS Marketplace Buyer Getting Started Script # This script demonstrates how to search for products in AWS Marketplace, # launch an EC2 instance with a product AMI, and manage subscriptions. set -euo pipefail # Setup logging with secure permissions LOG_FILE="marketplace-tutorial.log" touch "$LOG_FILE" chmod 600 "$LOG_FILE" exec > >(tee -a "$LOG_FILE") 2>&1 echo "===================================================" echo "AWS Marketplace Buyer Getting Started Tutorial" echo "===================================================" echo "This script will:" echo "1. List available products in AWS Marketplace" echo "2. Create resources needed to launch an EC2 instance" echo "3. Launch an EC2 instance with an Amazon Linux 2 AMI" echo "4. Show how to manage and terminate the instance" echo "===================================================" echo "" # Validate AWS CLI is installed and configured if ! command -v aws &> /dev/null; then echo "ERROR: AWS CLI is not installed. Please install it first." exit 1 fi # Verify AWS credentials are configured if ! aws sts get-caller-identity &> /dev/null; then echo "ERROR: AWS credentials are not configured. Please configure them first." exit 1 fi # Validate jq is installed if ! command -v jq &> /dev/null; then echo "ERROR: jq is not installed. Please install jq for safe JSON parsing." exit 1 fi # Function to safely extract JSON values using jq extract_json_value() { local json=$1 local query=$2 echo "$json" | jq -r "$query" 2>/dev/null || { echo "ERROR: Failed to parse JSON with query: $query" >&2 return 1 } } # Function to validate AWS permissions validate_aws_permissions() { echo "Validating AWS permissions..." local identity identity=$(aws sts get-caller-identity --output json) local account_id account_id=$(extract_json_value "$identity" '.Account') || return 1 local arn arn=$(extract_json_value "$identity" '.Arn') || return 1 echo "AWS Account ID: $account_id" echo "AWS Principal ARN: $arn" echo "Note: This script requires EC2 permissions for key pair, security group, and instance management." echo "" } # Function to clean up resources cleanup_resources() { echo "" echo "===================================================" echo "CLEANING UP RESOURCES" echo "===================================================" if [ -n "${INSTANCE_ID:-}" ]; then echo "Terminating EC2 instance: $INSTANCE_ID" aws ec2 terminate-instances --instance-ids "$INSTANCE_ID" --region "$AWS_REGION" > /dev/null 2>&1 || true echo "Waiting for instance to terminate..." aws ec2 wait instance-terminated --instance-ids "$INSTANCE_ID" --region "$AWS_REGION" 2>/dev/null || true echo "Instance terminated successfully." fi if [ -n "${SECURITY_GROUP_ID:-}" ]; then echo "Waiting before deleting security group..." sleep 5 echo "Deleting security group: $SECURITY_GROUP_ID" aws ec2 delete-security-group --group-id "$SECURITY_GROUP_ID" --region "$AWS_REGION" > /dev/null 2>&1 || true echo "Security group deleted." fi if [ -n "${KEY_NAME:-}" ]; then echo "Deleting key pair: $KEY_NAME" aws ec2 delete-key-pair --key-name "$KEY_NAME" --region "$AWS_REGION" > /dev/null 2>&1 || true # Remove the local key file if it exists with secure deletion if [ -f "${KEY_NAME}.pem" ]; then if command -v shred &> /dev/null; then shred -vfz -n 3 "${KEY_NAME}.pem" 2>/dev/null || rm -f "${KEY_NAME}.pem" else rm -f "${KEY_NAME}.pem" fi echo "Local key file securely deleted." fi fi echo "Cleanup completed." } # Set trap to ensure cleanup on script exit trap cleanup_resources EXIT # Get the current AWS region AWS_REGION=$(aws configure get region || echo "us-east-1") if [ -z "$AWS_REGION" ] || [ "$AWS_REGION" = "None" ]; then AWS_REGION="us-east-1" fi echo "Using AWS Region: $AWS_REGION" echo "" # Validate permissions validate_aws_permissions # Generate random identifier for resource names using cryptographically secure method RANDOM_ID=$(head -c 6 /dev/urandom | od -An -tx1 | tr -d ' ') KEY_NAME="marketplace-key-${RANDOM_ID}" SECURITY_GROUP_NAME="marketplace-sg-${RANDOM_ID}" # Initialize variables to track created resources INSTANCE_ID="" SECURITY_GROUP_ID="" AMI_ID="" # Step 1: List available products in AWS Marketplace echo "Listing available products in AWS Marketplace..." echo "Note: In a real scenario, you would use marketplace-catalog commands to list and search for products." echo "However, this requires specific permissions and product knowledge." echo "" echo "For this tutorial, we'll use a public Amazon Linux 2 AMI instead of an actual marketplace product." echo "This is because subscribing to marketplace products requires accepting terms via the console." echo "" # Step 2: Create a key pair for SSH access echo "Creating key pair: $KEY_NAME" KEY_OUTPUT=$(aws ec2 create-key-pair \ --key-name "$KEY_NAME" \ --region "$AWS_REGION" \ --query 'KeyMaterial' \ --output text) || { echo "ERROR: Failed to create key pair" >&2 exit 1 } # Securely save the key with restricted permissions if ! echo "$KEY_OUTPUT" > "${KEY_NAME}.pem" 2>/dev/null; then echo "ERROR: Failed to write key file ${KEY_NAME}.pem" >&2 exit 1 fi chmod 600 "${KEY_NAME}.pem" || { echo "ERROR: Failed to set permissions on key file" >&2 rm -f "${KEY_NAME}.pem" exit 1 } echo "Key pair created and saved to ${KEY_NAME}.pem with secure permissions (600)" # Step 3: Create a security group echo "Creating security group: $SECURITY_GROUP_NAME" SG_OUTPUT=$(aws ec2 create-security-group \ --group-name "$SECURITY_GROUP_NAME" \ --description "Security group for AWS Marketplace tutorial" \ --region "$AWS_REGION" \ --output json) || { echo "ERROR: Failed to create security group" >&2 exit 1 } # Extract security group ID using jq for safe parsing SECURITY_GROUP_ID=$(extract_json_value "$SG_OUTPUT" '.GroupId') || exit 1 if [ -z "$SECURITY_GROUP_ID" ] || [ "$SECURITY_GROUP_ID" = "null" ]; then echo "ERROR: Could not extract security group ID" >&2 exit 1 fi echo "Security group created with ID: $SECURITY_GROUP_ID" # Add inbound rules for SSH and HTTP in parallel for better performance echo "Configuring security group rules..." { aws ec2 authorize-security-group-ingress \ --group-id "$SECURITY_GROUP_ID" \ --protocol tcp \ --port 22 \ --cidr 0.0.0.0/0 \ --region "$AWS_REGION" > /dev/null 2>&1 } & SSH_PID=$! { aws ec2 authorize-security-group-ingress \ --group-id "$SECURITY_GROUP_ID" \ --protocol tcp \ --port 80 \ --cidr 0.0.0.0/0 \ --region "$AWS_REGION" > /dev/null 2>&1 } & HTTP_PID=$! # Wait for both operations to complete wait $SSH_PID || { echo "ERROR: Failed to add SSH ingress rule" >&2 exit 1 } wait $HTTP_PID || { echo "ERROR: Failed to add HTTP ingress rule" >&2 exit 1 } echo "Security group configured with SSH and HTTP access." echo "WARNING: SSH rule allows access from any IP (0.0.0.0/0). Restrict this in production." echo "WARNING: In a production environment, you should restrict access to specific IP ranges." echo "" # Step 4: Get the latest Amazon Linux 2 AMI ID - Use pagination to optimize costs echo "Getting the latest Amazon Linux 2 AMI ID..." AMI_ID=$(aws ec2 describe-images \ --owners amazon \ --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=state,Values=available" \ --region "$AWS_REGION" \ --query "sort_by(Images, &CreationDate)[-1].ImageId" \ --output text \ --max-results 50) || { echo "ERROR: Failed to describe images" >&2 exit 1 } if [ -z "$AMI_ID" ] || [ "$AMI_ID" = "None" ]; then echo "ERROR: Could not find a suitable AMI ID" >&2 exit 1 fi echo "Using AMI ID: $AMI_ID" echo "Note: In a real marketplace scenario, you would use the AMI ID from your subscribed product." echo "" # Step 5: Launch an EC2 instance with cost optimization echo "Launching EC2 instance with the AMI..." echo "Using t2.micro (eligible for AWS Free Tier if applicable)" INSTANCE_OUTPUT=$(aws ec2 run-instances \ --image-id "$AMI_ID" \ --instance-type t2.micro \ --key-name "$KEY_NAME" \ --security-group-ids "$SECURITY_GROUP_ID" \ --count 1 \ --region "$AWS_REGION" \ --monitoring Enabled=false \ --tag-specifications 'ResourceType=instance,Tags=[{Key=project,Value=doc-smith},{Key=tutorial,Value=marketplace-buyer-gs}]' \ --output json) || { echo "ERROR: Failed to launch instance" >&2 exit 1 } # Extract instance ID using jq for safe parsing INSTANCE_ID=$(extract_json_value "$INSTANCE_OUTPUT" '.Instances[0].InstanceId') || exit 1 if [ -z "$INSTANCE_ID" ] || [ "$INSTANCE_ID" = "null" ]; then echo "ERROR: Could not extract instance ID" >&2 exit 1 fi echo "Instance launched with ID: $INSTANCE_ID" # Wait for the instance to be running echo "Waiting for instance to be in running state..." aws ec2 wait instance-running --instance-ids "$INSTANCE_ID" --region "$AWS_REGION" || { echo "ERROR: Instance failed to reach running state" >&2 exit 1 } echo "Instance is now running." echo "" # Step 6: Get instance details echo "Getting instance details..." INSTANCE_DETAILS=$(aws ec2 describe-instances \ --instance-ids "$INSTANCE_ID" \ --region "$AWS_REGION" \ --output json) || { echo "ERROR: Failed to describe instance" >&2 exit 1 } echo "Instance details:" extract_json_value "$INSTANCE_DETAILS" '.Reservations[0].Instances[0] | {InstanceId, State: .State.Name, PublicDnsName, PrivateIpAddress, LaunchTime, InstanceType}' || exit 1 # Display summary of created resources echo "" echo "===================================================" echo "RESOURCE SUMMARY" echo "===================================================" echo "Key Pair: $KEY_NAME" echo "Security Group: $SECURITY_GROUP_NAME (ID: $SECURITY_GROUP_ID)" echo "EC2 Instance: $INSTANCE_ID" echo "Instance Type: t2.micro (cost-optimized)" echo "AMI ID: $AMI_ID" echo "Region: $AWS_REGION" echo "" echo "COST OPTIMIZATION NOTES:" echo "- t2.micro instances are eligible for AWS Free Tier (750 hours/month for 12 months)" echo "- Detailed monitoring is disabled to reduce costs" echo "- Consider using Spot Instances for non-production workloads" echo "- Review AWS Pricing Calculator: https://calculator.aws/" echo "" echo "To connect to your instance (once it's fully initialized):" echo "ssh -i ${KEY_NAME}.pem ec2-user@<public-dns-name>" echo "Replace <public-dns-name> with the PublicDnsName from the instance details above." echo "" # Auto-confirm cleanup of resources echo "===================================================" echo "CLEANUP CONFIRMATION" echo "===================================================" echo "Cleaning up all created resources..." echo "" echo "Script completed. See $LOG_FILE for the complete log."