Open-sourced my dtools CLI

This commit is contained in:
2025-11-24 15:32:30 -07:00
parent 3cff748a76
commit 8df7811c39
254 changed files with 40015 additions and 2 deletions
+135
View File
@@ -0,0 +1,135 @@
name: aws
help: AWS commands
group: AWS
expose: always
dependencies:
aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'
commands:
- name: login
help: |-
Log in to AWS using SSO.
This command will also set your 'AWS_PROFILE' and 'AWS_REGION' environment variables.
It will also export temporary credentials to your environment with the 'AWS_ACCESS_KEY_ID' and 'AWS_SECRET_ACCESS_KEY' environment variables.
This command is essentially a shorthand for the following commands:
dtools aws profile <PROFILE>
dtools aws region <REGION>
dtools aws login
dtools aws export-sso-creds
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
examples:
- dtools aws login -p prod -r us-east-1
- |-
# When the 'AWS_PROFILE' and 'AWS_REGION' environment variables are already
# set
dtools aws login
- name: console
help: Open the AWS console in your default browser using the current AWS_REGION and AWS_PROFILE
dependencies:
wmctrl: Install with 'sudo apt-get install wmctrl'
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --service
short: -s
help: The AWS service to open the console to
arg: service
completions:
- >-
$(python -c $'import boto3\nfor service in boto3.Session().get_available_services(): print(service)' | grep -v 'codestar\|honeycode\|mobile\|worklink')
- name: shell
help: Drop into an interactive AWS CLI shell with auto-completion
- name: profile
help: Change AWS profile
completions:
- $(cat ~/.aws/config | awk '/\[profile*/ { print substr($2, 1, length($2)-1); }')
args:
- name: profile
required: true
help: The AWS profile to use, corresponding profiles in your ~/.aws/config
validate: aws_profile_exists
examples:
- dtools aws profile prod
- name: region
help: Change AWS region
args:
- name: region
required: true
help: The AWS region to use
allowed:
import: src/components/aws/allowed_regions.yml
examples:
- dtools aws region us-east-1
- name: toggle-auto-prompt
help: Toggle the AWS CLI auto prompt
- name: export-sso-creds
help: |-
Exports SSO credentials to environment variables for use with AWS SDKs
This includes all of the following variables:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_SESSION_TOKEN
AWS_CREDENTIAL_EXPIRATION
AWS_REGION
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- name: generate-sso-profiles
help: |-
Fetch all AWS accounts via AWS SSO, and generate the profiles for CLI connectivity.
In the event that the script fails automation when selecting an account to use for the basic setup,
you can manually perform this first step by running 'aws configure sso', use 'https://d-123456789ab.awsapps.com/start'
as the SSO Start URL, and use any account with any settings. Then you can run this command again for it
to work properly.
dependencies:
jq: Install with 'brew install jq'
flags:
- long: --backup
help: Create a backup of the previous AWS config
- long: --default-cli-region
short: -d
arg: default-cli-region
help: |-
The default CLI region for each profile.
Defaults to using the same region as the provided SSO region
allowed:
import: src/components/aws/allowed_regions.yml
- long: --sso-region
short: -r
arg: sso-region
required: true
help: The region for SSO accounts
allowed:
import: src/components/aws/allowed_regions.yml
- long: --sso-start-url
short: -u
arg: sso-start-url
required: true
help: The start URL for SSO authentication
examples:
- dtools aws generate-sso-profiles -u https://d-123456789ab.awsapps.com/start -r us-east-1
- import: src/commands/aws/ec2/ec2_commands.yml
- import: src/commands/aws/ssm/ssm_commands.yml
- import: src/commands/aws/secretsmanager/secretsmanager_commands.yml
- import: src/commands/aws/logs/logs_commands.yml
- import: src/commands/aws/rds/rds_commands.yml
+438
View File
@@ -0,0 +1,438 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
# shellcheck disable=SC2155
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare service="${args[--service]}"
declare base_aws_url="https://console.aws.amazon.com"
validate-or-refresh-aws-auth
if ! [[ -f /usr/local/bin/aws_console ]]; then
cat <<EOF >> aws_console
#!/usr/bin/env python3
import sys
import json
import webbrowser
import urllib.parse
import os
import argparse
from typing import Optional
import time
import pyautogui
import requests
import boto3
def get_logout_url(region: Optional[str] = None):
urllib.parse.quote_plus(
"https://aws.amazon.com/premiumsupport/knowledge-center/sign-out-account/?from_aws_sso_util_logout"
)
if not region or region == "us-east-1":
return "https://signin.aws.amazon.com/oauth?Action=logout&redirect_uri="
if region == "us-gov-east-1":
return "https://us-gov-east-1.signin.amazonaws-us-gov.com/oauth?Action=logout"
if region == "us-gov-west-1":
return "https://signin.amazonaws-us-gov.com/oauth?Action=logout"
return f"https://{region}.signin.aws.amazon.com/oauth?Action=logout&redirect_uri="
def get_federation_endpoint(region: Optional[str] = None):
if not region or region == "us-east-1":
return "https://signin.aws.amazon.com/federation"
if region == "us-gov-east-1":
return "https://us-gov-east-1.signin.amazonaws-us-gov.com/federation"
if region == "us-gov-west-1":
return "https://signin.amazonaws-us-gov.com/federation"
return f"https://{region}.signin.aws.amazon.com/federation"
def get_destination_base_url(region: Optional[str] = None):
if region and region.startswith("us-gov-"):
return "https://console.amazonaws-us-gov.com"
if region:
return f"https://{region}.console.aws.amazon.com/"
return "https://console.aws.amazon.com/"
def get_destination(
path: Optional[str] = None,
region: Optional[str] = None,
override_region_in_destination: bool = False,
):
base = get_destination_base_url(region=region)
if path:
stripped_path_parts = urllib.parse.urlsplit(path)[2:]
path = urllib.parse.urlunsplit(("", "") + stripped_path_parts)
url = urllib.parse.urljoin(base, path)
else:
url = base
if not region:
return url
parts = list(urllib.parse.urlsplit(url))
query_params = urllib.parse.parse_qsl(parts[3])
if override_region_in_destination:
query_params = [(k, v) for k, v in query_params if k != "region"]
query_params.append(("region", region))
elif not any(k == "region" for k, _ in query_params):
query_params.append(("region", region))
query_str = urllib.parse.urlencode(query_params)
parts[3] = query_str
url = urllib.parse.urlunsplit(parts)
return url
def DurationType(value):
value = int(value)
if 15 < value < 720:
raise ValueError("Duration must be between 15 and 720 minutes (inclusive)")
return value
def main():
parser = argparse.ArgumentParser(description="Launch the AWS console")
parser.add_argument("--profile", metavar="PROFILE_NAME", help="A config profile to use")
parser.add_argument("--region", metavar="REGION", help="The AWS region")
parser.add_argument(
"--destination",
dest="destination_path",
metavar="PATH",
help="Console URL path to go to",
)
override_region_group = parser.add_mutually_exclusive_group()
override_region_group.add_argument("--override-region-in-destination", action="store_true")
override_region_group.add_argument(
"--keep-region-in-destination",
dest="override_region_in_destination",
action="store_false",
)
open_group = parser.add_mutually_exclusive_group()
open_group.add_argument(
"--open",
dest="open_url",
action="store_true",
default=None,
help="Open the login URL in a browser (the default)",
)
open_group.add_argument(
"--no-open",
dest="open_url",
action="store_false",
help="Do not open the login URL",
)
print_group = parser.add_mutually_exclusive_group()
print_group.add_argument(
"--print",
dest="print_url",
action="store_true",
default=None,
help="Print the login URL",
)
print_group.add_argument(
"--no-print",
dest="print_url",
action="store_false",
help="Do not print the login URL",
)
parser.add_argument(
"--duration",
metavar="MINUTES",
type=DurationType,
help="The session duration in minutes",
)
logout_first_group = parser.add_mutually_exclusive_group()
logout_first_group.add_argument(
"--logout-first",
"-l",
action="store_true",
default=True,
help="Open a logout page first",
)
logout_first_group.add_argument(
"--no-logout-first",
dest="logout_first",
action="store_false",
help="Do not open a logout page first",
)
args = parser.parse_args()
if args.open_url is None:
args.open_url = True
logout_first_from_env = False
if args.logout_first is None:
args.logout_first = os.environ.get("AWS_CONSOLE_LOGOUT_FIRST", "").lower() in [
"true",
"1",
]
logout_first_from_env = True
if args.logout_first and not args.open_url:
if logout_first_from_env:
logout_first_value = os.environ["AWS_CONSOLE_LOGOUT_FIRST"]
raise parser.exit(f"AWS_CONSOLE_LOGOUT_FIRST={logout_first_value} requires --open")
else:
raise parser.exit("--logout-first requires --open")
session = boto3.Session(profile_name=args.profile)
if not args.region:
args.region = session.region_name or os.environ.get("AWS_CONSOLE_DEFAULT_REGION")
if not args.destination_path:
args.destination_path = session._session.get_scoped_config().get("web_console_destination") or os.environ.get(
"AWS_CONSOLE_DEFAULT_DESTINATION"
)
credentials = session.get_credentials()
if not credentials:
parser.exit("Could not find credentials")
federation_endpoint = get_federation_endpoint(region=args.region)
issuer = os.environ.get("AWS_CONSOLE_DEFAULT_ISSUER")
destination = get_destination(
path=args.destination_path,
region=args.region,
override_region_in_destination=args.override_region_in_destination,
)
launch_console(
session=session,
federation_endpoint=federation_endpoint,
destination=destination,
region=args.region,
open_url=args.open_url,
print_url=args.print_url,
duration=args.duration,
logout_first=args.logout_first,
issuer=issuer,
)
def launch_console(
session: boto3.Session,
federation_endpoint: str,
destination: str,
region: Optional[str] = None,
open_url: Optional[bool] = None,
print_url: Optional[bool] = None,
duration: Optional[int] = None,
logout_first: Optional[bool] = None,
issuer: Optional[str] = None,
):
if not issuer:
issuer = "aws_console_launcher.py"
read_only_credentials = session.get_credentials().get_frozen_credentials()
session_data = {
"sessionId": read_only_credentials.access_key,
"sessionKey": read_only_credentials.secret_key,
"sessionToken": read_only_credentials.token,
}
get_signin_token_payload = {
"Action": "getSigninToken",
"Session": json.dumps(session_data),
}
if duration is not None:
get_signin_token_payload["SessionDuration"] = duration * 60
response = requests.post(federation_endpoint, data=get_signin_token_payload)
if response.status_code != 200:
print("Could not get signin token", file=sys.stderr)
print(response.status_code + "\n" + response.text, file=sys.stderr)
sys.exit(2)
token = response.json()["SigninToken"]
get_login_url_params = {
"Action": "login",
"Issuer": issuer,
"Destination": destination,
"SigninToken": token,
}
request = requests.Request(method="GET", url=federation_endpoint, params=get_login_url_params)
prepared_request = request.prepare()
login_url = prepared_request.url
if print_url:
print(login_url)
if open_url:
if logout_first:
logout_url = get_logout_url(region=region)
webbrowser.open(logout_url, autoraise=False)
time.sleep(1)
os.system('wmctrl -a "Manage AWS Resources"')
pyautogui.hotkey("ctrl", "w")
webbrowser.open(login_url)
if __name__ == "__main__":
main()
EOF
chmod +x aws_console
sudo mv aws_console /usr/local/bin/
fi
declare -A service_aliases=(
[accessanalyzer]="access-analyzer"
[alexaforbusiness]="a4b"
[apigatewaymanagementapi]="apigateway"
[apigatewayv2]="apigateway"
[appconfig]="systems-manager/appconfig"
[application-autoscaling]="awsautoscaling"
[application-insights]="cloudwatch/home?#settings:AppInsightsSettings"
[appstream]="appstream2"
[autoscaling]="ec2/home#AutoScalingGroups:"
[autoscaling-plans]="awsautoscaling/home#dashboard"
[budgets]="billing/home#/budgets"
[ce]="costmanagement/home#/cost-explorer"
[chime]="chime-sdk"
[clouddirectory]="directoryservicev2/home#!/cloud-directories"
[cloudhsmv2]="cloudhsm"
[cloudsearchdomain]="cloudsearch"
[codeartifact]="codesuite/codeartifact"
[codeguru-reviewer]="codeguru/reviewer"
[codeguruprofiler]="codeguru/profiler"
[cognito-identity]="iamv2/home#/identity_providers"
[cognito-idp]="cognito/v2/idp"
[cognito-sync]="appsync"
[connectparticipant]="connect"
[cur]="billing/home#/reports"
[dax]="dynamodbv2/home#dax-clusters"
[directconnect]="directconnect/v2/home"
[dlm]="ec2/home#Lifecycle"
[dms]="dms/v2"
[ds]="directoryservicev2"
[dynamodbstreams]="dynamodbv2"
[ebs]="ec2/home#Volumes:"
[ec2-instance-connect]="ec2/home#Instances:"
[elastic-inference]="sagemaker"
[elb]="ec2/home#LoadBalancers:"
[elbv2]="ec2/home#LoadBalancers:"
[es]="aos/home"
[fms]="wafv2/fmsv2/home"
[forecastquery]="forecast"
[glacier]="glacier/home"
[globalaccelerator]="globalaccelerattor/home"
[identitystore]="singlesignon"
[iot-data]="iot"
[iot-jobs-data]="iot/home#/jobhub"
[iot1click-devices]="iot/home#/thinghub"
[iot1click-projects]="iot"
[iotevents-data]="iotevents/home#/input"
[iotsecuretunneling]="iot/home#/tunnelhub"
[iotthingsgraph]="iot/home#/thinghub"
[kafka]="msk"
[kinesis-video-archived-media]="kinesisvideo/home"
[kinesis-video-media]="kinesisvideo/home"
[kinesis-video-signaling]="kinesisvideo/home#/signalingChannels"
[kinesisanalyticsv2]="flink"
[kinesisvideo]="kinesisvideo/home"
[lex-models]="lexv2/home#bots"
[lex-runtime]="lexv2/home#bots"
[lightsail]="ls"
[logs]="cloudwatch/home#logsV2:"
[macie2]="macie"
[marketplace-catalog]="marketplace/home#/search!mpSearch/search"
[marketplace-entitlement]="marketplace"
[marketplacecommerceanalytics]="marketplace/home#/vendor-insights"
[mediapackage-vod]="mediapackagevod"
[mediastore-data]="mediastore"
[meteringmarketplace]="marketplace"
[mgh]="migrationhub"
[migrationhub-config]="migrationhub"
[mq]="amazon-mq"
[networkmanager]="networkmanager/home"
[opsworkscm]="opsworks"
[personalize]="personalize/home"
[personalize-events]="personalize/home"
[personalize-runtime]="personalize/home"
[pi]="rds/home#performance-insights"
[pinpoint]="pinpointv2"
[pinpoint-email]="pinpoint/home#/email-account-settings/overview"
[pinpoint-sms-voice]="pinpoint"
[qldb-session]="qldb"
[ram]="ram/home"
[rds-data]="rds/home#query-editor:"
[redshift-data]="redshiftv2/home#/query-editor:"
[resourcegroupstaggingapi]="resource-groups"
[route53domains]="route53/domains"
[s3control]="s3"
[sagemaker-a2i-runtime]="sagemaker/groundtruth#/a2i"
[sagemaker-runtime]="sagemaker"
[savingsplans]="costmanagement/home#/savings-plans/overview"
[schemas]="events/home#/schemas"
[sdb]="simpledb"
[service-quotas]="servicequotas"
[servicediscovery]="cloudmap"
[shield]="wafv2/shieldv2"
[sms]="mgn/home"
[snowball]="snowfamily"
[ssm]="systems-manager"
[sso]="singlesignon"
[sso-admin]="singlesignon"
[sso-oidc]="singlesignon"
[stepfunctions]="states"
[sts]="iam"
[swf]="swf/v2"
[translate]="translate/home"
[waf]="wafv2/homev2"
[waf-regional]="wafv2/homev2"
[wafv2]="wafv2/homev2"
[workdocs]="zocalo"
[workmailmessageflow]="workmail"
[xray]="xray/home"
)
case "$service" in
"pricing")
firefox "https://calculator.aws" > /dev/null 2>&1
exit
;;
"mturk")
firefox "https://mturk.com" > /dev/null 2>&1
exit
;;
"quicksight")
firefox "quicksight.aws.amazon.com" > /dev/null 2>&1
exit
;;
*)
if [[ -v service_aliases["$service"] ]]; then
service_url="${base_aws_url}/${service_aliases[$service]}"
else
service_url="${base_aws_url}/${service}"
fi
;;
esac
aws_console --profile "$aws_profile" --region "$aws_region" --destination "$service_url"
+28
View File
@@ -0,0 +1,28 @@
name: ec2
help: EC2 commands
group: EC2
expose: always
dependencies:
aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'
jq: Install using 'brew install jq'
commands:
- name: list-instances
help: List all EC2 instances in the account
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --detailed
help: Output the list of all instances in the full detailed format
conflicts: [--filter]
- long: --filter
short: -f
arg: filter
help: Filter the output to only show the specified information
repeatable: true
unique: true
allowed:
import: src/components/aws/ec2/allowed_list_instance_filters.yml
conflicts: [--detailed]
+49
View File
@@ -0,0 +1,49 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare detailed_format="${args[--detailed]}"
eval "filters=(${args[--filter]:-})"
validate-or-refresh-aws-auth
spinny-start
# shellcheck disable=SC2155
declare instances=$(aws ec2 describe-instances --profile "$aws_profile" --region "$aws_region")
spinny-stop
# Must be ordered by non-nested fields first
declare -A instance_field_mappings=(
[instance-id]='InstanceId'
[instance-type]='InstanceType'
[private-dns-name]='PrivateDnsName'
[private-ip-address]='PrivateIpAddress'
[public-dns-name]='PublicDnsName'
[subnet-id]='SubnetId'
[vpc-id]='VpcId'
[tags]='Tags'
[launch-time]='LaunchTime'
[architecture]='Architecture'
[instance-profile]='IamInstanceProfile'
[security-groups]='SecurityGroups'
[availability-zone]='"AvailabilityZone": .Placement.AvailabilityZone'
[state]='"State": .State.Name'
[os]='"OS": .PlatformDetails'
)
if [[ $detailed_format == 1 ]]; then
jq . <<< "$instances"
elif [[ -v filters[@] ]]; then
declare object_def=""
for filter_name in "${!instance_field_mappings[@]}"; do
# shellcheck disable=SC2154
if printf '%s\0' "${filters[@]}" | grep -Fxqz -- "$filter_name"; then
object_def+="${instance_field_mappings[$filter_name]}, "
fi
done
jq '.Reservations[].Instances[] | { '"$object_def"' }' <<< "$instances"
else
jq '.Reservations[].Instances[] | pick(.InstanceId, .PrivateDnsName, .PrivateIpAdress, .PublicDnsName, .SubnetId, .VpcId, .Tags)' <<< "$instances"
fi
+7
View File
@@ -0,0 +1,7 @@
# shellcheck disable=SC2155
declare aws_profile="$(get-aws-profile)"
declare aws_region="$(get-aws-region)"
validate-or-refresh-aws-auth
bash -c "eval \"\$(aws --profile $aws_profile --region $aws_region configure export-credentials --format env)\"; export AWS_REGION=$aws_region; exec bash"
+123
View File
@@ -0,0 +1,123 @@
# shellcheck disable=SC2154
declare aws_region="${args[--default-cli-region]}"
declare sso_region="${args[--sso-region]}"
declare sso_start_url="${args[--sso-start-url]}"
declare backup="${args[--backup]}"
set -e
if [[ -z $aws_region ]]; then
aws_region="$sso_region"
fi
export AWS_REGION=$aws_region
write-profile-to-config() {
profileName=$1
ssoStartUrl=$2
ssoRegion=$3
ssoAccountId=$4
ssoRoleName=$5
defaultRegion=$6
blue_bold "Creating profile $profileName"
cat <<-EOF >> "$HOME"/.aws/config
[profile $profileName]
sso_start_url = $ssoStartUrl
sso_region = $ssoRegion
sso_account_id = $ssoAccountId
sso_role_name = $ssoRoleName
region = $defaultRegion
EOF
}
if [[ $backup == 1 ]]; then
yellow "Backing up old AWS config"
mv "$HOME"/.aws/config "$HOME"/.aws/config.bak
fi
login() {
ssoLoggedIn=$(find "$HOME/.aws/sso/cache" -type f ! -name "botocore*" -exec jq -r '.accessToken | select(. != null)' {} \; | wc -l)
if [[ $ssoLoggedIn == 0 || ! -f "$HOME"/.aws/config ]]; then
yellow_bold "You must first be logged into AWS with at least one profile. Logging in now..."
[[ -f "$HOME"/.aws/config ]] || touch "$HOME"/.aws/config
export AWS_PROFILE=''
export AWS_REGION=''
/usr/bin/expect<<-EOF
set force_conservative 1
set timeout 120
match_max 100000
spawn aws configure sso
expect "SSO session name (Recommended):"
send -- "session\r"
expect "SSO start URL"
send -- "$sso_start_url\\r"
expect "SSO region"
send -- "$sso_region\r"
expect {
"SSO registration scopes" {
send "sso:account:access\\r"
exp_continue
}
-re {(.*)accounts available to you(.*)} {
send "\\r"
exp_continue
}
-re {(.*)roles available to you(.*)} {
send "\\r"
exp_continue
}
"CLI default client Region"
}
send "\r\r\r\r"
expect eof
EOF
elif ! (aws sts get-caller-identity > /dev/null 2>&1); then
red_bold "You must be logged into AWS before running this script."
yellow "Logging in via SSO. Follow the steps in the opened browser to log in."
profiles=$(awk '/\[profile*/ { print substr($2, 1, length($2)-1); }' ~/.aws/config | tail -1)
if ! aws sso login --profile "${profiles[0]}"; then
red_bold "Unable to login. Please try again."
exit 1
fi
green "Logged in!"
fi
blue "Fetching SSO access token"
profiles=$(awk '/\[profile*/ { print substr($2, 1, length($2)-1); }' ~/.aws/config | tail -1)
# shellcheck disable=SC2227
ACCESS_TOKEN=$(find "$HOME/.aws/sso/cache" -type f ! -name 'botocore*' -exec jq -r '.accessToken | select(. != null)' {} 2>/dev/null \; | tail -1)
}
login
if ! (aws sso list-accounts --profile "${profiles[0]}" --region "$aws_region" --access-token "$ACCESS_TOKEN" --output json > /dev/null 2>&1); then
red "Unable to use existing SSO access token. Wiping tokens and generating new tokens..."
rm "$HOME"/.aws/sso/cache/*.json
login
fi
aws sso list-accounts --profile "${profiles[0]}" --region "$aws_region" --access-token "$ACCESS_TOKEN" --output json | jq '.accountList[]' -rc | while read -r account; do
declare accountId
declare accountName
accountId="$(echo "$account" | jq -rc '.accountId')"
accountName="$(echo "$account" | jq -rc '.accountName | ascii_downcase | gsub(" "; "-")')"
aws sso list-account-roles --profile "${profiles[0]}" --region "$aws_region" --access-token "$ACCESS_TOKEN" --output json --account-id "$accountId" | jq '.roleList[].roleName' -rc | while read -r roleName; do
declare profileName
profileName="$accountName-$roleName"
if ! (grep -q "$profileName" ~/.aws/config); then
blue "Creating profiles for account $accountName"
write-profile-to-config "$accountName-$roleName" "$sso_start_url" "$sso_region" "$accountId" "$roleName" "$aws_region"
fi
done
done
green_bold "Successfully generated profiles from AWS SSO!"
+15
View File
@@ -0,0 +1,15 @@
# shellcheck disable=SC2155
declare aws_profile="$(get-aws-profile)"
declare aws_region="$(get-aws-region)"
validate-or-refresh-aws-auth
if ( grep "AWS_PROFILE" ~/.bashrc > /dev/null 2>&1 ); then
sed -i "/^AWS_PROFILE=/c\export AWS_PROFILE=$aws_profile" ~/.bashrc
fi
if ( grep "AWS_REGION" ~/.bashrc > /dev/null 2>&1 ); then
sed -i "/^AWS_REGION=/c\export AWS_REGION=$aws_region" ~/.bashrc
fi
bash -c "export AWS_PROFILE=$aws_profile; export AWS_REGION=$aws_region; eval \"\$(aws configure export-credentials --format env --profile $aws_profile)\"; exec bash"
+15
View File
@@ -0,0 +1,15 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare detailed_format="${args[--detailed]}"
validate-or-refresh-aws-auth
declare log_groups=$(aws logs describe-log-groups --profile "$aws_profile" --region "$aws_region")
if [[ $detailed_format == 1 ]]; then
jq . <<< "$log_groups"
else
jq -r '.logGroups[].logGroupName' <<< "$log_groups"
fi
+77
View File
@@ -0,0 +1,77 @@
name: logs
help: AWS Logs commands
group: Logs
expose: always
dependencies:
aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'
lnav: Install with 'brew install lnav'
unbuffer: Install with 'brew install expect'
commands:
- name: list-log-groups
help: List all of the log groups in CloudWatch
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --detailed
help: Output the list of all CloudWatch log groups in the full detailed format
- name: tail-log-group
help: Tails the specified CloudWatch log group
dependencies:
lnav: Install with 'brew install lnav'
unbuffer: Install with 'brew install expect'
args:
- name: log-group
required: true
help: The name of the log group to tail
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --since
short: -s
arg: since
default: 10m
help: The time to start tailing the log group from
validate: relative_since_time_format
completions:
- $(for e in s m h d w; do echo "${2//[!0-9]/}${e}"; done)
- long: --verbose
short: -v
help: Show verbose log output
- long: --stdout
help: Show the log output in stdout
examples:
- dtools aws tail-log-group /aws/lambda/test-lambda-1
- name: query-log-groups
help: Query one or more log groups with the given query string
filters:
- profile_and_region_variables_set_with_flags
args:
- name: query
help: The query string to query the log groups for
default: fields @timestamp, @message | sort @timestamp desc
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --log-group-name
short: -l
help: The names of a log group to query for
repeatable: true
arg: log_group_name
required: true
- long: --start-time
help: The start time for the query (ISO 8601)
arg: start_time
required: true
- long: --end-time
help: The end time for the query (ISO 8601)
arg: end_time
required: true
examples:
- dtools aws logs query-log-groups 'correlationId' --start-time '2025-03-18T15:00:00Z' --end-time '2025-03-18T16:00:00Z' --log-group-name caerus-api-log-group -l /aws/lambda/revisit-prod-revisit-core-historical-schedules-s3-writer-lambda
+43
View File
@@ -0,0 +1,43 @@
# shellcheck disable=SC2155
export aws_region="$(get-aws-region)"
# shellcheck disable=SC2155
export aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
export query="${args[query]}"
# shellcheck disable=SC2154
export start_time="${args[--start-time]}"
# shellcheck disable=SC2154
export end_time="${args[--end-time]}"
eval "log_group_names=(${args[--log-group-name]})"
export log_file=$(mktemp)
trap "rm -f $log_file" EXIT
validate-or-refresh-aws-auth
write-logs() {
log_group="$1"
query_id="$(aws logs start-query \
--log-group-names "$log_group" \
--start-time "$(date -d "$start_time" +"%s%3N")" \
--end-time "$(date -d "$end_time" +"%s%3N")" \
--query-string "$query" \
--profile "$aws_profile" \
--region "$aws_region" \
--output json | jq -r '.queryId // empty')"
if [[ -z $query_id ]]; then
red "Unable to start query for log group: '$log_group'"
exit 1
fi
until [[ "$(aws logs get-query-results --query-id "$query_id" --profile "$aws_profile" --region "$aws_region" --query status --output text)" == "Complete" ]]; do
sleep 1
done
aws logs get-query-results --query-id "$query_id" --profile "$aws_profile" --region "$aws_region" | tr -d '\000-\037' | jq -r --arg log_group "$log_group" '.results[] | { "timestamp": (.[] | select(.field == "@timestamp") | .value), "message": (.[] | select(.field == "@message") | .value), "logGroup": $log_group }' >> "$log_file"
}
export -f write-logs
parallel -j8 write-logs {} ::: ${log_group_names[*]}
jq -rs '. | sort_by(.timestamp) | map("\(.timestamp) \(.logGroup) \(.message)")[]' "$log_file" | sed '/^$/d'
+31
View File
@@ -0,0 +1,31 @@
# shellcheck disable=SC2155
declare aws_profile="$(get-aws-profile)"
declare aws_region="$(get-aws-region)"
declare temp_log_file="$(mktemp)"
set -e
# shellcheck disable=SC2064
# 'kill -- -$$' also kills the entire process group whose ID is $$
# So this means that this will also kill all subprocesses started by
# this script
trap "rm -f $temp_log_file && kill -- -$$" EXIT
validate-or-refresh-aws-auth
# shellcheck disable=SC2154
unbuffer aws --profile "$aws_profile" --region "$aws_region" logs tail "${args[log-group]}" --follow --format short --no-cli-auto-prompt --since "${args[--since]}" >> "$temp_log_file" &
if [[ ${args[--verbose]} == 1 ]]; then
if [[ ${args[--stdout]} == 1 ]]; then
tail -f "$temp_log_file"
else
lnav "$temp_log_file"
fi
elif [[ ${args[--stdout]} == 1 ]]; then
tail -f "$temp_log_file" |\
awk '{$1=""; gsub(/^[ \t]+/, "", $0); if ($0 !~ /^END|^REPORT|^START/) { print }}'
else
tail -f "$temp_log_file" |\
awk '{$1=""; gsub(/^[ \t]+/, "", $0); if ($0 !~ /^END|^REPORT|^START/) { print }}' |\
lnav
fi
+11
View File
@@ -0,0 +1,11 @@
set-aws-profile() {
if ( grep -q "AWS_PROFILE" ~/.bashrc ); then
sed -i "/^AWS_PROFILE=/c\export AWS_PROFILE=$1" ~/.bashrc
fi
bash -c "export AWS_PROFILE=$1; exec bash"
}
declare profile
# shellcheck disable=SC2154
set-aws-profile "${args[profile]}"
@@ -0,0 +1,16 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
# shellcheck disable=SC2155
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare db_instance="${args[db_instance]}"
validate-or-refresh-aws-auth
spinny-start
aws --profile "$aws_profile" \
--region "$aws_region" \
rds describe-db-instances \
--query DBInstances[] |\
jq -r '.[] | select(.DBInstanceIdentifier == "'"$db_instance"'") | .Endpoint | {"address": .Address, "port": .Port}'
spinny-stop
+14
View File
@@ -0,0 +1,14 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
# shellcheck disable=SC2155
declare aws_profile="$(get-aws-profile)"
validate-or-refresh-aws-auth
spinny-start
aws --profile "$aws_profile" \
--region "$aws_region" \
rds describe-db-instances \
--query 'DBInstances[].DBInstanceIdentifier' \
--output text
spinny-stop
+28
View File
@@ -0,0 +1,28 @@
name: rds
help: RDS commands
group: RDS
expose: always
dependencies:
aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'
jq: Install with 'brew install jq'
commands:
- name: list-db-instances
help: List all RDS DB instances for the given account by their name
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- name: fetch-db-connection-details
help: Fetch the connection details for the given RDS DB instance
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
args:
- name: db_instance
required: true
help: The RDS DB instance name
+8
View File
@@ -0,0 +1,8 @@
declare region
# shellcheck disable=SC2154
region="${args[region]}"
if ( grep -q "AWS_REGION" ~/.bashrc ); then
sed -i "/^AWS_REGION=/c\export AWS_REGION=$region" ~/.bashrc
fi
bash -c "export AWS_REGION=$region; exec bash"
@@ -0,0 +1,10 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare secret_name="${args[--name]}"
declare secret_string="${args[--secret-string]}"
validate-or-refresh-aws-auth
aws secretsmanager create-secret --name "$secret_name" --secret-string "$secret_string" --profile "$aws_profile" --region "$aws_region"
@@ -0,0 +1,16 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare detailed_format="${args[--detailed]}"
validate-or-refresh-aws-auth
# shellcheck disable=SC2155
declare secrets=$(aws secretsmanager list-secrets --profile "$aws_profile" --region "$aws_region")
if [[ $detailed_format == 1 ]]; then
jq . <<< "$secrets"
else
jq -r '.SecretList[].Name' <<< "$secrets"
fi
@@ -0,0 +1,48 @@
name: secretsmanager
help: Secrets Manager commands
group: Secrets Manager
expose: always
dependencies:
aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'
jq: Install using 'brew install jq'
commands:
- name: list-secrets
help: List all AWS Secrets Manager secrets
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --detailed
help: Output the list of all secrets in the detailed format
- name: show-secret
help: Show the secret value for the specified secret
args:
- name: secret_id
required: true
help: The secret ID for which the value needs to be displayed
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --detailed
help: Output the secret value in detailed format
- name: create-secret
help: Create a new secret in Secrets Manager
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --name
help: Name for the new secret
required: true
arg: name
- long: --secret-string
help: The secret string to be stored
required: true
arg: secret_string
@@ -0,0 +1,16 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare detailed_format="${args[--detailed]}"
declare secret_id="${args[secret_id]}"
validate-or-refresh-aws-auth
declare secret_value=$(aws secretsmanager get-secret-value --secret-id "$secret_id" --profile "$aws_profile" --region "$aws_region")
if [[ $detailed_format == 1 ]]; then
jq . <<< "$secret_value"
else
jq '.SecretString' <<< "$secret_value" | sed 's|\\"|"|g' | sed -e 's/"{/{/' -e 's/}"/}/' | jq
fi
+1
View File
@@ -0,0 +1 @@
aws --cli-auto-prompt
+10
View File
@@ -0,0 +1,10 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare name="${args[--name]}"
declare value="${args[--value]}"
validate-or-refresh-aws-auth
aws ssm put-parameter --name "$name" --value "$value" --type String --profile "$aws_profile" --region "$aws_region"
+9
View File
@@ -0,0 +1,9 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare parameter_name="${args[parameter_name]}"
validate-or-refresh-aws-auth
aws ssm delete-parameter --name "$parameter_name" --profile "$aws_profile" --region "$aws_region"
+16
View File
@@ -0,0 +1,16 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare detailed_format="${args[--detailed]}"
declare parameter_name="${args[parameter_name]}"
validate-or-refresh-aws-auth
declare parameter_value=$(aws ssm get-parameter --name "$parameter_name" --profile "$aws_profile" --region "$aws_region")
if [[ $detailed_format == 1 ]]; then
jq . <<< "$parameter_value"
else
jq '.Parameter.Value' <<< "$parameter_value" | tr -d '"'
fi
+16
View File
@@ -0,0 +1,16 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare detailed_format="${args[--detailed]}"
validate-or-refresh-aws-auth
# shellcheck disable=SC2155
declare parameters=$(aws ssm describe-parameters --profile "$aws_profile" --region "$aws_region")
if [[ $detailed_format == 1 ]]; then
jq . <<< "$parameters"
else
jq -r '.Parameters[].Name' <<< "$parameters"
fi
+137
View File
@@ -0,0 +1,137 @@
name: ssm
help: SSM commands
group: SSM
expose: always
dependencies:
aws: Install the latest version following the instructions at 'https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html'
jq: Install using 'brew install jq'
commands:
- name: start-port-forwarding
help: Use SSM to connect to an EC2 instance and forward a local port to the remote machine
args:
- name: instance-id
help: The ID of the EC2 instance to connect to
required: true
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --remote-port
help: The port number of the server on the EC2 instance
arg: remote-port
default: "80"
validate: aws_ssm_port_forwarding_number
- long: --local-port
help: The port number on the local machine to forward traffic to. An open port is chosen at run-time if not provided.
arg: local-port
default: "0"
validate: aws_ssm_port_forwarding_number
- long: --host
help: Hostname or IP address of the destination server
arg: host
default: localhost
validate: aws_ssm_port_forwarding_host
examples:
- dtools aws start-port-forwarding i-0892eeaed80a5b00b --remote-port 5432 --local-port 5432 --host prod-postgres.ctm8i4qgknv3.us-east-1.rds.amazonaws.com --profile prod --region us-east-1
- name: start-ngrok-bastion-instance
help: Start an EC2 instance to act as a bastion host for ngrok
dependencies:
jq: Install with 'brew install jq'
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --hostname
help: |
The hostname to forward connections to.
This will be hostnames like the ones that are only accessible via AWS ECS Service Discovery (e.g. api.caerus.local)
required: true
- long: --subnet-id
help: The subnet ID that the instance is to be deployed into
required: true
- long: --port
help: The port on the destination hostname to forward connections to
arg: port
default: "8080"
- long: --ngrok-url
short: -u
arg: ngrok_url
help: The ngrok URL to connect to
required: true
- long: --ngrok-auth-token
short: -a
arg: ngrok_auth_token
help: The ngrok authentication token
required: true
- name: list-parameters
help: List all AWS SSM Parameter Store parameters
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --detailed
help: Output the list of all parameters in the detailed format
- name: get-parameter
help: Get the value of an AWS SSM Parameter Store parameter
args:
- name: parameter_name
required: true
help: The name of the parameter to retrieve
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --detailed
help: Output the parameter value in detailed format
- name: create-parameter
help: Create a new parameter in AWS SSM Parameter Store
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --name
help: Name for the new parameter
required: true
arg: name
- long: --value
help: The value of the parameter to be stored
required: true
arg: value
- name: update-parameter
help: Update an existing parameter in AWS SSM Parameter Store (Will create a new parameter if it does not exist)
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
- long: --name
help: Name of the parameter to update
required: true
arg: name
- long: --value
help: The value of the parameter to be stored
required: true
arg: value
- name: delete-parameter
help: Delete a parameter from AWS SSM Parameter Store
filters:
- profile_and_region_variables_set_with_flags
flags:
- import: src/components/aws/profile_flag.yml
- import: src/components/aws/region_flag.yml
args:
- name: parameter_name
required: true
help: The name of the parameter to delete
@@ -0,0 +1,108 @@
set -e
# shellcheck disable=SC2155
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
# shellcheck disable=SC2154
declare subnet_id="${args[--subnet-id]}"
declare hostname="${args[--hostname]}"
declare port="${args[--port]}"
declare ngrok_url="${args[--ngrok-url]}"
declare ngrok_auth_token="${args[--ngrok-auth-token]}"
validate-or-refresh-aws-auth
cleanup() {
if [[ -n "$instance_id" ]]; then
yellow "Terminating the EC2 instance..."
aws --profile "$aws_profile" --region "$aws_region" ec2 terminate-instances --instance-ids "$instance_id"
fi
}
trap "cleanup" EXIT
cyan "Ensuring the AmazonSSMRoleForInstancesQuickSetup role exists..."
if ! aws --profile "$aws_profile" --region "$aws_region" iam get-role --role-name AmazonSSMRoleForInstancesQuickSetup > /dev/null 2>&1; then
yellow "Creating the AmazonSSMRoleForInstancesQuickSetup role..."
aws --profile "$aws_profile" --region "$aws_region" iam create-role \
--role-name AmazonSSMRoleForInstancesQuickSetup \
--assume-role-policy-document '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Principal": {"Service": "ec2.amazonaws.com"}, "Action": "sts:AssumeRole"}]}' \
> /dev/null
yellow "Attaching the AmazonSSMManagedInstanceCore policy to the role..."
aws --profile "$aws_profile" --region "$aws_region" iam attach-role-policy \
--role-name AmazonSSMRoleForInstancesQuickSetup \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
yellow "Attaching the AmazonSSMPatchAssociation policy to the role..."
aws --profile "$aws_profile" --region "$aws_region" iam attach-role-policy \
--role-name AmazonSSMRoleForInstancesQuickSetup \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMPatchAssociation
yellow "Creating the AmazonSSMRoleForInstancesQuickSetup instance profile..."
aws --profile "$aws_profile" --region "$aws_region" iam create-instance-profile \
--instance-profile-name AmazonSSMRoleForInstancesQuickSetup \
> /dev/null
yellow "Adding the AmazonSSMRoleForInstancesQuickSetup role to the instance profile..."
aws --profile "$aws_profile" --region "$aws_region" iam add-role-to-instance-profile \
--instance-profile-name AmazonSSMRoleForInstancesQuickSetup --role-name AmazonSSMRoleForInstancesQuickSetup \
> /dev/null
sleep 5
fi
cyan "Launching an EC2 instance..."
# shellcheck disable=SC2155
declare instance_id=$({
aws --profile "$aws_profile" --region "$aws_region" ec2 run-instances \
--image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \
--instance-type t2.micro \
--count 1 \
--subnet-id "$subnet_id" \
--iam-instance-profile Name=AmazonSSMRoleForInstancesQuickSetup \
--user-data $'#!/bin/bash\nwget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz\ntar xvzf ./ngrok-v3-stable-linux-amd64.tgz -C /usr/local/bin' \
--query Instances[0].InstanceId \
--output text
})
get-instance-state() {
aws --profile "$aws_profile" --region "$aws_region" ec2 describe-instance-status \
--instance-ids "$instance_id" \
--query InstanceStatuses[0] |\
jq '. | {instance: .InstanceStatus.Details[0].Status, system: .SystemStatus.Details[0].Status}'
}
status_checks=$(get-instance-state)
until [[ $(jq -r '.instance' <<< "$status_checks") == "passed" && $(jq -r '.system' <<< "$status_checks") == "passed" ]]; do
yellow "Waiting for instance to start..."
sleep 1
status_checks=$(get-instance-state)
done
green 'Instance is running!'
yellow "Adding the ngrok authtoken to the instance..."
aws --profile "$aws_profile" --region "$aws_region" ssm start-session \
--target "$instance_id" \
--document-name AWS-StartInteractiveCommand \
--parameters command="ngrok config add-authtoken $ngrok_auth_token"
yellow 'Starting ngrok tunnel...'
cyan 'The resource will be available at the following URL: '
cyan_bold "https://$ngrok_url"
cyan "\nYou will be able to point Postman to the above URL to access the resource."
yellow_bold "\nPress 'Ctrl+C' to stop the ngrok tunnel and to terminate the EC2 instance."
red_bold "This information will only be displayed once. Please make a note of it.\n"
read -rp "To acknowledge receipt and continue, press 'Enter'." </dev/tty
aws --profile "$aws_profile" --region "$aws_region" ssm start-session \
--target "$instance_id" \
--document-name AWS-StartInteractiveCommand \
--parameters command="ngrok http ${hostname}:${port} --domain $ngrok_url"
yellow "Terminating the EC2 instance..."
aws --profile "$aws_profile" --region "$aws_region" ec2 terminate-instances --instance-ids "$instance_id"
@@ -0,0 +1,17 @@
# shellcheck disable=SC2155
declare aws_profile="$(get-aws-profile)"
declare aws_region="$(get-aws-region)"
# shellcheck disable=SC2154
declare instance_id="${args[instance-id]}"
declare remote_port="${args[--remote-port]}"
declare local_port="${args[--local-port]}"
declare host="${args[--host]}"
validate-or-refresh-aws-auth
aws ssm start-session \
--profile "$aws_profile" \
--region "$aws_region" \
--target "$instance_id" \
--document-name "AWS-StartPortForwardingSessionToRemoteHost" \
--parameters "portNumber=${remote_port},localPortNumber=${local_port},host=${host}"
+10
View File
@@ -0,0 +1,10 @@
# shellcheck disable=SC2155
declare aws_region="$(get-aws-region)"
declare aws_profile="$(get-aws-profile)"
# shellcheck disable=SC2154
declare name="${args[--name]}"
declare value="${args[--value]}"
validate-or-refresh-aws-auth
aws ssm put-parameter --name "$name" --value "$value" --overwrite --profile "$aws_profile" --region "$aws_region"
+13
View File
@@ -0,0 +1,13 @@
set-aws-auto-prompt() {
if ( grep "AWS_CLI_AUTO_PROMPT" ~/.bashrc > /dev/null 2>&1 ); then
sed -i "/AWS_CLI_AUTO_PROMPT=/c\export AWS_CLI_AUTO_PROMPT=$1" ~/.bashrc
fi
bash -c "export AWS_CLI_AUTO_PROMPT=$1; exec bash"
}
if [[ -z ${AWS_CLI_AUTO_PROMPT} || $AWS_CLI_AUTO_PROMPT == 'off' ]]; then
set-aws-auto-prompt on
else
set-aws-auto-prompt off
fi