Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: ci

on:
push:
branches: [master]
pull_request:

jobs:
typos:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: crate-ci/typos@v1.30.2

terraform-fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: hashicorp/setup-terraform@v1
with:
terraform_version: ^1
terraform_wrapper: false

- run: terraform fmt -check

terraform-validate:
runs-on: ubuntu-latest

strategy:
matrix:
project:
- asset-account/terraform/stack-set/examples/self-managed
- asset-account/terraform/stack-set/examples/service-managed

steps:
- uses: actions/checkout@v4

- uses: hashicorp/setup-terraform@v1
with:
terraform_version: ^1
terraform_wrapper: false

- run: terraform init -input=false
working-directory: ${{ matrix.project }}

- run: terraform validate
working-directory: ${{ matrix.project }}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.terraform
.terraform.tfstate.lock.info
terraform.tfstate
terraform.tfstate.backup
terraform.tfvars
11 changes: 11 additions & 0 deletions asset-account/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Elastio Asset Account Stack

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.

There are several ways to deploy the Elastio Asset Account stack, that we'll review below.

## AWS CloudFormation StackSet

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.

See the [`terraform/stack-set`](./terraform/stack-set) to get started.
9 changes: 9 additions & 0 deletions asset-account/terraform/stack-set/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Elastio Asset Account CloudFormation StackSet

See [this README](../..) for more details on what this stack does.

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.

See the `examples` directory for some examples of how this module can be used:
- `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)
- `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)

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Self-Managed StackSet Example

This is a basic example of using the `elastio-asset-account-stack-set` terraform module with the self-managed AWS Cloudformation StackSet.

You can deploy it even within a single account. Just specify the `template_url` input variable at minimum.

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.
71 changes: 71 additions & 0 deletions asset-account/terraform/stack-set/examples/self-managed/admin.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
module "elastio_asset_accounts" {
# Use the link from the real terraform registry here. Relative path is used for testing purposes.
source = "../../"
providers = {
aws = aws.admin
}

depends_on = [
# Needs to wait for the execution role in the asset account to be fully created
aws_iam_role_policy.execution_deployment,

# Needs to wait for the admin role in the admin account to be fully created
aws_iam_role_policy.admin_execution,
]

template_url = var.template_url

# We are deploying just into a single asset account in this example
accounts = [local.asset_account_id]

administration_role_arn = aws_iam_role.admin.arn
}

# Admin role, that StackSets will use to access the asset accounts to deploy the stacks
resource "aws_iam_role" "admin" {
provider = aws.admin

assume_role_policy = data.aws_iam_policy_document.admin_trust.json
name = "AWSCloudFormationStackSetAdministrationRole"
}

data "aws_iam_policy_document" "admin_trust" {
statement {
actions = ["sts:AssumeRole"]
effect = "Allow"

principals {
identifiers = ["cloudformation.amazonaws.com"]
type = "Service"
}

# Conditions to prevent the confused deputy attack
condition {
test = "StringEquals"
variable = "aws:SourceAccount"
values = [local.admin_account_id]
}

condition {
test = "StringLike"
variable = "aws:SourceArn"
values = ["arn:aws:cloudformation:*:${local.admin_account_id}:stackset/*"]
}
}
}

data "aws_iam_policy_document" "admin_execution" {
statement {
actions = ["sts:AssumeRole"]
effect = "Allow"
resources = ["arn:aws:iam::*:role/AWSCloudFormationStackSetExecutionRole"]
}
}

resource "aws_iam_role_policy" "admin_execution" {
provider = aws.admin

name = "AssumeExecutionRole"
policy = data.aws_iam_policy_document.admin_execution.json
role = aws_iam_role.admin.name
}
35 changes: 35 additions & 0 deletions asset-account/terraform/stack-set/examples/self-managed/asset.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
resource "aws_iam_role" "execution" {
provider = aws.asset

name = "AWSCloudFormationStackSetExecutionRole"
assume_role_policy = data.aws_iam_policy_document.execution_trust.json
}

data "aws_iam_policy_document" "execution_trust" {
statement {
actions = ["sts:AssumeRole"]
effect = "Allow"

principals {
identifiers = [aws_iam_role.admin.arn]
type = "AWS"
}
}
}

# Specifies the set of permissions required for the deployment of the Cloudfomation stack
data "aws_iam_policy_document" "execution_deployment" {
statement {
actions = ["*"]
effect = "Allow"
resources = ["*"]
}
}

resource "aws_iam_role_policy" "execution_deployment" {
provider = aws.asset

name = "Deployment"
policy = data.aws_iam_policy_document.execution_deployment.json
role = aws_iam_role.execution.name
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
provider "aws" {
alias = "admin"
profile = var.admin_account_aws_profile
}

provider "aws" {
alias = "asset"
profile = var.asset_account_aws_profile
}

data "aws_caller_identity" "admin" {
provider = aws.admin
}

data "aws_caller_identity" "asset" {
provider = aws.asset
}

locals {
admin_account_id = data.aws_caller_identity.admin.account_id
asset_account_id = data.aws_caller_identity.asset.account_id
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
variable "template_url" {
description = <<-DESCR
The URL of the Elastio Asset Account CloudFormation template obtained from
the Elastio Portal.

This parameter is sensitive, because anyone who knows this URL can deploy
Elastio Account stack and linking it to your Elastio tenant.
DESCR

sensitive = true
type = string
nullable = false
}

variable "admin_account_aws_profile" {
type = string
default = null
}

variable "asset_account_aws_profile" {
type = string
default = null
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Service-Managed StackSet Example

This is a basic example of using the `elastio-asset-account-stack-set` terraform module with the service-managed AWS Cloudformation StackSet.

You'll need to deploy it from the AWS Management account. You'll also need to specify both the input variables: `accounts` and `organizational_unit_ids`.

AWS API requires at least one org unit ID that contains the provided accounts. It doesn't mean you'll deploy the StackSet into the entire org unit, it's just a quirk of the AWS API. The Stack set instances will still be deployed into the accounts specified in `accounts`.

If you want to deploy into the entire org unit, then modify the `deployment_targets` as needed for your use case.
16 changes: 16 additions & 0 deletions asset-account/terraform/stack-set/examples/service-managed/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module "elastio_asset_accounts" {
# Use the link from the real terraform registry here. Relative path is used for testing purposes.
source = "../../"

template_url = var.template_url

permission_model = "SERVICE_MANAGED"
deployment_targets = {
account_filter_type = "INTERSECTION"
accounts = var.accounts
organizational_unit_ids = var.organizational_unit_ids
}
auto_deployment = {
enabled = false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
variable "template_url" {
description = <<-DESCR
The URL of the Elastio Asset Account CloudFormation template obtained from
the Elastio Portal.

This parameter is sensitive, because anyone who knows this URL can deploy
Elastio Account stack and linking it to your Elastio tenant.
DESCR

sensitive = true
type = string
nullable = false
}

variable "accounts" {
type = list(string)

description = <<-DESCR
List of AWS account IDs where the Elastio Asset Account stack instances will
be deployed.
DESCR
}

variable "organizational_unit_ids" {
type = list(string)

description = <<-DESCR
Organization root ID or organizational unit (OU) IDs to which stack sets deploy.
DESCR
}
Loading