Nathan Griffiths
Nathan Griffiths

Reputation: 12756

How to create a Snowflake Storage Integration with AWS S3 with Terraform?

I am trying to use Terraform to set up a Snowflake "Storage Integration" object that links to an AWS S3 bucket. I'm using the "chanzuckerberg" Snowflake provider from the Terraform registry in addition to the standard AWS provider.

The issue I have is that part of the process to create the integration requires the following sequence of actions:

  1. Create an IAM Role with S3 access policy
  2. Create a Snowflake Storage Integration object, specifying the IAM Role created in step 1
  3. Modify the IAM Role access policy using values from the Storage Integration object

(complete list of steps here)

Hence there is a circular dependency between the IAM Role and Storage Integration. Steps 1 and 2 are straightforward but I'm not sure how to implement step 3 with Terraform as in involves modifying an object's state after it has been created.

Unfortunately it looks like the IAM Role access policy cannot be modified separate from the role itself.

Is such a thing possible or does the circular relationship between the resources mean this can't be handled by Terraform?

Upvotes: 5

Views: 3288

Answers (2)

Prasanth K
Prasanth K

Reputation: 81

This module already helps make it a turn-key deployment.

https://github.com/Snowflake-Labs/terraform-snowflake-storage-integration

Let me know if that helps.

Upvotes: 2

Jarl
Jarl

Reputation: 3150

Terraform dependency cycles with IAM roles have a straightforward workaround. The role ARN can be precalculated, and the integration resource then has no dependency on the role. The role can then use the integration outputs freely.

Sample code:

locals {
  role_name = "my_role"
  role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${local.role_name}"
}

resource "snowflake_storage_integration" "int" {
  storage_aws_role_arn = local.role_arn
  ...
}

resource "aws_iam_role" "role" {
  name = local.role_name
  assume_role_policy = jsonencode({
    "Version" : "2012-10-17"
    "Statement" : [
      {
        "Action" : "sts:AssumeRole"
        "Effect" : "Allow"
        "Principal" : {
          "AWS" : snowflake_storage_integration.int.storage_aws_iam_user_arn
        }
        "Condition" : {
          "StringEquals" : {
            "sts:ExternalId" : snowflake_storage_integration.int.storage_aws_external_id
          }
        }
      }
    ]
  })
}

Upvotes: 8

Related Questions