CloudPloy

Docs

Connect AWS

Create one role, one policy and one user in your AWS account, then paste the user's access key into CloudPloy.

Setup steps

  1. 1

    Create the EC2 instance role

    Sign in to the AWS account you want to use as an administrator. In IAM, create a role for EC2 and name it exactly as the CloudPloy connect screen shows. The name looks like CloudPloyEc2SsmRole-4. Paste this trust policy if you use a custom trust policy, then attach AmazonSSMManagedInstanceCore. The console creates the instance profile with the same name.

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "ec2.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
  2. 2

    Attach the instance policy

    On that role, attach this managed policy.

    arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
  3. 3

    Create the CloudPloyAccess policy

    In IAM, choose Policies, then Create policy, and switch to the JSON tab. Paste the document below and name the policy CloudPloyAccess. Replace CloudPloyEc2SsmRole-TEAMID with your role name; the CloudPloy connect screen shows a copy with it already filled in. The policy lets the key manage only servers CloudPloy created.

    Jump to the policy
  4. 4

    Create the IAM user

    Create a user named cloudploy without console access. Under permissions choose Attach policies directly and select CloudPloyAccess.

  5. 5

    Create the access key and paste it

    Open the cloudploy user, choose Security credentials, then Create access key. Choose Application running outside AWS. Copy the access key ID and the secret access key, then paste both into CloudPloy. CloudPloy connects as soon as you save.

    Open CloudPloy and paste the key

Policy to paste

CloudPloyAccess permissions

Name the policy CloudPloyAccess. Anything that changes or deletes an existing resource is limited to resources tagged CreatedBy=CloudPloy, so the key cannot touch the rest of the account. When CloudPloy needs more permissions, the connect screen shows a new version: open the policy, choose Edit, paste it and save.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadInventory",
      "Effect": "Allow",
      "Action": [
        "ec2:Describe*",
        "ssm:DescribeInstanceInformation",
        "ssm:GetCommandInvocation",
        "cloudwatch:GetMetricData",
        "cloudwatch:GetMetricStatistics",
        "cloudwatch:ListMetrics"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ReadPublicImageParameters",
      "Effect": "Allow",
      "Action": [
        "ssm:GetParameter",
        "ssm:GetParameters"
      ],
      "Resource": "arn:aws:ssm:*::parameter/aws/service/*"
    },
    {
      "Sid": "CreateTaggedServerResources",
      "Effect": "Allow",
      "Action": [
        "ec2:RunInstances",
        "ec2:CreateVolume"
      ],
      "Resource": [
        "arn:aws:ec2:*:*:instance/*",
        "arn:aws:ec2:*:*:volume/*",
        "arn:aws:ec2:*:*:network-interface/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:RequestTag/CreatedBy": "CloudPloy"
        }
      }
    },
    {
      "Sid": "LaunchIntoOwnGroupsAndKeys",
      "Effect": "Allow",
      "Action": "ec2:RunInstances",
      "Resource": [
        "arn:aws:ec2:*:*:security-group/*",
        "arn:aws:ec2:*:*:key-pair/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/CreatedBy": "CloudPloy"
        }
      }
    },
    {
      "Sid": "LaunchIntoSubnets",
      "Effect": "Allow",
      "Action": "ec2:RunInstances",
      "Resource": "arn:aws:ec2:*:*:subnet/*"
    },
    {
      "Sid": "LaunchPublicImages",
      "Effect": "Allow",
      "Action": "ec2:RunInstances",
      "Resource": "arn:aws:ec2:*::image/*",
      "Condition": {
        "Bool": {
          "ec2:Public": "true"
        }
      }
    },
    {
      "Sid": "CreateGroupsKeysAndAddresses",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateSecurityGroup",
        "ec2:CreateKeyPair",
        "ec2:AllocateAddress"
      ],
      "Resource": "*"
    },
    {
      "Sid": "TagWhatItCreates",
      "Effect": "Allow",
      "Action": "ec2:CreateTags",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "ec2:CreateAction": [
            "RunInstances",
            "CreateSecurityGroup",
            "CreateKeyPair",
            "AllocateAddress",
            "CreateVolume"
          ]
        }
      }
    },
    {
      "Sid": "ManageOwnedResources",
      "Effect": "Allow",
      "Action": [
        "ec2:StartInstances",
        "ec2:StopInstances",
        "ec2:RebootInstances",
        "ec2:TerminateInstances",
        "ec2:ModifyInstanceAttribute",
        "ec2:AssociateAddress",
        "ec2:DisassociateAddress",
        "ec2:ReleaseAddress",
        "ec2:AuthorizeSecurityGroupIngress",
        "ec2:RevokeSecurityGroupIngress",
        "ec2:DeleteSecurityGroup",
        "ec2:DeleteKeyPair",
        "ec2:AttachVolume",
        "ec2:DetachVolume",
        "ec2:ModifyVolume",
        "ec2:DeleteVolume"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/CreatedBy": "CloudPloy"
        }
      }
    },
    {
      "Sid": "UseOwnedServers",
      "Effect": "Allow",
      "Action": [
        "ssm:SendCommand",
        "ec2:GetConsoleOutput"
      ],
      "Resource": "arn:aws:ec2:*:*:instance/*",
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/CreatedBy": "CloudPloy"
        }
      }
    },
    {
      "Sid": "RunShellScriptDocument",
      "Effect": "Allow",
      "Action": "ssm:SendCommand",
      "Resource": "arn:aws:ssm:*::document/AWS-RunShellScript"
    },
    {
      "Sid": "UseTheInstanceRole",
      "Effect": "Allow",
      "Action": [
        "iam:GetRole",
        "iam:GetInstanceProfile",
        "iam:PassRole"
      ],
      "Resource": [
        "arn:aws:iam::*:role/CloudPloyEc2SsmRole-TEAMID",
        "arn:aws:iam::*:instance-profile/CloudPloyEc2SsmRole-TEAMID"
      ],
      "Condition": {
        "StringEqualsIfExists": {
          "iam:PassedToService": "ec2.amazonaws.com"
        }
      }
    }
  ]
}