diff --git a/iam/clouds/aws/CloudGovernanceDeletePolicy.json b/iam/clouds/aws/CloudGovernanceInfra/CloudGovernanceDeletePolicy.json similarity index 84% rename from iam/clouds/aws/CloudGovernanceDeletePolicy.json rename to iam/clouds/aws/CloudGovernanceInfra/CloudGovernanceDeletePolicy.json index f2fa18701..98cc39a8d 100644 --- a/iam/clouds/aws/CloudGovernanceDeletePolicy.json +++ b/iam/clouds/aws/CloudGovernanceInfra/CloudGovernanceDeletePolicy.json @@ -6,7 +6,13 @@ "Effect": "Allow", "Action": [ "ce:GetCostAndUsage", - "ce:GetCostForecast" + "ce:GetCostForecast", + "tag:GetResources", + "tag:TagResources", + "support:DescribeTrustedAdvisorCheckResult", + "support:DescribeTrustedAdvisorChecks", + "resource-explorer-2:ListViews", + "resource-explorer-2:Search" ], "Resource": "*" }, @@ -39,52 +45,49 @@ "Sid": "EC2ResourceLevel", "Effect": "Allow", "Action": [ - "ec2:DeregisterImage", - "ec2:DeleteSubnet", + "autoscaling:DescribeAutoScalingGroups", + "autoscaling:DescribeLaunchConfigurations", + "ec2:AssociateDhcpOptions", + "ec2:DeleteDhcpOptions", + "ec2:DeleteInternetGateway", + "ec2:DeleteNatGateway", + "ec2:DeleteNetworkAcl", + "ec2:DeleteNetworkInterface", + "ec2:DeleteRouteTable", + "ec2:DeleteSecurityGroup", "ec2:DeleteSnapshot", - "ec2:DescribeAddresses", - "ec2:DescribeInstances", + "ec2:DeleteSubnet", + "ec2:DeleteVolume", + "ec2:DeleteVpc", "ec2:DeleteVpcEndpoints", "ec2:DeleteVpcPeeringConnection", - "autoscaling:DescribeLaunchConfigurations", - "ec2:DescribeRegions", - "ec2:CreateImage", - "ec2:CreateVpc", + "ec2:DeregisterImage", + "ec2:DescribeAddresses", "ec2:DescribeDhcpOptions", - "ec2:DescribeSnapshots", - "ec2:DeleteRouteTable", + "ec2:DescribeImages", + "ec2:DescribeInstanceTypes", + "ec2:DescribeInstances", "ec2:DescribeInternetGateways", - "ec2:DeleteVolume", - "ec2:DescribeNetworkInterfaces", - "autoscaling:DescribeAutoScalingGroups", - "ec2:DescribeVolumes", - "ec2:DeleteInternetGateway", + "ec2:DescribeNatGateways", "ec2:DescribeNetworkAcls", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeRegions", + "ec2:DescribeReservedInstances", "ec2:DescribeRouteTables", - "ec2:DeleteNetworkAcl", - "ec2:ReleaseAddress", - "ec2:AssociateDhcpOptions", - "ec2:TerminateInstances", - "ec2:DetachNetworkInterface", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSnapshots", + "ec2:DescribeSubnets", "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DescribeVpcEndpoints", "ec2:DescribeVpcPeeringConnections", - "ec2:ModifyNetworkInterfaceAttribute", - "ec2:DeleteNetworkInterface", + "ec2:DescribeVpcs", "ec2:DetachInternetGateway", - "ec2:DescribeNatGateways", - "ec2:StopInstances", + "ec2:DetachNetworkInterface", "ec2:DisassociateRouteTable", - "ec2:DescribeSecurityGroups", - "ec2:RevokeSecurityGroupIngress", - "ec2:DescribeImages", - "ec2:DescribeVpcs", - "ec2:DeleteSecurityGroup", - "ec2:DescribeInstanceTypes", - "ec2:DeleteDhcpOptions", - "ec2:DeleteNatGateway", - "ec2:DescribeVpcEndpoints", - "ec2:DeleteVpc", - "ec2:DescribeSubnets" + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:ReleaseAddress", + "ec2:RevokeSecurityGroupIngress" ], "Resource": "*" }, @@ -95,7 +98,8 @@ "elasticloadbalancing:DeleteLoadBalancer", "elasticloadbalancing:DescribeTags", "elasticloadbalancing:AddTags", - "elasticloadbalancing:DescribeLoadBalancers" + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:RemoveTags" ], "Resource": "*" }, @@ -103,32 +107,28 @@ "Sid": "IAM", "Effect": "Allow", "Action": [ - "iam:GetRole", - "iam:DeleteAccessKey", - "iam:DeleteGroup", - "iam:TagRole", + "iam:DeleteInstanceProfile", + "iam:DeletePolicy", + "iam:DeleteRole", + "iam:DeleteRolePolicy", "iam:DeleteUserPolicy", - "iam:ListRoles", - "iam:DeleteUser", - "iam:ListUserPolicies", - "iam:CreateUser", - "iam:TagUser", - "sts:AssumeRole", - "iam:RemoveUserFromGroup", - "iam:GetUserPolicy", - "iam:ListAttachedRolePolicies", - "iam:ListUsers", + "iam:DetachRolePolicy", + "iam:GetRole", "iam:GetUser", + "iam:GetUserPolicy", "iam:ListAccessKeys", - "iam:ListRolePolicies", "iam:ListAccountAliases", - "iam:DeleteRole", - "iam:DetachRolePolicy", - "iam:DeletePolicy", - "iam:DeleteRolePolicy", + "iam:ListAttachedRolePolicies", "iam:ListInstanceProfilesForRole", + "iam:ListRolePolicies", + "iam:ListRoles", + "iam:ListUserPolicies", + "iam:ListUsers", "iam:RemoveRoleFromInstanceProfile", - "sts:GetCallerIdentity" + "iam:TagRole", + "iam:TagUser", + "iam:UntagRole", + "iam:UntagUser" ], "Resource": "*" }, @@ -142,17 +142,16 @@ "Sid": "S3Bucket", "Effect": "Allow", "Action": [ - "s3:PutObject", + "s3:DeleteBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:GetBucketTagging", "s3:GetObject", "s3:ListAllMyBuckets", - "s3:CreateBucket", "s3:ListBucket", + "s3:PutObject", "s3:PutObjectTagging", - "s3:DeleteObject", - "s3:DeleteBucket", - "s3:putBucketTagging", - "s3:GetBucketTagging", - "s3:GetBucketLocation" + "s3:putBucketTagging" ], "Resource": "*" }, @@ -173,6 +172,15 @@ "cloudwatch:GetMetricData" ], "Resource": "*" + }, + { + "Sid": "RDS", + "Effect": "Allow", + "Action": [ + "rds:AddTagsToResource", + "rds:DescribeDBInstances" + ], + "Resource": "*" } ] } diff --git a/iam/clouds/aws/CloudGovernanceInfra/CloudGovernanceInfra.tar b/iam/clouds/aws/CloudGovernanceInfra/CloudGovernanceInfra.tar new file mode 100644 index 000000000..fa2c7bd08 Binary files /dev/null and b/iam/clouds/aws/CloudGovernanceInfra/CloudGovernanceInfra.tar differ diff --git a/iam/clouds/aws/CloudGovernanceReadPolicy.json b/iam/clouds/aws/CloudGovernanceInfra/CloudGovernanceReadPolicy.json similarity index 79% rename from iam/clouds/aws/CloudGovernanceReadPolicy.json rename to iam/clouds/aws/CloudGovernanceInfra/CloudGovernanceReadPolicy.json index a67c8b894..3b6e75c90 100644 --- a/iam/clouds/aws/CloudGovernanceReadPolicy.json +++ b/iam/clouds/aws/CloudGovernanceInfra/CloudGovernanceReadPolicy.json @@ -6,7 +6,13 @@ "Effect": "Allow", "Action": [ "ce:GetCostAndUsage", - "ce:GetCostForecast" + "ce:GetCostForecast", + "tag:GetResources", + "tag:TagResources", + "support:DescribeTrustedAdvisorCheckResult", + "support:DescribeTrustedAdvisorChecks", + "resource-explorer-2:ListViews", + "resource-explorer-2:Search" ], "Resource": "*" }, @@ -14,6 +20,7 @@ "Sid": "EC2AccountLevel", "Effect": "Allow", "Action": [ + "ec2:DeleteTags", "ec2:CreateTags" ], "Resource": [ @@ -38,29 +45,28 @@ "Sid": "EC2ResourceLevel", "Effect": "Allow", "Action": [ - "ec2:DescribeAddresses", - "ec2:DescribeInstances", + "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeLaunchConfigurations", - "ec2:DescribeRegions", + "ec2:DescribeAddresses", "ec2:DescribeDhcpOptions", - "ec2:DescribeSnapshots", + "ec2:DescribeImages", + "ec2:DescribeInstanceTypes", + "ec2:DescribeInstances", "ec2:DescribeInternetGateways", - "ec2:DescribeNetworkInterfaces", - "autoscaling:DescribeAutoScalingGroups", - "ec2:DescribeVolumes", + "ec2:DescribeNatGateways", "ec2:DescribeNetworkAcls", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeRegions", + "ec2:DescribeReservedInstances", "ec2:DescribeRouteTables", - "ec2:ReleaseAddress", - "ec2:AssociateDhcpOptions", - "ec2:DescribeTags", - "ec2:DescribeVpcPeeringConnections", - "ec2:DescribeNatGateways", "ec2:DescribeSecurityGroups", - "ec2:DescribeImages", - "ec2:DescribeVpcs", - "ec2:DescribeInstanceTypes", + "ec2:DescribeSnapshots", + "ec2:DescribeSubnets", + "ec2:DescribeTags", + "ec2:DescribeVolumes", "ec2:DescribeVpcEndpoints", - "ec2:DescribeSubnets" + "ec2:DescribeVpcPeeringConnections", + "ec2:DescribeVpcs" ], "Resource": "*" }, @@ -70,7 +76,8 @@ "Action": [ "elasticloadbalancing:DescribeTags", "elasticloadbalancing:AddTags", - "elasticloadbalancing:DescribeLoadBalancers" + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:RemoveTags" ], "Resource": "*" }, @@ -79,20 +86,20 @@ "Effect": "Allow", "Action": [ "iam:GetRole", - "iam:TagRole", - "iam:ListRoles", - "iam:ListUserPolicies", - "iam:CreateUser", - "iam:TagUser", - "iam:GetUserPolicy", - "iam:ListAttachedRolePolicies", - "iam:ListUsers", "iam:GetUser", + "iam:GetUserPolicy", "iam:ListAccessKeys", - "iam:ListRolePolicies", "iam:ListAccountAliases", + "iam:ListAttachedRolePolicies", "iam:ListInstanceProfilesForRole", - "sts:GetCallerIdentity" + "iam:ListRolePolicies", + "iam:ListRoles", + "iam:ListUserPolicies", + "iam:ListUsers", + "iam:TagRole", + "iam:TagUser", + "iam:UntagRole", + "iam:UntagUser" ], "Resource": "*" }, @@ -106,15 +113,14 @@ "Sid": "S3Bucket", "Effect": "Allow", "Action": [ - "s3:PutObject", + "s3:GetBucketLocation", + "s3:GetBucketTagging", "s3:GetObject", "s3:ListAllMyBuckets", - "s3:CreateBucket", "s3:ListBucket", + "s3:PutObject", "s3:PutObjectTagging", - "s3:putBucketTagging", - "s3:GetBucketTagging", - "s3:GetBucketLocation" + "s3:putBucketTagging" ], "Resource": "*" }, @@ -131,8 +137,17 @@ "Sid": "CloudWatch", "Effect": "Allow", "Action": [ - "cloudwatch:GetMetricData", - "cloudwatch:GetMetricStatistics" + "cloudwatch:GetMetricStatistics", + "cloudwatch:GetMetricData" + ], + "Resource": "*" + }, + { + "Sid": "RDS", + "Effect": "Allow", + "Action": [ + "rds:AddTagsToResource", + "rds:DescribeDBInstances" ], "Resource": "*" } diff --git a/iam/clouds/aws/CloudGovernanceInfra/README.md b/iam/clouds/aws/CloudGovernanceInfra/README.md new file mode 100644 index 000000000..acc4a04f6 --- /dev/null +++ b/iam/clouds/aws/CloudGovernanceInfra/README.md @@ -0,0 +1,80 @@ +## Create CloudGovernance Infra in the cloud + +#### Requirements + +- IAM User: to access cloud resources. +- IAM Policy: Least privilege principle +- S3-Bucket: To store the logs of cloud-governance policy runs. + +### Pre-requisites + +- Install [AWS-CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). +- Configure IAM Access credentials. + - Permissions required for the User. + ```json lines + { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "STS", + "Effect": "Allow", + "Action": "sts:GetCallerIdentity", + "Resource": "*" + }, + { + "Sid": "IAMPermissions", + "Effect": "Allow", + "Action": [ + "iam:CreateUser", + "iam:CreatePolicy", + "iam:DeleteUser", + "iam:DeletePolicy", + "iam:AttachUserPolicy", + "iam:CreateAccessKey" + ], + "Resource": "*" + }, + { + "Sid": "S3Bucket", + "Effect": "Allow", + "Action": [ + "s3:CreateBucket", + "s3:DeleteBucket" + ], + "Resource": "*" + } + ] + } + ``` + +Steps to create Cloud Governance Infra resources: + +- Download tar `CloudGovernanceInfra.tar` and untar the file. + +```shell +curl -L https://github.com/redhat-performance/cloud-governance/raw/main/iam/clouds/aws/CloudGovernanceInfra.tar | tar -xzvf - +``` + +- Change the permissions of the file `create_infra.sh`. + +```shell +chmod 700 create_infra.sh +``` + +- Create read user and create bucket. + +```shell +./create_infra.sh --username "$USERNAME" --s3-bucket-name "$BUCKET_NAME" +``` + +- Create only delete user + +```shell +./create_infra.sh --username "$USERNAME" --s3-bucket-name "$BUCKET_NAME" --policy-type delete +``` + +- To get help + +```shell +./create_infra.sh --help +``` diff --git a/iam/clouds/aws/CloudGovernanceInfra/create_infra.sh b/iam/clouds/aws/CloudGovernanceInfra/create_infra.sh new file mode 100755 index 000000000..a54a4d741 --- /dev/null +++ b/iam/clouds/aws/CloudGovernanceInfra/create_infra.sh @@ -0,0 +1,158 @@ +#!/bin/bash + +username="" +policy_type="read" +s3_bucket_name="" +show_help=false +AWS_DEFAULT_REGION=us-east-2 + +show_help() { + echo "Usage: $0 --username --s3-bucket-name [--policy-type ]" + echo "" + echo "Options:" + echo " --username Specify the IAM username to create." + echo " --policy-type (Optional) Specify the policy type to create and attach. Supported Values: read, delete." + echo " --s3-bucket-name (Optional) Specify the S3 bucket name to create." + echo " --help Display this help message." + echo "" + echo "Example:" + echo " $0 --username my-username --policy-type read --s3-bucket-name my-bucket" + echo " $0 --username my-username --s3-bucket-name my-bucket" + exit 0 +} + +to_title_case() { + echo "$1" | awk '{print toupper(substr($0,1,1)) tolower(substr($0,2))}' +} + +delete_user() { + aws iam delete-user --user-name "$1" 1>/dev/null + echo "Deleted IAM User $1 due to failures." +} + +delete_policy() { + aws iam delete-policy --policy-arn "$1" 1>/dev/null + echo "Deleted IAM Policy $1 due to failures." +} + +delete_bucket() { + aws s3 rb "s3://$1" --force 1>/dev/null + echo "Deleted S3 bucket $1 due to failures." +} + +create_bucket() { + if ! aws s3api create-bucket --bucket "$1" --region "$AWS_DEFAULT_REGION" --create-bucket-configuration LocationConstraint="$AWS_DEFAULT_REGION" 1>/dev/null; then + echo "Failed to create S3 bucket $1." + delete_user "$2" + if [ -n "$3" ]; then + delete_policy "$3" + fi + exit 1 + fi + echo "S3 bucket $1 created successfully." +} + +create_access_key() { + access_key_json=$(aws iam create-access-key --user-name "$1" --query 'AccessKey.[AccessKeyId,SecretAccessKey]' --output json) + if [ $? -ne 0 ]; then + echo "Failed to create access key for user $1." + delete_user "$1" + if [ -n "$3" ]; then + delete_bucket "$2" + fi + if [ -n "$3" ]; then + delete_policy "$3" + fi + exit 1 + fi + + access_key_id=$(echo "$access_key_json" | jq -r '.[0]') + secret_access_key=$(echo "$access_key_json" | jq -r '.[1]') + + echo "Access Key ID: $access_key_id" + echo "Secret Access Key: $secret_access_key" +} + +create_user() { + if ! aws iam create-user --user-name "$1" --tags "Key=User,Value=$1" 1>/dev/null; then + echo "Failed to create user $1." + exit 1 + fi + echo "User $1 created successfully." +} + + + +while [[ "$#" -gt 0 ]]; do + case $1 in + --username) username="$2"; shift ;; + --policy-type) policy_type="$2"; shift ;; + --s3-bucket-name) s3_bucket_name="$2"; shift ;; + --help) show_help=true ;; + *) echo "Unknown parameter passed: $1"; show_help ;; + esac + shift +done + +if [ "$show_help" = true ]; then + show_help +fi + + +if [ -z "$username" ] ; then + echo "Error: --username and --s3-bucket-name are required." + show_help +fi + +if [ -n "$policy_type" ]; then + case "$(to_title_case "$policy_type")" in + Read|Delete) policy_type=$(to_title_case "$policy_type") ;; + *) echo "Error: Unsupported policy type '$policy_type'. Supported values are: Read, Delete."; exit 1 ;; + esac +fi + +policy_document="./CloudGovernance${policy_type}Policy.json" +account_id=$(aws sts get-caller-identity --query 'Account' --output text) +if [ $? -ne 0 ]; then + echo "Failed to retrieve AWS account ID." + exit 1 +fi +echo "AWS Account ID: $account_id" + +if [ -n "$account_id" ]; then + sed -i '' -e "s/account_id/${account_id}/g" "$policy_document" +fi + +create_user "$username" + +if [ -n "$policy_type" ]; then + policy_name="CloudGovernance${policy_type}" + + if [ ! -f "$policy_document" ]; then + echo "Error: Policy document file $policy_document does not exist." + delete_user "$username" + exit 1 + fi + + policy_arn=$(aws iam create-policy --policy-name "$policy_name" --policy-document "file://$policy_document" --query 'Policy.Arn' --output text) + if [ $? -ne 0 ]; then + echo "Failed to create policy $policy_name." + delete_user "$username" + exit 1 + fi + echo "Policy $policy_name created successfully with ARN $policy_arn." + + if ! aws iam attach-user-policy --user-name "$username" --policy-arn "$policy_arn"; then + echo "Failed to attach policy $policy_name to user $username." + delete_policy "$policy_arn" + delete_user "$username" + exit 1 + fi + echo "Policy $policy_name attached to user $username successfully." +fi +if [ -n "$s3_bucket_name" ]; then + create_bucket "$s3_bucket_name" "$username" "$policy_arn" +fi + + +create_access_key "$username" "$s3_bucket_name" "$policy_arn" diff --git a/jenkins/tenant/aws/README.md b/jenkins/tenant/aws/README.md index afcae3a85..3191ef335 100644 --- a/jenkins/tenant/aws/README.md +++ b/jenkins/tenant/aws/README.md @@ -1,12 +1,15 @@ # How to run cloud-governance on Tenant Accounts Steps -1. Create AWS User and attach user by [CloudGovernanceDeletePolicy.json](../../../iam/clouds/aws/CloudGovernanceDeletePolicy.json). [ Note: Replace account_id with actual account id] + +1. Create AWS User and attach user + by [CloudGovernanceDeletePolicy.json](../../../iam/clouds/aws/CloudGovernanceCloudCreds/CloudGovernanceDeletePolicy.json). [ Note: Replace account_id with actual account id] 2. Create S3 bucket 3. Add kind secret-text to jenkins with below naming conventions - 1. ${account_name}-aws-access-key-id - 2. ${account_name}-aws-secret-key-id - 3. ${account_name}-s3-bucket + 1. ${account_name}-aws-access-key-id + 2. ${account_name}-aws-secret-key-id + 3. ${account_name}-s3-bucket 4. Create folder named that you want to run the cloud-governance policies and copy the file in templates. -5. Add account_name to account variable in this [PolicyJenkinsfileDaily](../aws/template/PolicyJenkinsfileDaily) and [TaggingJenkinsfileHourly](../aws/template/TaggingJenkinsfileHourly). +5. Add account_name to account variable in this [PolicyJenkinsfileDaily](../aws/template/PolicyJenkinsfileDaily) + and [TaggingJenkinsfileHourly](../aws/template/TaggingJenkinsfileHourly). 6. Create two Jenkins jobs by using this two Jenkinsfile