diff --git a/common/common.sh b/common/common.sh index fd539ad..d810c0f 100644 --- a/common/common.sh +++ b/common/common.sh @@ -1,32 +1,32 @@ -aws_assume_role_option_set_output_table() { +function aws_assume_role_option_set_output_table() { export AWS_DEFAULT_OUTPUT="table" } -aws_assume_role_option_set_output_json() { +function aws_assume_role_option_set_output_json() { export AWS_DEFAULT_OUTPUT="json" } -aws_assume_role_option_set_output_yml() { +function aws_assume_role_option_set_output_yml() { export AWS_DEFAULT_OUTPUT="yaml" } -aws_assume_role_enable_fast_mode() { +function aws_assume_role_enable_fast_mode() { export aws_assume_role_print_account_info=false } -aws_assume_role_disable_fast_mode() { +function aws_assume_role_disable_fast_mode() { export aws_assume_role_print_account_info=true } -aws_assume_role_disable_load_current_assume_role_for_new_tab() { +function aws_assume_role_disable_load_current_assume_role_for_new_tab() { rm -rf ${aws_cli_current_assume_role_name} >/dev/null } -aws_assume_role_disable_show_detail_commandline() { +function aws_assume_role_disable_show_detail_commandline() { export aws_show_commandline=false } -aws_run_commandline_with_retry() { +function aws_run_commandline_with_retry() { local aws_commandline=$1 local silent_mode=$2 local retry_counter=0 @@ -57,7 +57,7 @@ aws_run_commandline_with_retry() { } -aws_run_commandline() { +function aws_run_commandline() { aws_run_commandline=$1 aws_run_commandline="${aws_run_commandline:?'aws_run_commandline is unset or empty'}" aws_run_commandline_with_logging "${aws_run_commandline}" @@ -72,7 +72,7 @@ function aws_commandline_logging() { fi } -aws_run_commandline_with_logging() { +function aws_run_commandline_with_logging() { local aws_commandline=$1 local log_file_path=${aws_cli_logs}/${ASSUME_ROLE}.log diff --git a/common/logging.sh b/common/logging.sh index f22dc81..4b8ae86 100644 --- a/common/logging.sh +++ b/common/logging.sh @@ -1,19 +1,19 @@ #!/bin/bash -aws_assume_role_get_log() { +function aws_assume_role_get_log() { local log_file_path=${aws_cli_logs}/${ASSUME_ROLE}.log echo "Read the log ${log_file_path}" view +$ -c 'set number' ${log_file_path} } -aws_assume_role_get_log_uploaded() { +function aws_assume_role_get_log_uploaded() { local log_file_path=${aws_cli_logs}/${ASSUME_ROLE}-uploaded.log echo "Read the log ${log_file_path}" view +$ -c 'set number' ${log_file_path} } # TODO LATER -aws_assume_role_enable_log_uploaded() { +function aws_assume_role_enable_log_uploaded() { export aws_show_log_uploaded=true local log_uploaded_file_path=${aws_cli_logs}/${ASSUME_ROLE}-uploaded.log touch ${log_uploaded_file_path} diff --git a/common/peco.sh b/common/peco.sh index 2d8d865..0443bed 100644 --- a/common/peco.sh +++ b/common/peco.sh @@ -1,42 +1,42 @@ -peco_assume_role_name() { +function peco_assume_role_name() { cat ~/.aws/config | grep -e "^\[profile.*\]$" | peco } -peco_format_name_convention_pre_defined() { +function peco_format_name_convention_pre_defined() { local peco_input=$1 echo "${peco_input}" | tr "\t" "\n" | tr -s " " "\n" | tr -s '\n' } -peco_format_aws_output_text() { +function peco_format_aws_output_text() { local peco_input=$1 echo "${peco_input}" | tr "\t" "\n" } -peco_aws_acm_list() { +function peco_aws_acm_list() { aws_acm_list | peco } -peco_name_convention_input() { +function peco_name_convention_input() { local text_input=$1 local format_text=$(peco_format_name_convention_pre_defined $text_input) echo $format_text } -peco_create_menu_with_array_input() { +function peco_create_menu_with_array_input() { local text_input=$1 local format_text=$(peco_format_name_convention_pre_defined $text_input) echo $format_text } -peco_aws_disable_input_cached() { +function peco_aws_disable_input_cached() { export peco_input_expired_time=0 } -peco_aws_input() { +function peco_aws_input() { peco_commandline_input "${1} --output text" $2 } -peco_commandline_input() { +function peco_commandline_input() { local commandline="${1}" local result_cached=$2 @@ -73,7 +73,7 @@ peco_commandline_input() { } -peco_create_menu() { +function peco_create_menu() { local input_function=$1 local peco_options=$2 local peco_command="peco ${peco_options}" @@ -83,33 +83,33 @@ peco_create_menu() { } # AWS Logs -peco_aws_logs_list() { +function peco_aws_logs_list() { peco_aws_input 'aws logs describe-log-groups --query "*[].logGroupName"' 'true' } # AWS ECS -peco_aws_ecs_list_clusters() { +function peco_aws_ecs_list_clusters() { peco_aws_input 'aws ecs list-clusters --query "*[]"' 'true' } -peco_aws_ecs_list_services() { +function peco_aws_ecs_list_services() { peco_aws_input 'aws ecs list-services --cluster $aws_ecs_cluster_arn --query "*[]"' } # AWS ECR -peco_aws_ecr_list_repo_names() { +function peco_aws_ecr_list_repo_names() { peco_aws_input 'aws ecr describe-repositories --query "*[].repositoryName"' 'true' } -peco_aws_ecr_list_images() { +function peco_aws_ecr_list_images() { aws_ecr_repo_name=$1 peco_aws_input "aws ecr list-images \ --repository-name ${aws_ecr_repo_name:?'aws_ecr_repo_name is unset or empy'} \ --query \"imageIds[].{imageTag:imageTag}\"" } -peco_aws_alb_list_listners() { +function peco_aws_alb_list_listners() { aws_alb_arn=$1 peco_aws_input " \ aws elbv2 describe-listeners \ @@ -118,85 +118,85 @@ peco_aws_alb_list_listners() { } # AWS RDS -peco_aws_list_db_parameter_groups() { +function peco_aws_list_db_parameter_groups() { peco_aws_input 'aws rds describe-db-parameter-groups --query "*[].DBParameterGroupName"' 'true' } -peco_aws_rds_list_db_cluster_snapshots() { +function peco_aws_rds_list_db_cluster_snapshots() { peco_aws_input 'aws rds describe-db-cluster-snapshots \ --snapshot-type manual \ --query "DBClusterSnapshots[].DBClusterSnapshotIdentifier"' } -peco_aws_rds_list_db_snapshots() { +function peco_aws_rds_list_db_snapshots() { peco_aws_input 'aws rds describe-db-snapshots \ --snapshot-type manual \ --query "DBSnapshots[].DBSnapshotIdentifier"' } -peco_aws_list_db_cluster_parameter_groups() { +function peco_aws_list_db_cluster_parameter_groups() { peco_aws_input 'aws rds describe-db-cluster-parameter-groups --query "*[].DBClusterParameterGroupName"' 'true' } -peco_aws_list_db_clusters() { +function peco_aws_list_db_clusters() { peco_aws_input 'aws rds describe-db-clusters --query "*[].DBClusterIdentifier"' 'true' } -peco_aws_list_db_endpoint() { +function peco_aws_list_db_endpoint() { peco_aws_input 'aws rds describe-db-clusters --query "*[].[Endpoint, ReaderEndpoint]"' 'true' } -peco_aws_list_db_instances() { +function peco_aws_list_db_instances() { peco_aws_input 'aws rds describe-db-instances --query "*[].DBInstanceIdentifier"' 'true' } # Lambda -peco_aws_lambda_list() { +function peco_aws_lambda_list() { peco_aws_input 'aws lambda list-functions --query "*[].FunctionName"' 'true' } # S3 -peco_aws_s3_list() { +function peco_aws_s3_list() { peco_aws_input 'aws s3api list-buckets --query "Buckets[].Name"' 'true' } # Codebuild -peco_aws_codebuild_list() { +function peco_aws_codebuild_list() { peco_aws_input 'aws codebuild list-projects --query "*[]"' 'true' } -peco_aws_codepipeline_list() { +function peco_aws_codepipeline_list() { peco_aws_input 'aws codepipeline list-pipelines --query "*[].name"' 'true' } # Codedeploy -peco_aws_codedeploy_list_deployment_ids() { +function peco_aws_codedeploy_list_deployment_ids() { peco_aws_input 'aws deploy list-deployments --query "deployments[]"' } # Cloudfront -peco_aws_cloudfront_list() { +function peco_aws_cloudfront_list() { commandline="aws cloudfront list-distributions \ --query 'DistributionList.Items[*].{AId:Id,BComment:Comment}' --output text | tr -s '\t' '_'" peco_commandline_input ${commandline} 'true' } # Autoscaling group -peco_aws_autoscaling_list() { +function peco_aws_autoscaling_list() { peco_aws_input 'aws autoscaling describe-auto-scaling-groups --query "*[].AutoScalingGroupName"' 'true' } # IAM role list -peco_aws_iam_list_roles() { +function peco_aws_iam_list_roles() { peco_aws_input 'aws iam list-roles --query "*[].{RoleName:RoleName}"' 'true' } -peco_aws_iam_list_attached_policies() { +function peco_aws_iam_list_attached_policies() { peco_aws_input 'aws iam list-policies --scope Local --only-attached --query "*[].Arn"' 'true' } # EC2 Instance -peco_aws_ec2_list() { +function peco_aws_ec2_list() { local instance_state=${1:-'running'} commandline="aws ec2 describe-instances \ @@ -206,58 +206,82 @@ peco_aws_ec2_list() { peco_commandline_input ${commandline} 'true' } -peco_aws_ec2_list_all() { +function peco_aws_ec2_list_all() { commandline="aws ec2 describe-instances \ --query 'Reservations[].Instances[].{Name: Tags[?Key==\`Name\`].Value | [0],InstanceId:InstanceId,PrivateIpAddress:PrivateIpAddress}' \ --output text | tr -s '\t' '_'" peco_commandline_input ${commandline} 'true' } -peco_aws_ssm_list_parameters() { +function peco_aws_ssm_list_parameters() { commandline=" \ - aws ssm get-parameters-by-path \ - --path "/" \ - --recursive \ - --query 'Parameters[*].Name' \ - | jq -r '.[]' + aws ssm get-parameters-by-path \ + --path "/" \ + --recursive \ + --query 'Parameters[*].Name' \ + | jq -r '.[]' " peco_commandline_input ${commandline} 'true' } -peco_aws_dynamodb_list_tables() { +function peco_aws_dynamodb_list_tables() { peco_aws_input "aws dynamodb list-tables --query 'TableNames[]'" 'true' } -peco_aws_sqs_list() { +function peco_aws_sqs_list() { peco_aws_input 'aws sqs list-queues --query "*[]"' 'true' } -peco_aws_eks_list_clusters() { +function peco_aws_eks_list_clusters() { peco_aws_input 'aws eks list-clusters --query "*[]"' 'true' } -peco_aws_cloudformation_list_stacks() { +function peco_aws_cloudformation_list_stacks() { peco_aws_input 'aws cloudformation list-stacks --query "*[].StackName"' 'true' } -peco_aws_imagebuilder_list() { +function peco_aws_imagebuilder_list() { peco_aws_input 'aws imagebuilder list-image-pipelines --query "imagePipelineList[*].arn"' 'true' } -peco_aws_imagebuilder_list_recipes() { +function peco_aws_imagebuilder_list_recipes() { peco_aws_input 'aws imagebuilder list-image-recipes --query "*[].arn"' 'true' } -peco_aws_budgets_list() { +function peco_aws_budgets_list() { aws_assume_role_get_aws_account_id peco_aws_input 'aws budgets describe-budgets --account-id=${AWS_ACCOUNT_ID} --query "*[].BudgetName"' 'true' } -peco_aws_secretmanager_list() { +function peco_aws_secretmanager_list() { peco_aws_input 'aws secretsmanager list-secrets --query "*[].Name"' 'true' } -peco_aws_sns_list() { +function peco_aws_sns_list() { peco_aws_input 'aws sns list-topics --query "*[].TopicArn"' 'true' } + +function peco_aws_iam_user_list() { + peco_aws_input 'aws iam list-users --query "*[].{UserName:UserName}"' 'true' +} + +function peco_aws_iam_group_list() { + peco_aws_input 'aws iam list-groups --query "*[].{GroupName:GroupName}"' 'true' +} + +function peco_aws_iam_policy_list() { + peco_aws_input 'aws iam list-policies --query "*[].{PolicyName:PolicyName}"' 'true' +} + +function peco_aws_iam_role_list() { + peco_aws_input 'aws iam list-roles --query "*[].{RoleName:RoleName}"' 'true' +} + +function peco_aws_iam_instance_profile_list() { + peco_aws_input 'aws iam list-instance-profiles --query "*[].{InstanceProfileName:InstanceProfileName}"' 'true' +} + +function peco_aws_scheduler_list() { + peco_aws_input 'aws scheduler list-schedules --query "Schedules[*].[Name]"' 'true' +} diff --git a/services/acm.sh b/services/acm.sh index b2ee6dc..c84daf3 100644 --- a/services/acm.sh +++ b/services/acm.sh @@ -2,12 +2,107 @@ # AWS acm aws_acm_list() { - for item in $(aws acm list-certificates --query "*[].CertificateArn" --output text); do - aws_run_commandline \ - " - aws acm describe-certificate \ - --certificate-arn $item \ - --query \"*[].{CertificateArn:CertificateArn,DomainName:DomainName,SubjectAlternativeNames:SubjectAlternativeNames,Type:Type}\" - " - done + for item in $(aws acm list-certificates --query "*[].CertificateArn" --output text); do + aws_run_commandline \ + " + aws acm describe-certificate \ + --certificate-arn $item \ + --query \"*[].{CertificateArn:CertificateArn,DomainName:DomainName,SubjectAlternativeNames:SubjectAlternativeNames,Type:Type}\" + " + done +} + +aws_acm_import() { + local certificate_arn="$1" + local certificate_file="$2" + local private_key_file="$3" + local certificate_chain_file="$4" + + if [[ -z "$certificate_arn" || -z "$certificate_file" || -z "$private_key_file" || -z "$certificate_chain_file" ]]; then + echo "Error: Missing required arguments." + echo "Usage: aws_acm_import " + return 1 + fi + + aws_run_commandline \ + "aws acm import-certificate \ + --certificate-arn $certificate_arn \ + --certificate fileb://$certificate_file \ + --private-key fileb://$private_key_file \ + --certificate-chain fileb://$certificate_chain_file" +} + +aws_acm_delete() { + local certificate_arn="$1" + + if [[ -z "$certificate_arn" ]]; then + echo "Error: Missing required argument." + echo "Usage: aws_acm_delete " + return 1 + fi + + aws_run_commandline "aws acm delete-certificate --certificate-arn $certificate_arn" +} + +aws_acm_request() { + local domain_name="$1" + local validation_method="$2" + local subject_alternative_names="$3" + + if [[ -z "$domain_name" || -z "$validation_method" ]]; then + echo "Error: Missing required arguments." + echo "Usage: aws_acm_request [subject_alternative_names]" + return 1 + fi + + local command="aws acm request-certificate --domain-name $domain_name --validation-method $validation_method" + + if [[ -n "$subject_alternative_names" ]]; then + command="$command --subject-alternative-names $subject_alternative_names" + fi + + aws_run_commandline "$command" +} + +aws_acm_validate() { + local certificate_arn="$1" + local validation_record="$2" + + if [[ -z "$certificate_arn" || -z "$validation_record" ]]; then + echo "Error: Missing required arguments." + echo "Usage: aws_acm_validate " + return 1 + fi + + aws_run_commandline \ + "aws acm validate-certificate \ + --certificate-arn $certificate_arn \ + --validation-record $validation_record" +} + +aws_acm_get_validation_records() { + local certificate_arn="$1" + + if [[ -z "$certificate_arn" ]]; then + echo "Error: Missing required argument." + echo "Usage: aws_acm_get_validation_records " + return 1 + fi + + aws_run_commandline \ + "aws acm describe-certificate \ + --certificate-arn $certificate_arn \ + --query 'Certificate.DomainValidationOptions[].ResourceRecord'" +} + +aws_acm_get_with_hint() { + local certificate_list=$(aws acm list-certificates --query "*[].{Arn:CertificateArn,Domain:DomainName}" --output text | awk '{print $1 " (" $2 ")"}') + local selected_certificate=$(peco_create_menu 'echo ${certificate_list}' '--prompt "Select ACM certificate >"' | awk '{print $1}') + + if [[ -n "$selected_certificate" ]]; then + aws_run_commandline \ + "aws acm describe-certificate \ + --certificate-arn $selected_certificate \ + --query \"*[].{CertificateArn:CertificateArn,DomainName:DomainName,SubjectAlternativeNames:SubjectAlternativeNames,Type:Type}\"" + fi } diff --git a/services/assume_role.sh b/services/assume_role.sh index 2161a01..5b9413c 100644 --- a/services/assume_role.sh +++ b/services/assume_role.sh @@ -224,12 +224,13 @@ aws_assume_role_set_name() { aws_assume_role_save_current_assume_role ${aws_cli_current_assume_role_name} } -aws_assume_role_set_name_with_hint() { - function peco_aws_asssume_role_list() { - # To ignore comment profile - cat ~/.aws/config | grep -E '^\[profile (.*)\]$' | sed -E 's|^\[profile (.*)\]$|\1|g' +function peco_aws_asssume_role_list() { + # To ignore comment profile + cat ~/.aws/config | grep -E '^\[profile (.*)\]$' | sed -E 's|^\[profile (.*)\]$|\1|g' - } +} + +function aws_assume_role_set_name_with_hint() { function aws_assume_role_insert_current_asssume_role_first() { assume_role_list=$1 diff --git a/services/aws_cost.sh b/services/aws_cost.sh new file mode 100644 index 0000000..454e385 --- /dev/null +++ b/services/aws_cost.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +################################################################### +# # @version 1.0.0 +# # @script aws_cost.sh +# # @author lamhaison +# # @email lamhaison@gmail.com +# # @description Description detail about the script +# # @bash_version None +# # @notes None +# # @usage Only use function in the script instead of bash aws_config.sh +# # @date YYYYMMDD +################################################################### + +function aws_cost_list_months_later() { + # Default is 6 months + local months=${1:-'6'} + aws ce get-cost-and-usage \ + --time-period "Start=$(date -d "${months} months ago" +%Y-%m-01),End=$(date -d "$(date +%Y-%m-01) -1 day" +%Y-%m-%d)" \ + --granularity MONTHLY --metrics "UnblendedCost" +} diff --git a/services/aws_scheduler.sh b/services/aws_scheduler.sh new file mode 100644 index 0000000..c37343d --- /dev/null +++ b/services/aws_scheduler.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +################################################################### +# # @script aws_scheduler.sh +# # @author lamhaison +# # @description aws_scheduler.sh is a script to manage AWS Scheduler resources. +# # @email lamhaison@gmail.com +################################################################### + +function aws_scheduler_list() { + aws_run_commandline "\ + aws scheduler list-schedules \ + --query 'Schedules[*].[Name,GroupName,State,ScheduleExpression]' --output table + " + +} + +function aws_scheduler_get() { + local schedule_name=$1 + + if [[ -z "$schedule_name" ]]; then + echo "Usage: aws_scheduler_get " + return 1 + fi + + aws_run_commandline "\ + aws scheduler get-schedule \ + --name \"$schedule_name\" \ + " +} + +function aws_scheduler_get_with_hint() { + local schedule_name=$(peco_create_menu 'peco_aws_scheduler_list' '--prompt "Choose scheduler name >"') + aws_scheduler_get "$schedule_name" +} + +function aws_scheduler_disable_schedule() { + local schedule_name=$1 + + if [[ -z "$schedule_name" ]]; then + echo "Usage: aws_scheduler_disable_schedule " + return 1 + fi + + # Get the current schedule details + local schedule_detail + schedule_detail=$(aws scheduler get-schedule --name "$schedule_name" 2>/dev/null) + if [[ $? -ne 0 || -z "$schedule_detail" ]]; then + echo "Failed to get schedule details for '$schedule_name'" + return 1 + fi + + # Extract required fields from the schedule detail + local schedule_expression + local flexible_time_window + local target + + schedule_expression=$(echo "$schedule_detail" | jq -c -r '.ScheduleExpression') + flexible_time_window=$(echo "$schedule_detail" | jq -c -r '.FlexibleTimeWindow') + target=$(echo "$schedule_detail" | jq -c -r '.Target') + + if [[ -z "$schedule_expression" || -z "$flexible_time_window" || -z "$target" ]]; then + echo "Failed to extract required fields from schedule details." + return 1 + fi + + aws_run_commandline "\ + aws scheduler update-schedule \ + --name \"$schedule_name\" \ + --state DISABLED \ + --flexible-time-window '$flexible_time_window' \ + --schedule-expression '$schedule_expression' \ + --target '$target' + " +} + +function aws_scheduler_disable_schedule_with_hint() { + local schedule_name=$(peco_create_menu 'peco_aws_scheduler_list' '--prompt "Choose scheduler name >"') + aws_scheduler_disable_schedule "$schedule_name" +} + +function aws_scheduler_enable_schedule() { + local schedule_name=$1 + + if [[ -z "$schedule_name" ]]; then + echo "Usage: aws_scheduler_enable_schedule " + return 1 + fi + + aws_run_commandline "\ + aws scheduler update-schedule \ + --name \"$schedule_name\" \ + --state ENABLED + " +} diff --git a/services/aws_secretmanager.sh b/services/aws_secretmanager.sh index c11ffa7..3fb8742 100644 --- a/services/aws_secretmanager.sh +++ b/services/aws_secretmanager.sh @@ -157,7 +157,8 @@ function aws_secretmanager_update_secret() { function aws_secretmanager_update_specific_secret_key_with_hint() { - local secret_name=$(peco_create_menu 'peco_aws_secretmanager_list' '--prompt "Choose secret that you want >"') + local secret_name + secret_name=$(peco_create_menu 'peco_aws_secretmanager_list' '--prompt "Choose secret that you want >"') # Check input invalid if [[ -z "$secret_name" ]]; then @@ -187,6 +188,12 @@ function aws_secretmanager_update_specific_secret_key_with_hint() { continue fi + # Remove space/end-of-line at the begining and end of line for secret_value and secret key + secret_key=$(echo "${secret_key}" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//') + secret_key=$(echo "$secret_key" | sed '/./,$!d' | tac | sed '/./,$!d' | tac) + secret_value=$(echo "${secret_value}" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//') + secret_value=$(echo "$secret_value" | sed '/./,$!d' | tac | sed '/./,$!d' | tac) + aws_secretmanager_update_secret "${secret_name}" "${secret_key}" "${secret_value}" done @@ -230,13 +237,19 @@ function aws_secretmanager_delete_key() { # Be careful when using this } function aws_secretmanager_delete_key_with_hint() { # # Be careful when using this - local secret_name=$(peco_create_menu 'peco_aws_secretmanager_list' '--prompt "Choose secret that you want >"') + local secret_name + local secret_key + + secret_name=$(peco_create_menu 'peco_aws_secretmanager_list' '--prompt "Choose secret that you want >"') # Check input invalid - if [[ -z "$secret_name" ]]; then return; fi + if [[ -z "$secret_name" ]]; then + echo "❌ Secret name is invalid." + return + fi - local secret_key=$(peco_create_menu 'aws_secretmanager_list_keys ${secret_name}' '--prompt "Choose secret key that you want >"') + secret_key=$(peco_create_menu 'aws_secretmanager_list_keys ${secret_name}' '--prompt "Choose secret key that you want >"') - aws_secretmanager_delete_key "${secret_name}" ${secret_key} + aws_secretmanager_delete_key "${secret_name}" "${secret_key}" } diff --git a/services/ec2/aws_ec2_natgw.sh b/services/ec2/aws_ec2_natgw.sh new file mode 100644 index 0000000..4a41f84 --- /dev/null +++ b/services/ec2/aws_ec2_natgw.sh @@ -0,0 +1,20 @@ +#!/bin/bash +################################################################### +# # @version 1.0.0 +# # @script aws_ec2_natgw.sh +# # @author lamhaison +# # @email lamhaison@gmail.com +# # @description When working with natgw +# # @bash_version None +# # @notes None +# # @usage Only use function in the script instead of bash aws_ec2_natgw.sh +# # @date YYYYMMDD +################################################################### + +function aws_ec2_natgw_list() { + aws_run_commandline '\ + aws ec2 describe-nat-gateways \ + --query "NatGateways[*].{ID:NatGatewayId, State:State, EIP:NatGatewayAddresses[*].PublicIp, Subnet:SubnetId, VPC:VpcId}" \ + --output table + ' +} diff --git a/services/ecs.sh b/services/ecs.sh index 19819b3..b97e7f7 100644 --- a/services/ecs.sh +++ b/services/ecs.sh @@ -99,4 +99,48 @@ aws_ecs_execute_container() { container_name=$(aws ecs describe-task-definition --task-definition $aws_ecs_task_definition_arn --query 'taskDefinition.containerDefinitions[*].name' --output text | sed 's/\t/\n/g' | peco) echo Container name ${container_name:?"container_name is not set or empty"} aws ecs execute-command --cluster $aws_ecs_cluster_arn --container $container_name --interactive --command "/bin/sh" --task $aws_ecs_task_arn -} \ No newline at end of file +} + +aws_ecs_list_task_definitions() { + aws_run_commandline "\ + aws ecs list-task-definitions \ + --query 'taskDefinitionArns[]' \ + --output text" +} + +aws_ecs_describe_task_definition() { + local task_definition="$1" + + if [[ -z "$task_definition" ]]; then + echo "Error: Missing required argument." + echo "Usage: aws_ecs_describe_task_definition " + return 1 + fi + + aws_run_commandline "\ + aws ecs describe-task-definition \ + --task-definition $task_definition" +} + +aws_ecs_deregister_task_definition() { + local task_definition="$1" + + if [[ -z "$task_definition" ]]; then + echo "Error: Missing required argument." + echo "Usage: aws_ecs_deregister_task_definition " + return 1 + fi + + aws_run_commandline "\ + aws ecs deregister-task-definition \ + --task-definition $task_definition" +} + +aws_ecs_get_task_definition_with_hint() { + local task_definition_list=$(aws ecs list-task-definitions --query 'taskDefinitionArns[]' --output text) + local selected_task_definition=$(peco_create_menu 'echo ${task_definition_list}' '--prompt "Select task definition >"') + + if [[ -n "$selected_task_definition" ]]; then + aws_ecs_describe_task_definition "$selected_task_definition" + fi +} diff --git a/services/iam.sh b/services/iam.sh index e811fb9..9049803 100644 --- a/services/iam.sh +++ b/services/iam.sh @@ -5,21 +5,127 @@ aws_iam_add_policy_to_role() { echo "TODO Later" } -aws_iam_list_users() { +function aws_iam_list_users() { aws_run_commandline 'aws iam list-users --output table' } -aws_iam_list_users_info() { +function aws_iam_user_get() { + local user_name=$1 - aws_run_commandline 'aws iam list-users --output table' + # Check input invalid + if [[ -z "$user_name" ]]; then return; fi - for user_name in $(aws iam list-users --query '*[].{UserName:UserName}' --output text); do - aws_run_commandline "\ - aws iam get-user --user-name ${user_name} - aws iam list-attached-user-policies --user-name ${user_name} - " + aws_run_commandline "\ + aws iam get-user --user-name "$user_name" + " +} + +function aws_iam_user_list_access_keys() { + + local iam_user_name=$1 + + # Check input invalid + if [[ -z "$iam_user_name" ]]; then return; fi + + aws_run_commandline "\ + aws iam list-access-keys --user-name "$iam_user_name" + " +} + +function aws_iam_user_list_access_keys_with_hint() { + local iam_user_name=$(peco_create_menu 'peco_aws_iam_user_list' '--prompt "Choose iam user name >"') + aws_iam_user_list_access_keys "${iam_user_name}" + +} + +function aws_iam_user_list_policies() { + local user_name=$1 + + # Check input invalid + if [[ -z "$user_name" ]]; then return; fi + + echo "============================================================" + echo "👤 User: $user_name" + echo "============================================================" + + aws_iam_user_get "${user_name}" + + # === MANAGED USER POLICIES === + echo "📎 Directly Attached (Managed) User Policies:" + + for policy_arn in $(aws iam list-attached-user-policies \ + --user-name "$user_name" \ + --query 'AttachedPolicies[].PolicyArn' \ + --output text); do + echo "- 🔐 Managed Policy ARN: $policy_arn" + version_id=$(aws iam get-policy --policy-arn "$policy_arn" --query 'Policy.DefaultVersionId' --output text) + + if [[ $version_id =~ ^v[0-9]+$ ]]; then + aws iam get-policy-version \ + --policy-arn "$policy_arn" \ + --version-id "$version_id" \ + --query 'PolicyVersion.Document' \ + --output json + else + echo "⚠️ Skipped invalid or missing version for $policy_arn (version_id: '$version_id')" + fi + done + + # === INLINE USER POLICIES === + echo "📜 Inline User Policies:" + for policy_name in $(aws iam list-user-policies --user-name "$user_name" --query 'PolicyNames' --output text); do + echo "- 📄 Inline Policy: $policy_name" + aws iam get-user-policy \ + --user-name "$user_name" \ + --policy-name "$policy_name" \ + --query 'PolicyDocument' \ + --output json done + # === GROUPS === + echo "👥 IAM Groups:" + for group in $(aws iam list-groups-for-user --user-name "$user_name" --query 'Groups[].GroupName' --output text); do + echo "🔸 Group: $group" + + # === MANAGED GROUP POLICIES === + echo "📎 Managed Group Policies:" + for policy_arn in $(aws iam list-attached-group-policies --group-name "$group" --query 'AttachedPolicies[].PolicyArn' --output text); do + echo "- 🔐 Managed Policy ARN: $policy_arn" + version_id=$(aws iam get-policy --policy-arn "$policy_arn" --query 'Policy.DefaultVersionId' --output text) + aws iam get-policy-version \ + --policy-arn "$policy_arn" \ + --version-id "$version_id" \ + --query 'PolicyVersion.Document' \ + --output json + done + + # === INLINE GROUP POLICIES === + echo "📜 Inline Group Policies:" + for policy_name in $(aws iam list-group-policies --group-name "$group" --query 'PolicyNames' --output text); do + echo "- 📄 Inline Policy: $policy_name" + aws iam get-group-policy \ + --group-name "$group" \ + --policy-name "$policy_name" \ + --query 'PolicyDocument' \ + --output json + done + done + + echo "" + +} + +function aws_iam_user_list_policies_all() { + echo "🔍 Listing IAM users and all IAM policies (managed + inline)..." + + for user_name in $(aws iam list-users --query 'Users[].UserName' --output text); do + aws_iam_user_list_policies "${user_name}" + done +} + +function aws_iam_user_list_policies_with_hint() { + local iam_user_name=$(peco_create_menu 'peco_aws_iam_user_list' '--prompt "Choose iam user name >"') + aws_iam_user_list_policies "$iam_user_name" } aws_iam_list_roles_info() { @@ -134,11 +240,11 @@ aws_iam_list_role_policies() { done } -aws_iam_list_role_policies_with_hint() { +function aws_iam_list_role_policies_with_hint() { aws_iam_list_role_policies $(peco_create_menu 'peco_aws_iam_list_roles') } -aws_iam_get_policy() { +function aws_iam_get_policy() { aws_iam_policy_arn=$1 aws_run_commandline "\ aws iam get-policy --policy-arn \ @@ -150,11 +256,11 @@ aws_iam_get_policy() { " } -aws_iam_get_policy_with_hint() { +function aws_iam_get_policy_with_hint() { aws_iam_get_policy $(peco_create_menu 'peco_aws_iam_list_attached_policies') } -aws_iam_list_ec2_instance_profiles() { +function aws_iam_list_ec2_instance_profiles() { aws_run_commandline " aws iam list-instance-profiles \ --query '*[].{InstanceProfileName:InstanceProfileName,Arn:Arn}' diff --git a/services/logs.sh b/services/logs.sh index 7e23b14..1a8d015 100644 --- a/services/logs.sh +++ b/services/logs.sh @@ -18,6 +18,21 @@ function aws_logs_tail() { eval ${aws_cmd} } +function aws_logs_rm_group_instruction() { + aws_log_group_name=$1 + + # Check aws_log_group_name invalid + if [ -z "$aws_log_group_name" ]; then return; fi + local aws_cmd=$(echo "aws logs delete-log-group --log-group-name $aws_log_group_name") + echo "${aws_cmd}" +} + +function aws_logs_rm_group_instruction_with_hint() { + aws_log_group_name=$(peco_create_menu 'peco_aws_logs_list') + aws_logs_rm_group_instruction $aws_log_group_name + +} + function aws_logs_tail_with_hint() { echo "Your log group name >" aws_log_group_name=$(peco_create_menu 'peco_aws_logs_list') diff --git a/services/s3.sh b/services/s3.sh index 7b2e179..01f03ae 100644 --- a/services/s3.sh +++ b/services/s3.sh @@ -1,14 +1,14 @@ #!/bin/bash -aws_s3_ls() { +function aws_s3_ls() { aws_run_commandline "aws s3 ls" } -aws_s3_list() { +function aws_s3_list() { aws_run_commandline 'aws s3api list-buckets --query "Buckets[].Name"' } -aws_s3_get_bucket() { +function aws_s3_get_bucket() { aws_s3_bucket_name=$1 aws_run_commandline \ " @@ -17,7 +17,7 @@ aws_s3_get_bucket() { } -aws_s3_get_bucket_recursived() { +function aws_s3_get_bucket_recursived() { aws_s3_bucket_name=$1 aws_run_commandline \ " @@ -25,15 +25,15 @@ aws_s3_get_bucket_recursived() { " } -aws_s3_get_bucket_with_hint() { +function aws_s3_get_bucket_with_hint() { aws_s3_get_bucket $(peco_create_menu 'peco_aws_s3_list') } -aws_s3_get_bucket_recursived_with_hint() { +function aws_s3_get_bucket_recursived_with_hint() { aws_s3_get_bucket_recursived $(peco_create_menu 'peco_aws_s3_list') } -aws_s3_get_object_metadata() { +function aws_s3_get_object_metadata() { aws_s3_bucket_name=$1 object_key=$2 @@ -44,16 +44,16 @@ aws_s3_get_object_metadata() { } -aws_s3_get_bucket_arn() { +function aws_s3_get_bucket_arn() { aws_s3_bucket_name=$1 echo "arn:aws:s3:::${aws_s3_bucket_name:?'aws_s3_bucket_name is unset or empty'}" } -aws_s3_get_bucket_arn_with_hint() { +function aws_s3_get_bucket_arn_with_hint() { aws_s3_get_bucket_arn $(peco_create_menu 'peco_aws_s3_list') } -# aws_s3_get_object_metadata_with_hint() { +# function aws_s3_get_object_metadata_with_hint() { # bucket_name=$(peco_create_menu 'peco_aws_s3_list') # object_key=$2 @@ -64,7 +64,7 @@ aws_s3_get_bucket_arn_with_hint() { # } -aws_s3_create() { +function aws_s3_create() { local aws_s3_bucket_name=$1 # Don't have to specific bucket configuration if it is region us-east-1 local aws_s3_cmd_created="aws s3api create-bucket --bucket ${aws_s3_bucket_name:?'aws_s3_bucket_name is unset or empty'}" @@ -76,7 +76,7 @@ aws_s3_create() { } -aws_s3_rm_instruction() { +function aws_s3_rm_instruction() { aws_s3_bucket_name=$1 echo "We didn't run the commandline, we just suggest the commandline" echo "If you want ot process it please run the commandline \ @@ -96,12 +96,12 @@ aws_s3_rm_instruction() { # Delete all object versioning enabled aws s3api put-bucket-lifecycle-configuration \ --lifecycle-configuration '{"Rules":[{ - "ID":"empty-bucket", - "Status":"Enabled", - "Prefix":"", - "Expiration":{"Days":1}, - "NoncurrentVersionExpiration":{"NoncurrentDays":1} - }]}' \ + "ID":"empty-bucket", + "Status":"Enabled", + "Prefix":"", + "Expiration":{"Days":1}, + "NoncurrentVersionExpiration":{"NoncurrentDays":1} + }]}' \ --bucket ${aws_s3_bucket_name} # Then you just have to wait 1 day and the bucket can be deleted with @@ -110,7 +110,7 @@ aws_s3_rm_instruction() { __EOF__ } -aws_s3_rm_with_hint() { +function aws_s3_rm_with_hint() { aws_s3_rm_instruction $(peco_create_menu 'peco_aws_s3_list') } @@ -119,18 +119,18 @@ aws_s3_rm_with_hint() { # @param TODO The first parameter is the bucket name. # @return Buckets in Region us-east-1 have a LocationConstraint of null . # -aws_s3_get_location() { +function aws_s3_get_location() { aws_run_commandline "\ aws s3api get-bucket-location --bucket ${1} " } -aws_s3_get_location_with_hint() { +function aws_s3_get_location_with_hint() { # aws_s3_get_location $(peco_create_menu 'peco_aws_s3_list') } -aws_s3_get_bucket_policy() { +function aws_s3_get_bucket_policy() { aws_s3_bucket_name=$1 aws_run_commandline \ " @@ -140,27 +140,18 @@ aws_s3_get_bucket_policy() { " } -aws_s3_get_bucket_policy_with_hint() { +function aws_s3_get_bucket_policy_with_hint() { aws_s3_get_bucket_policy $(peco_create_menu 'peco_aws_s3_list') } -# -# TODO to get presign url for s3 object. -# @param The first parameter is the full path of object including s3 bucket name -# For ex: s3://DOC-EXAMPLE-BUCKET/test2.txt -# The second parameter is the expires-in (integer) Number of seconds until the pre-signed URL expires. -# Default is 3600 seconds. -# @return -# - -aws_s3_get_presigned_url() { +function aws_s3_get_presigned_url_for_viewer() { aws_run_commandline "\ aws s3 presign $1 --expires-in ${2:-3600} " } -aws_s3_cp_folder_instruction() { +function aws_s3_cp_folder_instruction() { echo "\ aws s3 cp s3://BUCKET_NAME/cf/cf-domain.com/cf-domain.com-2022-12 \ s3://NEW_BUCKET_NAME/cf-domain.com-2022-12/00-10 --recursive --exclude \"*\" --include \"CF_ID.2022-12-0*\" diff --git a/services/sqs.sh b/services/sqs.sh index 1843abf..429c795 100644 --- a/services/sqs.sh +++ b/services/sqs.sh @@ -66,3 +66,24 @@ function aws_sqs_purge() { # Be careful when using it, it will delete all the me function aws_sqs_purge_with_hint() { aws_sqs_purge $(peco_create_menu 'peco_aws_sqs_list') } + +function aws_sqs_push_message() { + local aws_sqs_queue_url=$1 + local aws_sqs_message_body=$2 + + # Check input invalid + if [[ -z "$aws_sqs_queue_url" || -z "$aws_sqs_message_body" ]]; then return; fi + + aws_run_commandline "\ + aws sqs send-message \ + --queue-url '${aws_sqs_queue_url}' \ + --message-body '${aws_sqs_message_body}' + " +} + +function aws_sqs_push_message_hello_world_with_hint() { + local aws_sqs_queue_url=$(peco_create_menu 'peco_aws_sqs_list') + local aws_sqs_message_body="hello world!" + + aws_sqs_push_message "${aws_sqs_queue_url}" "${aws_sqs_message_body}" +}