For Admins
For certain applications, Vocareum will launch resources in your own AWS account. This depends upon the business agreement between you and Vocareum and the type of labs used. You must be an Organization Admin for your organization to perform the following steps to register the AWS account that you want Vocareum to use to launch your AWS resources.
The three use cases for this type of integration are:
Databricks – providing the backing compute resources for students using Vocareum Databricks labs.
Virtual Machine Labs – creating Amazon Machine Images (AMI) provisioning Elastic Cloud Compute (EC2) instances for students using Vocareum VM Labs.
Custom Clusters – Running Vocareum container-based labs such as Vocareum Notebook on managed EC2 server clusters within your own AWS account.
In each case, you will need to provide Identity and Access Management (IAM) permissions so that Vocareum can manage the appropriate resources on your behalf.
If you are planning to use your own AWS payer to provision individual accounts to students via Vocareum's AWS Cloud Labs, please instead refer to Cloud Labs: Bring Your Own AWS Account for integration instructions.
Go to "Edit Org" page.
Enter the AWS account number which you want Vocareum to use under "Customer Account #"
Vocareum does not ask for the credential for your account but instead you must establish a trust relationship between your account and the account specified in the " "Account #" such that this account can assume the role vocareumvm in your account.
The Trust policy should look like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<Vocareum AWS account>:role/vocareum
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Please attach the appropriate policy to vocareumvm role.
[Note: the platform will not manage the budget in this case so please ignore the Budget field above].
Databricks:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VocDbEc2Access",
"Effect": "Allow",
"Action": [
"ec2:AllocateAddress",
"ec2:AssociateRouteTable",
"ec2:AttachInternetGateway",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CreateInternetGateway",
"ec2:CreateNatGateway",
"ec2:CreateRoute",
"ec2:CreateRouteTable",
"ec2:CreateSecurityGroup",
"ec2:CreateSubnet",
"ec2:CreateTags",
"ec2:CreateVpc",
"ec2:CreateVpcEndpoint",
"ec2:DeleteInternetGateway",
"ec2:DeleteNatGateway",
"ec2:DeleteRoute",
"ec2:DeleteRouteTable",
"ec2:DeleteSecurityGroup",
"ec2:DeleteSubnet",
"ec2:DeleteVpc",
"ec2:DescribeAccountAttributes",
"ec2:DescribeAddresses",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeCustomerGateways",
"ec2:DescribeDhcpOptions",
"ec2:DescribeEgressOnlyInternetGateways",
"ec2:DescribeInstances",
"ec2:DescribeInternetGateways",
"ec2:DescribeNatGateways",
"ec2:DescribeNetworkAcls",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeRegions",
"ec2:DescribeRouteTables",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeTags",
"ec2:DescribeVpcAttribute",
"ec2:DescribeVpcEndpoints",
"ec2:DescribeVpcEndpointServiceConfigurations",
"ec2:DescribeVpcPeeringConnections",
"ec2:DescribeVpcs",
"ec2:DescribeVpnConnections",
"ec2:DescribeVpnGateways",
"ec2:DetachInternetGateway",
"ec2:DisassociateRouteTable",
"ec2:ModifySubnetAttribute",
"ec2:ModifyVpcAttribute",
"ec2:ReleaseAddress",
"ec2:RevokeSecurityGroupEgress",
"ec2:RevokeSecurityGroupIngress"
],
"Resource": "*"
},
{
"Sid": "VocDbCfnAccess",
"Effect": "Allow",
"Action": [
"cloudformation:CreateStack",
"cloudformation:DeleteStack",
"cloudformation:DescribeStackEvents",
"cloudformation:DescribeStacks",
"cloudformation:GetStackPolicy",
"cloudformation:ListStacks",
"cloudformation:UpdateTerminationProtection"
],
"Resource": "*"
}
]
} VM Labs:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudformation:*",
"elasticloadbalancing:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"iam:GetRole",
"iam:GetPolicy",
"iam:GetInstanceProfile",
"iam:CreateInstanceProfile",
"iam:AddRoleToInstanceProfile",
"iam:RemoveRoleFromInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:PassRole"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2:*"
],
"Resource": "*",
"Condition": {
"StringEqualsIfExists": {
"ec2:InstanceType": [
"t2.micro",
"t2.small",
"t2.medium",
"t2.large",
"t2.xlarge",
"t2.2xlarge",
"t3.medium",
"t3.large",
"r4.large",
"r4.xlarge",
"r4.2xlarge",
"r5.xlarge",
"r5.2xlarge",
"r5.4xlarge",
"m5.2xlarge",
"p2.xlarge",
"p3.2xlarge",
"g2.2xlarge",
"g3s.xlarge",
"c5a.2xlarge",
"c5a.4xlarge",
"g4dn.xlarge",
"g4dn.2xlarge"
]
}
}
},
{
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": [
"elasticloadbalancing.amazonaws.com",
"spot.amazonaws.com",
"spotfleet.amazonaws.com"
]
}
}
},
{
"Effect": "Allow",
"Action": "logs:PutLogEvents",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ssm:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2messages:AcknowledgeMessage",
"ec2messages:DeleteMessage",
"ec2messages:FailMessage",
"ec2messages:GetEndpoint",
"ec2messages:GetMessages",
"ec2messages:SendReply"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"cloudwatch:PutMetricData"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ds:CreateComputer",
"ds:DescribeDirectories"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::dcv-license.us-west-2/*"
}
]
}Compute:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudformation:*",
"elasticloadbalancing:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"iam:GetRole",
"iam:GetPolicy",
"iam:GetInstanceProfile",
"iam:CreateInstanceProfile",
"iam:AddRoleToInstanceProfile",
"iam:RemoveRoleFromInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:PassRole"
],
"Resource": "*"
},
{
"Sid": "LaunchRunServers",
"Effect": "Allow",
"Action": "ec2:RunInstances",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": [
"elasticloadbalancing.amazonaws.com",
"spot.amazonaws.com",
"spotfleet.amazonaws.com"
]
}
}
},
{
"Effect": "Allow",
"Action": "logs:PutLogEvents",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ssm:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2messages:AcknowledgeMessage",
"ec2messages:DeleteMessage",
"ec2messages:FailMessage",
"ec2messages:GetEndpoint",
"ec2messages:GetMessages",
"ec2messages:SendReply"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"cloudwatch:PutMetricData"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ds:CreateComputer",
"ds:DescribeDirectories"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::dcv-license.us-west-2/*"
},
{
"Effect": "Allow",
"Action": [
"route53:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"acm:ImportCertificate",
"acm:ListCertificates"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"elasticfilesystem:*",
"iam:CreateServiceLinkedRole"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"kms:ListAliases"
],
"Resource": "*"
},
{
"Sid": "CreateTagsForServers",
"Effect": "Allow",
"Action": "ec2:CreateTags",
"Resource": "*"
},
{
"Sid": "SetInstanceTagsFromScript",
"Effect": "Allow",
"Action": "ec2:CreateTags",
"Resource": "arn:aws:ec2:*:*:instance/*"
},
{
"Sid": "SendDataToCloudWatch",
"Effect": "Allow",
"Action": [
"ec2:DescribeTags",
"ec2:DescribeVolumes",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:CreateLogGroup",
"logs:PutLogEvents",
"cloudwatch:PutMetricData",
"cloudwatch:PutMetricAlarm",
"cloudwatch:PutDashboard",
"cloudwatch:GetDashboard"
],
"Resource": "*"
},
{
"Sid": "KMSDecryptionForParameterStore",
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": [
"arn:aws:kms:<region>:<customer-aws-account>:key/*"
],
"Condition": {
"StringLike": {
"kms:ViaService": "ssm.*.amazonaws.com"
}
}
},
{
"Sid": "GetParameters",
"Effect": "Allow",
"Action": "ssm:GetParameter",
"Resource": "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-*"
},
{
"Sid": "MountFilesystems",
"Effect": "Allow",
"Action": [
"elasticfilesystem:ClientMount",
"elasticfilesystem:ClientWrite"
],
"Resource": "*"
},
{
"Sid": "AssumeS3Role",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<customer-aws-account>:role/voc-s3-readwrite-role"
},
{
"Sid": "ECRAccess",
"Effect": "Allow",
"Action": "ecr:GetAuthorizationToken",
"Resource": "*"
},
{
"Sid": "EC2Permissions",
"Effect": "Allow",
"Action": [
"ec2:TerminateInstances",
"ec2:ModifyInstanceAttribute",
"ec2:DescribeInstanceStatus",
"ec2:StopInstances",
"ec2:DescribeInstances",
"ec2:CreateLaunchTemplate",
"ec2:DescribeLaunchTemplateVersions",
"ec2:CreateLaunchTemplateVersion",
"ec2:ModifyLaunchTemplate",
"ec2:CancelSpotInstanceRequests",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteNetworkInterface",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeImages",
"ec2:DescribeKeyPairs",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeImageAttribute",
"ec2:ModifyImageAttribute"
],
"Resource": "*"
},
{
"Sid": "AllowGetRole",
"Effect": "Allow",
"Action": "iam:GetRole",
"Resource": "*"
},
{
"Sid": "AllowPassRunServerRole",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::<customer-aws-account>:role/runserver"
},
{
"Sid": "ALBPermissions",
"Effect": "Allow",
"Action": [
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
],
"Resource": "*"
},
{
"Sid": "launching",
"Effect": "Allow",
"Action": [
"ec2:DescribeVpcs",
"ec2:CreateSecurityGroup",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:CreateKeyPair"
],
"Resource": "*"
}
]
}
Databricks
To create workspaces and clusters in Databricks, an additional IAM role, IAM policy, and S3 bucket need to be created.
Create a policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1403287045000",
"Effect": "Allow",
"Action": [
"ec2:AssociateIamInstanceProfile",
"ec2:AttachVolume",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CancelSpotInstanceRequests",
"ec2:CreateTags",
"ec2:CreateVolume",
"ec2:DeleteTags",
"ec2:DeleteVolume",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeIamInstanceProfileAssociations",
"ec2:DescribeInstanceStatus",
"ec2:DescribeInstances",
"ec2:DescribeInternetGateways",
"ec2:DescribeNatGateways",
"ec2:DescribeNetworkAcls",
"ec2:DescribePrefixLists",
"ec2:DescribeReservedInstancesOfferings",
"ec2:DescribeRouteTables",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSpotInstanceRequests",
"ec2:DescribeSpotPriceHistory",
"ec2:DescribeSubnets",
"ec2:DescribeVolumes",
"ec2:DescribeVpcAttribute",
"ec2:DescribeVpcs",
"ec2:DetachVolume",
"ec2:DisassociateIamInstanceProfile",
"ec2:ReplaceIamInstanceProfileAssociation",
"ec2:RequestSpotInstances",
"ec2:RevokeSecurityGroupEgress",
"ec2:RevokeSecurityGroupIngress",
"ec2:RunInstances",
"ec2:TerminateInstances",
"ec2:DescribeFleetHistory",
"ec2:ModifyFleet",
"ec2:DeleteFleets",
"ec2:DescribeFleetInstances",
"ec2:DescribeFleets",
"ec2:CreateFleet",
"ec2:DeleteLaunchTemplate",
"ec2:GetLaunchTemplateData",
"ec2:CreateLaunchTemplate",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeLaunchTemplateVersions",
"ec2:ModifyLaunchTemplate",
"ec2:DeleteLaunchTemplateVersions",
"ec2:CreateLaunchTemplateVersion",
"ec2:AssignPrivateIpAddresses",
"ec2:GetSpotPlacementScores"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"iam:CreateServiceLinkedRole",
"iam:PutRolePolicy"
],
"Resource": "arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot",
"Condition": {
"StringLike": {
"iam:AWSServiceName": "spot.amazonaws.com"
}
}
}
]
}Create a role using this custom trust policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::414351767826:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "42b65603-f19a-4c55-9b5b-034cc37f6652"
}
}
}
]
}
and attach the policy from Step 1 to the role.
Create an S3 bucket
make sure the region of the bucket matches the region in the Edit Org page under Custom Infra. -> VM Settings
After creating the bucket, modify the bucket permissions. Edit the bucket policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Grant Databricks Access",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::414351767826:root"
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::<BUCKET_NAME>/*",
"arn:aws:s3:::<BUCKET_NAME>"
],
"Condition": {
"StringEquals": {
"aws:PrincipalTag/DatabricksAccountId": "42b65603-f19a-4c55-9b5b-034cc37f6652"
}
}
}
]
}
Replace <BUCKET_NAME> with the name of the bucket from Step 3.
Provide Vocareum with:
the ARN of the role from Step 2
the name of the bucket from Step 3
Compute
To run backend interactive and grading clusters an additional IAM role and corresponding IAM policy need to be created.
Create a policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SSM",
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParametersByPath"
],
"Resource": "*"
},
{
"Sid": "KMSDecryptionForParameterStore",
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": [
"arn:aws:kms:<region>:<customer-aws-account>:key/*"
],
"Condition": {
"StringLike": {
"kms:ViaService": "ssm.*.amazonaws.com"
}
}
},
{
"Sid": "CW",
"Effect": "Allow",
"Action": [
"cloudwatch:GetMetricData",
"cloudwatch:ListMetrics"
],
"Resource": "*"
},
{
"Sid": "CwAgentServer",
"Effect": "Allow",
"Action": [
"cloudwatch:PutMetricData",
"ec2:DescribeVolumes",
"ec2:DescribeTags",
"logs:PutLogEvents",
"logs:DescribeLogStreams",
"logs:DescribeLogGroups",
"logs:CreateLogStream",
"logs:CreateLogGroup"
],
"Resource": "*"
},
{
"Sid": "ECRPermissions",
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": "*"
},
{
"Sid": "DynamoDBAccess",
"Effect": "Allow",
"Action": [
"dynamodb:UpdateItem"
],
"Resource": [
"arn:aws:dynamodb:<region>:<customer-aws-account>:table/ExecutionProcesses"
]
}
]
}Create the "runserver" role using this custom trust policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<Vocareum AWS account>:role/vocareum
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Attach this policy as well as the aws managed policy "AmazonSSMManagedInstanceCore" to this role.
Note
It might be a good practice to create your account as a member account in a separate AWS Organization to keep the Vocareum related resources and billings isolated from other activity. In addition you can apply organization level scp (service control policy) to further reduce your risk. Please refer to relevant AWS documentation for details on this topic


