Skip to content

Commit

Permalink
docs: add aws account delegation instructions
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Bartolomey <[email protected]>
  • Loading branch information
zoomoid committed Oct 29, 2024
1 parent d2594db commit 40644d0
Show file tree
Hide file tree
Showing 2 changed files with 292 additions and 1 deletion.
293 changes: 292 additions & 1 deletion src/multiplayer-servers/getting-started/cloud-provider-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.

<img style="padding: 2rem; box-sizing: border-box" src="./images/cloud/aws-iam-setup.png"/>

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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 40644d0

Please sign in to comment.