Skip to content

Commit 828aed4

Browse files
authored
Introduce Elastio Asset Account CloudFormation StackSet (#89)
This PR adds a public terraform modules wrapper for the StackSet to deploy the Elastio Asset Account stack. Also provided two examples `self-managed` and `service-managed`.
1 parent d8c4ee1 commit 828aed4

File tree

18 files changed

+649
-0
lines changed

18 files changed

+649
-0
lines changed

.github/workflows/ci.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: ci
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
8+
jobs:
9+
typos:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: crate-ci/typos@v1.30.2
14+
15+
terraform-fmt:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- uses: hashicorp/setup-terraform@v1
21+
with:
22+
terraform_version: ^1
23+
terraform_wrapper: false
24+
25+
- run: terraform fmt -check
26+
27+
terraform-validate:
28+
runs-on: ubuntu-latest
29+
30+
strategy:
31+
matrix:
32+
project:
33+
- asset-account/terraform/stack-set/examples/self-managed
34+
- asset-account/terraform/stack-set/examples/service-managed
35+
36+
steps:
37+
- uses: actions/checkout@v4
38+
39+
- uses: hashicorp/setup-terraform@v1
40+
with:
41+
terraform_version: ^1
42+
terraform_wrapper: false
43+
44+
- run: terraform init -input=false
45+
working-directory: ${{ matrix.project }}
46+
47+
- run: terraform validate
48+
working-directory: ${{ matrix.project }}

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.terraform
2+
.terraform.tfstate.lock.info
3+
terraform.tfstate
4+
terraform.tfstate.backup
5+
terraform.tfvars

asset-account/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Elastio Asset Account Stack
2+
3+
Elastio Asset Account stack creates IAM roles to link the AWS account with the Elastio Connector. This allows the Elastio Connector to scan the assets available in the account where the Elastio Asset Account stack is deployed.
4+
5+
There are several ways to deploy the Elastio Asset Account stack, that we'll review below.
6+
7+
## AWS CloudFormation StackSet
8+
9+
You can generate the CloudFormation template link for your Elastio Asset Account using the Elastio Portal UI and then deploy it via a CloudFormation StackSet either manually, or using the Elastio official Terraform wrapper module for this.
10+
11+
See the [`terraform/stack-set`](./terraform/stack-set) to get started.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Elastio Asset Account CloudFormation StackSet
2+
3+
See [this README](../..) for more details on what this stack does.
4+
5+
This is a Terraform module, that is a thin wrapper on top of an [`aws_cloudformation_stack_set`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_set) and [`aws_cloudformation_stack_instances`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack_instances) resources used to deploy the Elastio Asset Account stack.
6+
7+
See the `examples` directory for some examples of how this module can be used:
8+
- `self-managed` - deploy the stack set using the [self-managed permission model](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-getting-started-create-self-managed.html)
9+
- `service-managed` - deploy the stack set using the [service-managed permission model](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-associate-stackset-with-org.html)

asset-account/terraform/stack-set/examples/self-managed/.terraform.lock.hcl

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Self-Managed StackSet Example
2+
3+
This is a basic example of using the `elastio-asset-account-stack-set` terraform module with the self-managed AWS Cloudformation StackSet.
4+
5+
You can deploy it even within a single account. Just specify the `template_url` input variable at minimum.
6+
7+
You can specify the `admin_account_aws_profile` and `asset_account_aws_profile` to use separate Admin and Asset accounts. If you don't specify them, then the default AWS account configured in your environment will be used as both the Admin and the Asset account.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
module "elastio_asset_accounts" {
2+
# Use the link from the real terraform registry here. Relative path is used for testing purposes.
3+
source = "../../"
4+
providers = {
5+
aws = aws.admin
6+
}
7+
8+
depends_on = [
9+
# Needs to wait for the execution role in the asset account to be fully created
10+
aws_iam_role_policy.execution_deployment,
11+
12+
# Needs to wait for the admin role in the admin account to be fully created
13+
aws_iam_role_policy.admin_execution,
14+
]
15+
16+
template_url = var.template_url
17+
18+
# We are deploying just into a single asset account in this example
19+
accounts = [local.asset_account_id]
20+
21+
administration_role_arn = aws_iam_role.admin.arn
22+
}
23+
24+
# Admin role, that StackSets will use to access the asset accounts to deploy the stacks
25+
resource "aws_iam_role" "admin" {
26+
provider = aws.admin
27+
28+
assume_role_policy = data.aws_iam_policy_document.admin_trust.json
29+
name = "AWSCloudFormationStackSetAdministrationRole"
30+
}
31+
32+
data "aws_iam_policy_document" "admin_trust" {
33+
statement {
34+
actions = ["sts:AssumeRole"]
35+
effect = "Allow"
36+
37+
principals {
38+
identifiers = ["cloudformation.amazonaws.com"]
39+
type = "Service"
40+
}
41+
42+
# Conditions to prevent the confused deputy attack
43+
condition {
44+
test = "StringEquals"
45+
variable = "aws:SourceAccount"
46+
values = [local.admin_account_id]
47+
}
48+
49+
condition {
50+
test = "StringLike"
51+
variable = "aws:SourceArn"
52+
values = ["arn:aws:cloudformation:*:${local.admin_account_id}:stackset/*"]
53+
}
54+
}
55+
}
56+
57+
data "aws_iam_policy_document" "admin_execution" {
58+
statement {
59+
actions = ["sts:AssumeRole"]
60+
effect = "Allow"
61+
resources = ["arn:aws:iam::*:role/AWSCloudFormationStackSetExecutionRole"]
62+
}
63+
}
64+
65+
resource "aws_iam_role_policy" "admin_execution" {
66+
provider = aws.admin
67+
68+
name = "AssumeExecutionRole"
69+
policy = data.aws_iam_policy_document.admin_execution.json
70+
role = aws_iam_role.admin.name
71+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
resource "aws_iam_role" "execution" {
2+
provider = aws.asset
3+
4+
name = "AWSCloudFormationStackSetExecutionRole"
5+
assume_role_policy = data.aws_iam_policy_document.execution_trust.json
6+
}
7+
8+
data "aws_iam_policy_document" "execution_trust" {
9+
statement {
10+
actions = ["sts:AssumeRole"]
11+
effect = "Allow"
12+
13+
principals {
14+
identifiers = [aws_iam_role.admin.arn]
15+
type = "AWS"
16+
}
17+
}
18+
}
19+
20+
# Specifies the set of permissions required for the deployment of the Cloudfomation stack
21+
data "aws_iam_policy_document" "execution_deployment" {
22+
statement {
23+
actions = ["*"]
24+
effect = "Allow"
25+
resources = ["*"]
26+
}
27+
}
28+
29+
resource "aws_iam_role_policy" "execution_deployment" {
30+
provider = aws.asset
31+
32+
name = "Deployment"
33+
policy = data.aws_iam_policy_document.execution_deployment.json
34+
role = aws_iam_role.execution.name
35+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
provider "aws" {
2+
alias = "admin"
3+
profile = var.admin_account_aws_profile
4+
}
5+
6+
provider "aws" {
7+
alias = "asset"
8+
profile = var.asset_account_aws_profile
9+
}
10+
11+
data "aws_caller_identity" "admin" {
12+
provider = aws.admin
13+
}
14+
15+
data "aws_caller_identity" "asset" {
16+
provider = aws.asset
17+
}
18+
19+
locals {
20+
admin_account_id = data.aws_caller_identity.admin.account_id
21+
asset_account_id = data.aws_caller_identity.asset.account_id
22+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
variable "template_url" {
2+
description = <<-DESCR
3+
The URL of the Elastio Asset Account CloudFormation template obtained from
4+
the Elastio Portal.
5+
6+
This parameter is sensitive, because anyone who knows this URL can deploy
7+
Elastio Account stack and linking it to your Elastio tenant.
8+
DESCR
9+
10+
sensitive = true
11+
type = string
12+
nullable = false
13+
}
14+
15+
variable "admin_account_aws_profile" {
16+
type = string
17+
default = null
18+
}
19+
20+
variable "asset_account_aws_profile" {
21+
type = string
22+
default = null
23+
}

0 commit comments

Comments
 (0)