Skip to main content

Cloud Labs: Bring Your Own AWS Account - Advanced

Advanced setup steps to enable AWS Cloud Labs while granting Vocareum minimal access to your AWS account.

Matthew avatar
Written by Matthew
Updated yesterday

For Admins

To provision AWS resources in Cloud Labs, you first need to grant Vocareum permission to manage relevant aspects of your AWS account.

Permission is configured using AWS Identity and Access Management (IAM). For further context, refer to the following AWS documentation: access to AWS accounts owned by third parties.

We support two options for connecting your AWS account to Vocareum: a standard flow and an advanced flow.

Standard Flow

In the standard flow, you create an IAM Role that grants Vocareum permission to generate and manage AWS accounts and policies. This reduces the complexity of the initial setup process and gives Vocareum more access to troubleshoot linked account issues on your behalf.

Vocareum clients have used this process for over a decade, and we have found it serves most organizations well.

The standard flow for connecting AWS with Vocareum can be found here: Cloud Labs: Bring Your Own AWS Account.

Advanced Flow

However, if your internal security policies require you to restrict third-party AWS access more than our standard flow allows, we also support the advanced process detailed in the following guide.

In this advanced flow, you will perform additional setup steps, such as generating linked accounts and policies manually, to reduce the AWS permissions Vocareum requires to manage your Cloud Lab resources.


Advanced AWS BYO Account Checklist

In your Payer account:

Vocareum will perform the following steps after your linked accounts are uploaded:

  • Import the AWS account list into our tables.

  • Use the 'vocareum' role to access the linked accounts.

  • Perform setup and verification in linked AWS accounts.

  • Activate your BYO Payer account.


Set up your AWS Payer account

Create an AWS Payer Account, Organization, and billing bucket

For data and billing isolation purposes, we recommend creating a new, standalone AWS account for Vocareum rather than using an existing account. This new AWS account will serve as your AWS Payer.

  1. Create a standalone AWS account. AWS guide: Create an AWS account

  2. Create an administrator user to manage your Payer account, so that you do not need to use the Root user for day-to-day operations. AWS guide: Create an administrator user

  3. In your AWS Payer account, go to the AWS Organization console and create an Organization Root. Your AWS Payer Account will serve as the management account for the organization. AWS guide: Creating an organization with AWS Organizations

  4. In the AWS Organization console, create an Organizational Unit (OU) under the Organization Root. AWS guide: Creating an organizational unit (OU) with AWS Organizations

  5. Navigate to the S3 service and create a new S3 bucket in the us-east-1 region. Vocareum will perform the remaining configuration to make this the AWS billing bucket for your AWS Payer. AWS guide: Creating a general purpose bucket


Enable Service Control Policies (SCPs)

  1. Navigate to AWS Organizations

  2. In the left side menu, select Policies

  3. Scroll to the "Supported policy types" section

  4. Enable "Service control policies"


Create the Vocareum Administrator IAM Role

1. Starting with an unused AWS payer account, navigate to IAM roles in the AWS console and create a new role.

2. Choose Another AWS account from the four options presented. In the Account ID field, please enter 117530877863 and verify that the number was entered correctly before proceeding.

Optionally, you can check the option 'Require external ID' and enter a string of your choice in the field. Note down the ID so you can provide it to Vocareum during a later step. The external ID can be any string of your choice. Vocareum will pass this ID to AWS when assuming the vocareumadmin role for additional security.

Click 'Next'.

3. Skip Add permission for now and click 'Next' at the end of the page. We will add the permission after the role is created.

4. Please enter vocareumadmin as the Role name. The name must be entered correctly for us to assume the role. You may enter 'Admin Access for Vocareum' in the Description, but this is not required.

Again we do not add the permission in this step. You may add tags if needed.

Click 'Create role' to finish creating the role.

5. After the role is created. In the Permission tab, click 'Add permissions' and select 'Select inline policy'.

Choose JSON format and cut and paste the following policy into the policy editor:

Please replace the my-billing-bucket with the name of your billing bucket name.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"organizations:Describe*",
"organizations:List*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:List*",
"s3:Get*"
],
"Resource": "arn:aws:s3:::<<my-billing-bucket>>"
},
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"arn:aws:iam::*:role/vocareum",
"arn:aws:iam::*:role/voclabs"
]
}
]
}

Click 'Next'.

Enter 'vocareumadmin-policy' as the policy name. (the name is not critical).

Then click 'Create policy' to create the policy.

6. Back to the 'vocareumadmin' role page, edit the maximum session duration from 1 hour to 12 hours.

Click 'Edit'.

Set the duration to 12 hours, then click 'Save changes'.

The 'vocareumadmin' role setup is completed.


Enable Billing Reports

1. Click on your account name in the navigation bar to open the drop-down menu. Then, click My Account to navigate to the account settings page.

2. Scroll down to the IAM User and Role Access to Billing Information section.

Check the box next to Activate IAM Access and then click Update.

3. In the Billing and Cost Management Console, choose 'Billing Preferences' from the left panel.

Click' Edit' to configure your billing bucket to receive the bill files.

4. In the S3 Console, enable the vocareumadmin role to retrieve bill files from you billing bucket by doing the following:

Choose your billing bucket from the S3 console, then choose the 'Permissions' tab and scroll to the Bucket policy section.

Click 'Edit' the edit the bucket policy, add the following statement to the policy

{
"Sid": "StmtPayerAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<<you payer account id>>:role/vocareumadmin"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<<your billing bucket>>/*"
}

Save the changes to update the policy.


Request an AWS member account quota increase

When you use AWS Cloud Labs, Vocareum creates member accounts in your AWS organization, configures them, and makes them available to your users through assignments. As such, you will need one or more AWS accounts available per student per assignment.

By default, AWS Organizations have a quota of 10 member accounts, including the Organization Management account. This means you will initially have a maximum quota of 9 accounts available for use in Vocareum Cloud Labs.

You can request an increase to your Organization's "default maximum number of accounts" quota in AWS. Only the Management account of an organization can submit this request. The maximum account quota for an AWS organization is 10,000.

For more information, refer to the AWS documentation on quotas and service limits for AWS Organizations.

1. Log into the Management account for the Organization you set up for Vocareum

2. Navigate to Service Quotas

3. Select AWS services from the left side menu

4. On the AWS services page, locate and select AWS Organizations

5. Select the quota named "Default maximum number of accounts"

6. Click the button to "Request increase at account level"

7. In the request modal that appears, enter your desired number of accounts in the "Increase quota value" field.

8. Click the Request button to submit your request.

AWS may take a few hours or even days to approve a quota increase request, as noted on their quota request form:

"Approvals: For some services, smaller increases are automatically approved, while larger requests are submitted to AWS Support.

Approval timeline: AWS Support can approve, deny, or partially approve your requests. Larger increase requests take more time to process and assess while we work with the service team."


Create and apply a set of protective SCPs

Vocareum uses a set of Service Control Policies (SCPs) to protect account management roles and resources and to prevent account abuse.

Create and apply the SCPs outlined below.

Root SCPs:

  1. FullAWSAccess

  2. VocProtections

  3. VocUnconditionalDeny

OU SCPs:

  1. FullAWSAccess

  2. ConditionalDeny

  3. RestrictRegions

  4. AllowServices

JSON for each SCP can be found in the following sections:

FullAWSAccess

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}

VocProtections

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"iam:DetachRolePolicy",
"iam:DeleteRolePolicy",
"iam:DeleteRole",
"iam:GetRolePolicy",
"iam:PutRolePolicy"
],
"Resource": [
"arn:aws:iam::*:role/vocareum"
]
},
{
"Effect": "Deny",
"Action": [
"iam:DetachRolePolicy",
"iam:DeleteRolePolicy",
"iam:DeleteRole",
"iam:GetRolePolicy",
"iam:PutRolePolicy"
],
"Resource": [
"arn:aws:iam::*:role/vocareum-eventbridge"
],
"Condition": {
"StringNotLikeIfExists": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/vocareum"
]
}
}
},
{
"Effect": "Deny",
"Action": [
"iam:GetRole",
"iam:GetRolePolicy",
"iam:UpdateAssumeRolePolicy",
"iam:UntagRole",
"iam:TagRole",
"iam:PutRolePolicy",
"iam:PutRolePermissionsBoundary",
"iam:AddRoleToInstanceProfile",
"iam:PassRole",
"iam:ListRolePolicies",
"iam:AttachRolePolicy",
"iam:UpdateRole",
"iam:RemoveRoleFromInstanceProfile",
"iam:UpdateRoleDescription"
],
"Resource": [
"arn:aws:iam::*:role/vocareum",
"arn:aws:iam::*:role/vocareum-eventbridge"
],
"Condition": {
"StringNotLikeIfExists": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/vocareum"
]
}
}
},
{
"Sid": "IAMVocLabsDefaultPolicyMirror",
"Effect": "Deny",
"Action": [
"iam:DeletePolicy",
"iam:DeletePolicyVersion",
"iam:CreatePolicy",
"iam:CreatePolicyVersion",
"iam:GetPolicy",
"iam:GetPolicyVersion"
],
"Resource": [
"arn:aws:iam::*:policy/voc-cancel-cred",
"arn:aws:iam::*:policy/Pvoclabs*",
"arn:aws:iam::*:policy/Pvocuser*"
],
"Condition": {
"StringNotLikeIfExists": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/vocareum"
]
}
}
},
{
"Sid": "IAMVocLabsDefaultRoleMirror",
"Effect": "Deny",
"Action": [
"iam:GetRole",
"iam:AttachRolePolicy",
"iam:DetachRolePolicy",
"iam:DeleteRolePolicy",
"iam:DeleteRole",
"iam:DeleteRolePermissionsBoundary",
"iam:PutRolePermissionsBoundary",
"iam:UpdateAssumeRolePolicy",
"iam:UpdateRole",
"iam:UpdateRoleDescription",
"iam:GetRolePolicy"
],
"Resource": [
"arn:aws:iam::*:role/voclabs"
],
"Condition": {
"StringNotLikeIfExists": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/vocareum"
]
}
}
},
{
"Sid": "IAMVocLabsDefaultUserMirror",
"Effect": "Deny",
"Action": [
"iam:GetUser",
"iam:CreateAccessKey",
"iam:DeleteAccessKey",
"iam:UpdateAccessKey",
"iam:AttachUserPolicy",
"iam:DetachUserPolicy",
"iam:DeleteUserPolicy",
"iam:DeleteUser",
"iam:GetUserPolicy",
"iam:AddUserToGroup",
"iam:DeleteUserPermissionsBoundary",
"iam:PutUserPermissionsBoundary",
"iam:UpdateUser"
],
"Resource": [
"arn:aws:iam::*:user/vocuser"
],
"Condition": {
"StringNotLikeIfExists": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/vocareum"
]
}
}
},
{
"Sid": "ProtectEventBridge",
"Effect": "Deny",
"Action": [
"events:*"
],
"Resource": [
"arn:aws:events:*:*:rule/voc-*"
],
"Condition": {
"ArnNotLike": {
"aws:PrincipalArn": "arn:aws:iam::*:role/vocareum"
}
}
}
]
}

VocUnconditionalDeny

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUnconditional",
"Effect": "Deny",
"Action": [
"mobiletargeting:*",
"sms-voice:*",
"ses:*",
"comprehendmedical:*",
"clouddirectory:*",
"lightsail:*",
"eks:CreateEksAnywhereSubscription",
"quicksight:CreateAccountSubscription",
"quicksight:Subscribe",
"ec2:AcceptReservedInstancesExchangeQuote",
"ec2:CancelCapacityReservation",
"ec2:CancelReservedInstancesListing",
"ec2:CopyFpgaImage",
"ec2:CreateCapacityReservation",
"ec2:CreateCapacityReservationFleet",
"ec2:CreateCustomerGateway",
"ec2:CreateFpgaImage",
"ec2:CreateReservedInstancesListing",
"ec2:CreateSpotDatafeedSubscription",
"ec2:DeleteFpgaImage",
"ec2:DeleteQueuedReservedInstances",
"ec2:DeleteSpotDatafeedSubscription",
"ec2:DescribeCapacityReservations",
"ec2:DescribeFastSnapshotRestores",
"ec2:DescribeFpgaImage*",
"ec2:DescribeHostReservationOfferings",
"ec2:DescribeHostReservations",
"ec2:DescribeReserved*",
"ec2:DescribeScheduled*",
"ec2:DisableFastSnapshotRestores",
"ec2:EnableFastSnapshotRestores",
"ec2:GetCapacityReservationUsage",
"ec2:GetGroupsForCapacityReservation",
"ec2:GetHostReservationPurchasePreview",
"ec2:GetReservedInstancesExchangeQuote",
"ec2:ModifyCapacityReservation",
"ec2:ModifyFpgaImageAttribute",
"ec2:ModifyInstanceCapacityReservationAttributes",
"ec2:ModifyReservedInstances",
"ec2:ModifySpotFleetRequest",
"ec2:Purchase*",
"ec2:ResetFpgaImageAttribute",
"ec2:RunScheduledInstances",
"glacier:GetVaultLock",
"glacier:AbortVaultLock",
"glacier:CompleteVaultLock",
"glacier:InitiateVaultLock",
"glacier:PurchaseProvisionedCapacity",
"glacier:CreateVault",
"glacier:InitiateMultipartUpload",
"glacier:InitiateJob",
"glacier:SetDataRetrievalPolicy",
"glacier:SetVaultAccessPolicy",
"glacier:DeleteVaultAccessPolicy",
"redshift:PurchaseReservedNodeOffering",
"redshift:GetReservedNodeExchangeOfferings",
"redshift:DescribeReservedNode*",
"redshift:AcceptReservedNodeExchange",
"rds:DescribeReservedDBInstances*",
"rds:PurchaseReservedDBInstancesOffering",
"dynamodb:DescribeReservedCapacity*",
"dynamodb:PurchaseReservedCapacityOfferings",
"route53domains:RegisterDomain",
"s3:PutObjectRetention",
"s3:GetObjectRetention",
"s3:GetObjectLegalHold",
"s3:PutObjectLegalHold",
"s3:GetBucketObjectLockConfiguration",
"s3:PutBucketObjectLockConfiguration",
"s3:PutAccelerateConfiguration",
"aws-portal:ModifyBilling",
"aws-portal:ModifyAccount",
"aws-portal:ModifyPaymentMethods",
"aws-portal:ViewAccount",
"aws-portal:ViewPaymentMethods",
"es:DescribeReservedElasticsearchInstanceOfferings",
"es:DescribeReservedElasticsearchInstances",
"es:PurchaseReservedElasticsearchInstanceOffering",
"elasticache:DescribeReservedCacheNodes",
"elasticache:DescribeReservedCacheNodesOfferings",
"elasticache:PurchaseReservedCacheNodesOffering",
"cloudfront:CreateMonitoringSubscription",
"cloudfront:CreateOriginRequestPolicy",
"cloudfront:CreateStreamingDistributionWithTags",
"cloudfront:CreateStreamingDistribution",
"cloudfront:CreateRealtimeLogConfig",
"cloudfront:CreatePublicKey",
"cloudfront:CreateKeyGroup",
"cloudfront:CreateInvalidation",
"cloudfront:CreateFunction",
"cloudfront:CreateFieldLevelEncryptionProfile",
"cloudfront:CreateFieldLevelEncryptionConfig",
"cloudfront:CreateCloudFrontOriginAccessIdentity",
"cloudfront:CreateCachePolicy",
"cloudfront:CreateDistribution"
],
"Resource": [
"*"
],
"Condition": {
"StringNotLikeIfExists": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/vocareum"
]
}
}
},
{
"Effect": "Deny",
"Action": [
"aws-marketplace:Subscribe"
],
"Resource": "*",
"Condition": {
"ForAnyValue:StringNotEquals": {
"aws-marketplace:ProductId": [
"1d288c71-65f9-489a-a3e2-9c7f4f6e6a85",
"cc0bdd50-279a-40d8-829c-4009b77a1fcc",
"prod-dr2vpvd4k73aq",
"c468b48a-84df-43a4-8c46-8870630108a7",
"b0eb9475-3a2c-43d1-94d3-56756fd43737",
"prod-6dw3qvchef7zy",
"prod-m5ilt4siql27k",
"prod-ozonys2hmmpeu",
"prod-fm3feywmwerog",
"a61c46fe-1747-41aa-9af0-2e0ae8a9ce05",
"216b69fd-07d5-4c7b-866b-936456d68311",
"prod-tukx4z3hrewle",
"prod-nb4wqmplze2pm",
"b7568428-a1ab-46d8-bab3-37def50f6f6a",
"38e55671-c3fe-4a44-9783-3584906e7cad",
"prod-ariujvyzvd2qy",
"prod-2c2yc2s3guhqy",
"prod-2lvuzn4iy6n6o"
]
}
}
},
{
"Resource": [
"*"
],
"Action": [
"aws-marketplace:Subscribe"
],
"Effect": "Deny",
"Condition": {
"Null": {
"aws-marketplace:ProductId": "true"
}
}
},
{
"Effect": "Allow",
"Action": [
"aws-marketplace:Unsubscribe",
"aws-marketplace:ViewSubscriptions"
],
"Resource": "*"
}
]
}

ConditionalDeny

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RestrictRDS",
"Effect": "Deny",
"Action": "rds:*",
"Resource": [
"*"
],
"Condition": {
"ForAnyValue:StringNotLikeIfExists": {
"rds:DatabaseClass": [
"*.micro",
"*.small",
"*.medium"
],
"rds:DatabaseEngine": [
"aurora-mysql",
"aurora-postgresql",
"mysql",
"postgres",
"mariadb"
]
},
"NumericGreaterThanIfExists": {
"rds:StorageSize": "100"
}
}
},
{
"Sid": "RestrictEC2",
"Effect": "Deny",
"Action": "ec2:*",
"Resource": [
"*"
],
"Condition": {
"StringNotEqualsIfExists": {
"ec2:Tenancy": [
"default"
]
},
"ForAnyValue:StringNotLike": {
"ec2:InstanceType": [
"*.large",
"*.medium",
"*.small",
"*.micro",
"*.nano"
]
},
"NumericGreaterThanIfExists": {
"ec2:VolumeSize": "50",
"ec2:VolumeIops": "0"
},
"StringEqualsIfExists": {
"ec2:PlacementGroupStrategy": "cluster"
},
"StringNotLikeIfExists": {
"ec2:VolumeType": [
"gp2"
]
}
}
},
{
"Sid": "RestrictASG",
"Effect": "Deny",
"Action": "autoscaling:CreateLaunchConfiguration",
"Resource": "*",
"Condition": {
"ForAnyValue:StringNotLikeIfExists": {
"autoscaling:InstanceType": [
"*.nano",
"*.micro",
"*.small",
"*.medium"
]
}
}
},
{
"Sid": "SageMakerPilotSpecificInstances",
"Effect": "Deny",
"Action": [
"sagemaker:CreateNotebookInstance",
"sagemaker:UpdateNotebookInstance",
"sagemaker:CreateTrainingJob",
"sagemaker:CreateTransformJob",
"sagemaker:CreateEndpointConfig",
"sagemaker:CreateHyperParameterTuningJob"
],
"Resource": "*",
"Condition": {
"ForAnyValue:StringNotEquals": {
"sagemaker:InstanceTypes": [
"ml.c5.xlarge",
"ml.m5.xlarge",
"ml.c4.xlarge",
"ml.m4.xlarge",
"ml.t2.medium",
"ml.t2.large",
"ml.t3.medium",
"ml.t3.large",
"ml.c5.large",
"ml.m5.large"
]
}
}
},
{
"Sid": "Cloud9SpecificInstances",
"Effect": "Deny",
"Action": "cloud9:CreateEnvironmentEC2",
"Resource": "*",
"Condition": {
"ForAnyValue:StringNotLike": {
"cloud9:InstanceType": [
"*.micro",
"*.nano",
"*.small",
"*.medium"
]
}
}
}
]
}

RestrictRegions

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RestrictRegions",
"Effect": "Deny",
"Action": [
"access-analyzer:*",
"account:ListRegions",
"acm:*",
"airflow:*",
"amplify:*",
"apigateway:*",
"application-autoscaling:*",
"appmesh:*",
"appsync:*",
"arsenal:*",
"artifact:*",
"athena:*",
"autoscaling:*",
"backup:*",
"batch:*",
"ce:*",
"cloud9:*",
"cloudformation:*",
"cloudfront:*",
"cloudsearch:*",
"cloudshell:*",
"cloudtrail:*",
"cloudwatch:*",
"codeartifact:*",
"codebuild:*",
"codecommit:*",
"codedeploy:*",
"codepipeline:*",
"codestar:*",
"codestar-notifications:*",
"cognito-identity:*",
"cognito-idp:*",
"cognito-sync:*",
"comprehend:*",
"comprehendmedical:*",
"compute-optimizer:*",
"config:*",
"cur:*",
"databrew:*",
"datapipeline:*",
"deepcomposer:*",
"deeplens:*",
"deepracer:*",
"dms:*",
"dynamodb:*",
"ebs:*",
"ec2:*",
"ec2-instance-connect:*",
"ec2messages:*",
"ecr:*",
"ecs:*",
"eks:*",
"elasticache:*",
"elasticbeanstalk:*",
"elasticfilesystem:*",
"elasticloadbalancing:*",
"elasticmapreduce:*",
"elastictranscoder:*",
"events:*",
"execute-api:*",
"firehose:*",
"forecast:*",
"gamelift:*",
"glacier:*",
"glue:*",
"greengrass:*",
"groundtruthlabeling:*",
"guardduty:*",
"health:*",
"iam:*",
"imagebuilder:*",
"inspector:*",
"iot:*",
"iot1click:*",
"iotanalytics:*",
"kendra:*",
"kinesis:*",
"kinesisanalytics:*",
"kinesisvideo:*",
"kms:*",
"lakeformation:*",
"lambda:*",
"lex:*",
"lightsail:*",
"logs:*",
"machinelearning:*",
"neptune-db:*",
"opsworks:*",
"personalize:*",
"polly:*",
"quicksight:*",
"rds:*",
"redshift:*",
"redshift-data:*",
"rekognition:*",
"resource-explorer:*",
"resource-groups:*",
"robomaker:*",
"route53:*",
"s3:*",
"sagemaker:*",
"schemas:*",
"secretsmanager:*",
"securityhub:*",
"serverlessrepo:*",
"servicecatalog:*",
"sns:*",
"sqs:*",
"ssm:*",
"ssmmessages:*",
"storagegateway:*",
"sts:*",
"swf:*",
"tag:*",
"textract:*",
"timestream:*",
"transcribe:*",
"translate:*",
"trustedadvisor:*",
"waf:*",
"waf-regional:*",
"wafv2:*",
"wellarchitected:*",
"xray:*"
],
"Resource": [
"*"
],
"Condition": {
"StringNotEqualsIfExists": {
"aws:RequestedRegion": [
"us-east-1"
]
}
}
}
]
}

AllowSevices

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": "*",
"Resource": "*"
},
{
"Sid": "CombinedFullAccess",
"Effect": "Deny",
"NotAction": [
"access-analyzer:*",
"account:ListRegions",
"acm:*",
"airflow:*",
"amplify:*",
"apigateway:*",
"application-autoscaling:*",
"appmesh:*",
"appsync:*",
"arsenal:*",
"artifact:*",
"athena:*",
"autoscaling:*",
"backup:*",
"batch:*",
"ce:*",
"cloud9:*",
"cloudformation:*",
"cloudfront:*",
"cloudsearch:*",
"cloudshell:*",
"cloudtrail:*",
"cloudwatch:*",
"codeartifact:*",
"codebuild:*",
"codecommit:*",
"codedeploy:*",
"codepipeline:*",
"codestar:*",
"codestar-notifications:*",
"cognito-identity:*",
"cognito-idp:*",
"cognito-sync:*",
"comprehend:*",
"comprehendmedical:*",
"compute-optimizer:*",
"config:*",
"cur:*",
"databrew:*",
"datapipeline:*",
"deepcomposer:*",
"deeplens:*",
"deepracer:*",
"dms:*",
"dynamodb:*",
"ebs:*",
"ec2:*",
"ec2-instance-connect:*",
"ec2messages:*",
"ecr:*",
"ecs:*",
"eks:*",
"elasticache:*",
"elasticbeanstalk:*",
"elasticfilesystem:*",
"elasticloadbalancing:*",
"elasticmapreduce:*",
"elastictranscoder:*",
"events:*",
"execute-api:*",
"firehose:*",
"forecast:*",
"gamelift:*",
"glacier:*",
"glue:*",
"greengrass:*",
"groundtruthlabeling:*",
"guardduty:*",
"health:*",
"iam:*",
"imagebuilder:*",
"inspector:*",
"iot:*",
"iot1click:*",
"iotanalytics:*",
"kendra:*",
"kinesis:*",
"kinesisanalytics:*",
"kinesisvideo:*",
"kms:*",
"lakeformation:*",
"lambda:*",
"lex:*",
"lightsail:*",
"logs:*",
"machinelearning:*",
"neptune-db:*",
"opsworks:*",
"personalize:*",
"polly:*",
"quicksight:*",
"rds:*",
"redshift:*",
"redshift-data:*",
"rekognition:*",
"resource-explorer:*",
"resource-groups:*",
"robomaker:*",
"route53:*",
"s3:*",
"sagemaker:*",
"schemas:*",
"secretsmanager:*",
"securityhub:*",
"serverlessrepo:*",
"servicecatalog:*",
"sns:*",
"sqs:*",
"ssm:*",
"ssmmessages:*",
"storagegateway:*",
"sts:*",
"swf:*",
"tag:*",
"textract:*",
"timestream:*",
"transcribe:*",
"translate:*",
"trustedadvisor:*",
"waf:*",
"waf-regional:*",
"wafv2:*",
"wellarchitected:*",
"xray:*"
],
"Resource": [
"*"
],
"Condition": {
"ArnNotLikeIfExists": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/vocareum"
]
}
}
}
]
}


Add your AWS Payer to Vocareum

1. Go to the Vocareum Control Center and select AWS from the sidebar.

2. Open the AWS Payers page.

3. Click the '+ Add payer' button to open the Add Payer form.

4. Complete the fields in the Add Payer form, including:

  • Account ID: input your AWS Payer account ID

  • Access Type: Select 'IAM Role' in the Access selection

  • External ID (Optional): Enter a string that Vocareum will pass to AWS when assuming the vocareumadmin role for additional security.

  • Billing bucket: Input the name of the S3 bucket you created in us-east-1 for billing reports.

  • Root ID: Enter the root ID of your Payer account.

  • Organization Unit ID: Input the ID of the OU you created in your Payer account.

  • Linked member account quota: Enter the number of accounts currently available from your Payer account quota. The quota is typically 9 for new accounts. If AWS has approved your account quota increase request, your quota may be higher.

5. Click 'Save' at the end of the Add Payer form.


Generate and upload linked AWS accounts

Create new AWS member accounts

  1. Create AWS member accounts in your AWS Organization

  2. Move the member accounts into your OU (Organizational Unit)

AWS provides multiple options for automating the creation of accounts. You can use the SDK of your choice to call the AWS API, or you can write a script using AWS CLI commands. Please refer to the AWS documentation for details:

Vocareum Requirements

  • The environment executing the code must have AWS credentials for the Organization's Management account

  • The member account must be assigned a role named 'vocareum'

    • Vocareum uses the admin role 'vocareum' to access and manage resources in linked accounts.

  • The member's account ID must be a unique identifier

  • [Recommended] The member account's email should follow the format: awslabs<insert account ID>@vocareum.com

    • The email domain @vocareum.com allows Vocareum to access linked accounts using root emails if necessary for troubleshooting.

  • The member accounts must be moved into the OU that you created for Vocareum.

Example API Call

The following code creates an account using the AWS SDK for PHP:

$result = $orgclient->createAccount(
['AccountName' => $my_id,
'Email' => $my_email,
'IamUserAccessToBilling' => 'ALLOW',
'RoleName' => 'vocareum']);

Within the provided code:

  • $my_id should be a unique identifier for the account.

  • $my_email should be "awslabs{$my_id}" . '@vocareum.com'.

For example, if the value of $my_id was 12345, then the value of $my_email would be awslabs12345@vocareum.com.

Following this account creation step, you would move the new account into your OU.


Upload your AWS member account list to Vocareum

1. Prepare an account list CSV file.

The format of the CSV file should align with the following example:

account_id1,my_id1,my_email1
account_id2,my_id2,my_email2

2. Navigate to the Vocareum Control Center and select AWS from the sidebar.

3. Open the AWS Payers page.

4. Select your Payer, then click "Upload accounts"

5. In the Upload Accounts form, choose the CSV file to be uploaded.

6. Click Upload


Once you have completed all the steps in this guide, please email support@vocareum.com with your Vocareum Organization name and AWS Payer account number so we can validate the integration.

Did this answer your question?