diff --git a/src/multiplayer-servers/getting-started/cloud-provider-setup.md b/src/multiplayer-servers/getting-started/cloud-provider-setup.md index b477a61..47071f4 100644 --- a/src/multiplayer-servers/getting-started/cloud-provider-setup.md +++ b/src/multiplayer-servers/getting-started/cloud-provider-setup.md @@ -8,7 +8,7 @@ contact your Nitrado Account Manager. ## Google Cloud -#### Prerequisites +### Prerequisites * You **must** already have an existing Google Cloud organization * You **must** possess the necessary permissions to manage principals and billing accounts in your organization @@ -53,3 +53,294 @@ In order to link your billing account to the projects managed by Nitrado, and to #### Confirming the setup After you have completed the steps above, please contact Nitrado to confirm that the setup is complete. + +## Amazon Web Services + +### Prerequisites + +* You **must** already have an existing AWS account +* You **must** possess the necessary permissions to create IAM resources in your account + +### Background + +For AWS, to access another organization, you have to setup a chain of _roles_. Roles are AWS objects that allow scoping permissions. Roles are assumable by _principals_. Principals are arbitrary entities operating AWS, and specifically, users or groups of users. This setup allows you to delegate game server cluster management to Gamefabric operators by creating a role that is fine-grained to provision resources _without having to grant broad access to their organization_. + +By chaining those roles together (i.e., allowing a role to assume another role), Gamefabric operators can access your organization/account, +as long as the chain of _Trust Relationship_ is not broken. + + + +For setting this up, we recommend using a tool like Terraform, as it allows you to simply declare the desired resources. Particularly for configuring various policy documents, this will be helpful. We'll use Terraform in the following. You can adapt this guide and do the following steps manually. + +### Creating the Role and Assumption Policy + +Create an IAM Role and the appropriate role assumption policy using Terraform: + +```terraform +variable "source_saml_principal_arn" { + type = string + description = "ARN of the principal backing the SAML authentication for SSO users from the source account" + default = "arn:aws:iam::339712714940:saml-provider/AWSSSO_5495e4acbcad9a8a_DO_NOT_DELETE" +} + +variable "source_role_arn" { + type = string + description = "ARN of the role in the source account to trust" + default = "arn:aws:iam::339712714940:role/gamefabric-operators" +} + +resource "aws_iam_role" "gamefabric_operators" { + name = "gamefabric-operators" + assume_role_policy = data.aws_iam_role_policy.assume_role_policy.json + + tags = { + role = "gamefabric-operators" + provider = "gamefabric" + } +} + +# This document is what is required to grant Nitrado access to your org +data "aws_iam_policy_document" "assume_role_policy" { + statement { + effect = "Allow" + actions = [ + "sts:AssumeRoleWithSAML", + "sts:TagSession", + "sts:AssumeRole" + ] + principals { + type = "Federated" + identifiers = [var.source_saml_principal_arn] + } + condition { + test = "StringEquals" + variable = "SAML:aud" + values = ["https://signin.aws.amazon.com/saml"] + } + } + statement { + effect = "Allow" + actions = [ + "sts:TagSession", + "sts:AssumeRole" + ] + principals { + type = "AWS" + identifiers = [ var.source_role_arn ] + } + } +} + +output "role_arn" { + value = aws_iam_role.gamefabric_operators.arn +} +``` + +The defaults for the variables are linking to the Gamefabric AWS account, specifically, the account ID `339712714940` belongs to the Gamefabric organization. +The two ARNs link to the role and the respective SAML provider on _our end_ (see the graphic above). + +### Creating Policies for Resource Management + +Create several IAM policy documents that grant access + +```terraform +data "aws_iam_policy_document" "deployer_eks" { + statement { + effect = "Allow" + actions = [ + "eks:AssociateAccessPolicy", + "eks:CreateAccessEntry", + "eks:CreateAddon", + "eks:CreateCluster", + "eks:CreateNodegroup", + "eks:DeleteAccessEntry", + "eks:DeleteAddon", + "eks:DeleteCluster", + "eks:DeleteNodegroup", + "eks:DescribeAccessEntry", + "eks:DescribeAddon", + "eks:DescribeAddonConfiguration", + "eks:DescribeAddonVersions", + "eks:DescribeCluster", + "eks:DescribeNodegroup", + "eks:DescribeUpdate", + "eks:DisassociateAccessPolicy", + "eks:ListAddons", + "eks:ListAssociatedAccessPolicies", + "eks:ListClusters", + "eks:ListNodegroups", + "eks:ListUpdates", + "eks:UpdateNodegroupConfig", + "eks:UpdateNodegroupVersion", + "eks:TagResource", + ] + resources = ["*"] + } +} + +data "aws_iam_policy_document" "deployer_ec2" { + statement { + effect = "Allow" + actions = [ + "ec2:AllocateAddress", + "ec2:AssociateRouteTable", + "ec2:AttachInternetGateway", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateInternetGateway", + "ec2:CreateNatGateway", + "ec2:CreateNetworkAclEntry", + "ec2:CreateRoute", + "ec2:CreateRouteTable", + "ec2:CreateSecurityGroup", + "ec2:CreateSubnet", + "ec2:CreateVpc", + "ec2:DeleteInternetGateway", + "ec2:DeleteNatGateway", + "ec2:DeleteNetworkAclEntry", + "ec2:DeleteRoute", + "ec2:DeleteRouteTable", + "ec2:DeleteSecurityGroup", + "ec2:DeleteSubnet", + "ec2:DeleteVpc", + "ec2:DescribeAddresses", + "ec2:DescribeAddressesAttribute", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInternetGateways", + "ec2:DescribeNatGateways", + "ec2:DescribeNetworkAcls", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribePlacementGroups", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroupRules", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs", + "ec2:DetachInternetGateway", + "ec2:DisassociateAddress", + "ec2:DisassociateRouteTable", + "ec2:GetEbsDefaultKmsKeyId", + "ec2:GetEbsEncryptionByDefault", + "ec2:GetInstanceMetadataDefaults", + "ec2:GetInstanceTypesFromInstanceRequirements", + "ec2:GetSecurityGroupsForVpc", + "ec2:ModifySubnetAttribute", + "ec2:ModifyVpcAttribute", + "ec2:ReleaseAddress", + "ec2:RevokeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress", + "ec2:CreateTags", + "ec2:DeleteTags", + "ec2:DescribeTags", + ] + resources = ["*"] + } +} + +data "aws_iam_policy_document" "deployer_autoscaling" { + statement { + effect = "Allow" + actions = [ + "autoscaling:AttachRolePolicy", + "autoscaling:CreateOpenIDConnectProvider", + "autoscaling:CreatePolicy", + "autoscaling:CreateRole", + "autoscaling:DeleteOpenIDConnectProvider", + "autoscaling:DeletePolicy", + "autoscaling:DeleteRole", + "autoscaling:DeleteRolePolicy", + "autoscaling:DetachRolePolicy", + "autoscaling:GetOpenIDConnectProvider", + "autoscaling:PutRolePolicy" + ] + resources = ["*"] + } +} + +data "aws_iam_policy_document" "deployer_aux" { + statement { + effect = "Allow" + actions = [ + "kms:CreateAlias", + "kms:CreateGrant", + "kms:CreateKey", + "kms:DeleteAlias", + "kms:EnableKeyRotation", + "kms:ListAliases", + "kms:ScheduleKeyDeletion", + "kms:TagResource" + ] + resources = ["*"] + } + statement { + effect = "Allow" + actions = [ + "iam:AttachRolePolicy", + "iam:CreateOpenIDConnectProvider", + "iam:CreatePolicy", + "iam:CreateRole", + "iam:DeleteOpenIDConnectProvider", + "iam:DeletePolicy", + "iam:DeleteRole", + "iam:DeleteRolePolicy", + "iam:DetachRolePolicy", + "iam:GetOpenIDConnectProvider", + "iam:GetPolicy", + "iam:GetPolicyVersion", + "iam:GetRole", + "iam:GetRolePolicy", + "iam:ListInstanceProfiles", + "iam:ListInstanceProfilesForRole", + "iam:ListPolicyVersions", + "iam:ListRolePolicies", + "iam:PutRolePolicy", + "iam:TagRole", + "iam:TagPolicy", + "iam:ListAttachedRolePolicies", + "iam:PassRole", + "iam:TagOpenIDConnectProvider", + "iam:ListOpenIDConnectProviders", + ] + resources = ["*"] + } + statement { + effect = "Allow" + actions = [ + "logs:CreateLogGroup", + "logs:DescribeLogGroups", + "logs:ListTagsForResource", + "logs:PutRetentionPolicy", + "logs:TagResource", + "logs:DeleteLogGroup", + ] + resources = ["*"] + } +} + +# Merge all policy docs together +data "aws_iam_policy_document" "combined_policy_documents" { + source_policy_documents = [ + data.aws_iam_policy_document.deployer_eks.json, + data.aws_iam_policy_document.deployer_ec2.json, + data.aws_iam_policy_document.deployer_autoscaling.json, + data.aws_iam_policy_document.deployer_aux.json + ] +} + +resource "aws_iam_role_policy" "gamefabric_operators" { + name = "gamefabric-operators" + role = aws_iam_role.gamefabric_operators.id + policy = data.aws_iam_policy_document.combined_policy_documents.json +} +``` + +::: info Policy Document Size Restrictions +AWS encodes their policy documents in JSON, and restricts the size of these documents rather strictly to 4KB per document. +Adding all the permissions into one policy exceeds the limit for a single policy. We split them up logically such that +they are grouped broadly by the resource types they grant access to. +::: + +### Confirming the setup + +After you have completed the steps above, please contact Nitrado to confirm that the setup is complete, and provide us with the ARN of the role you created previously, as we need it on our end to access your account. diff --git a/src/multiplayer-servers/getting-started/images/cloud/aws-iam-setup.png b/src/multiplayer-servers/getting-started/images/cloud/aws-iam-setup.png new file mode 100644 index 0000000..9ed12ab Binary files /dev/null and b/src/multiplayer-servers/getting-started/images/cloud/aws-iam-setup.png differ