This post shows a complete, reproducible flow:
- Install AWS CLI v2 on Ubuntu 24.04 (x86_64)
- Use AWS CloudShell to create a dedicated IAM user
aws-cli-user(programmatic access only) and generate access keys - Configure AWS CLI on Ubuntu with
aws configure(default region:ap-south-1)
Lab context
- OS: Ubuntu 24.04
- Architecture: x86_64
- Default region:
ap-south-1 - Example S3 bucket:
my2-opnsense-imgs(change to your bucket)
- Install AWS CLI v2 on Ubuntu 24.04 (x86_64)
- Install prerequisites
sudo apt update
sudo apt install -y curl unzip
- Download and install AWS CLI v2 (official ZIP)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip -q awscliv2.zip
sudo ./aws/install
- Verify
aws --version
which aws
- Create IAM user
aws-cli-userin AWS (CloudShell)
Important: The following CloudShell script is for this post’s use case (upload a large RAW image to a specific S3 bucket, then run VM Import/Export to create an AMI).
If your use case is different (only S3, only EC2, CloudWatch automation, Route53, etc.), you should change the permissions to match what you actually need.
What this script does (our case)
- Creates IAM user:
aws-cli-user - Creates a customer-managed policy that allows the following:
- Allow uploading large files to one S3 bucket
- Allow VM Import/Export APIs (import-snapshot, describe tasks)
- Allow registering an AMI (register-image)
- Allow creating/updating the
vmimportIAM role (one-time setup, done separately) - Allow passing the
vmimportrole to the VM Import/Export service (vmie.amazonaws.com)
- Generates an access key and saves it to
aws-cli-user.access-key.json
Open CloudShell
AWS Console → open CloudShell (top-right terminal icon).
Run the script
USER="aws-cli-user"
BUCKET="my2-opnsense-imgs"
ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
POLICY_NAME="AwsCliUserVmImportS3"
# 1) Create IAM user (if not exists)
aws iam get-user --user-name "$USER" >/dev/null 2>&1 || aws iam create-user --user-name "$USER" >/dev/null
echo "IAM user ready: $USER"
# 2) Write policy document (THIS IS FOR OUR USE CASE; customize for yours)
cat > "/tmp/${POLICY_NAME}.json" <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3UploadRawImage",
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket",
"s3:ListBucketMultipartUploads"
],
"Resource": "arn:aws:s3:::${BUCKET}"
},
{
"Sid": "S3PutObjectMultipart",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:AbortMultipartUpload",
"s3:ListMultipartUploadParts"
],
"Resource": "arn:aws:s3:::${BUCKET}/*"
},
{
"Sid": "EC2VmImportAndRegisterAmi",
"Effect": "Allow",
"Action": [
"ec2:ImportSnapshot",
"ec2:DescribeImportSnapshotTasks",
"ec2:DescribeSnapshots",
"ec2:RegisterImage",
"ec2:DescribeImages",
"ec2:Describe*"
],
"Resource": "*"
},
{
"Sid": "CreateAndManageVmImportRole",
"Effect": "Allow",
"Action": [
"iam:CreateRole",
"iam:PutRolePolicy",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:ListRolePolicies",
"iam:UpdateAssumeRolePolicy"
],
"Resource": "*"
},
{
"Sid": "PassVmImportRoleToVmie",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::${ACCOUNT_ID}:role/vmimport",
"Condition": {
"StringEquals": {
"iam:PassedToService": "vmie.amazonaws.com"
}
}
}
]
}
EOF
# 3) Create customer-managed policy (if not exists)
POLICY_ARN="$(aws iam list-policies --scope Local \
--query "Policies[?PolicyName=='${POLICY_NAME}'].Arn | [0]" --output text)"
if [ "$POLICY_ARN" = "None" ] || [ -z "$POLICY_ARN" ]; then
POLICY_ARN="$(aws iam create-policy \
--policy-name "$POLICY_NAME" \
--policy-document "file:///tmp/${POLICY_NAME}.json" \
--query 'Policy.Arn' --output text)"
echo "Created policy: $POLICY_ARN"
else
echo "Policy already exists: $POLICY_ARN"
fi
# 4) Attach policy to user
aws iam attach-user-policy --user-name "$USER" --policy-arn "$POLICY_ARN"
echo "Attached policy to user."
# 5) Create access key (SECRET shown once!) and save to a file
aws iam create-access-key --user-name "$USER" \
--query 'AccessKey.{AccessKeyId:AccessKeyId,SecretAccessKey:SecretAccessKey}' \
--output json > "${USER}.access-key.json"
echo "Access key saved to: ${USER}.access-key.json"
echo "IMPORTANT: Download it and delete it from CloudShell afterwards."
Download and delete the access key file
Download aws-cli-user.access-key.json from CloudShell, then remove it:
rm -f aws-cli-user.access-key.json
- Configure AWS CLI on Ubuntu (
aws configure)
On Ubuntu, run:
aws configure
Enter:
- AWS Access Key ID: from
aws-cli-user.access-key.json - AWS Secret Access Key: from
aws-cli-user.access-key.json - Default region name:
ap-south-1 - Default output format:
json
Confirm your config:
ls -la ~/.aws
cat ~/.aws/credentials
cat ~/.aws/config
Test credentials:
aws sts get-caller-identity
Did this guide save you time?
Support this site