DEV Community

Discussion on: How to setup a Serverless application with AWS SAM and Terraform

Collapse
 
rolfstreefkerk profile image
Rolf Streefkerk • Edited

Ive actually added the SSM Parameter Store to this solution using this module:

GitHub logo rpstreef / terraform-aws-ssm-parameter-store

Terraform module for AWS Systems Manager Parameter Store

Now we can sync our Terraform created parameters to AWS SAM like this:

module "ssm_parameters" {
  source = "github.com/rpstreef/terraform-aws-ssm-parameter-store?ref=master"

  application_name = var.resource_tag_name
  environment      = var.namespace

  parameters = {
    "cognito_user_pool_arn" = {
      "type"  = "String"
      "value" = module.cognito.cognito_user_pool_arn
    },
    "cognito_user_pool_client_id" = {
      "type"  = "String"
      "value" = module.cognito.cognito_user_pool_client_id
    },
    "cognito_identity_pool_id" = {
      "type"  = "String"
      "value" = module.cognito.cognito_identity_pool_id
    },
    "identity_role_arn" = {
      "type"  = "String"
      "value" = module.identity.iam_arn
    }
    "user_role_arn" = {
      "type"  = "String"
      "value" = module.user.iam_arn
    },
    "sns_topic_arn" = {
      "type"  = "String"
      "value" = module.user.sns_topic_arn
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

In the AWS SAM template you can reference these parameters like this:

Parameters:
  IdentityRoleARN:
    Type: AWS::SSM::Parameter::Value<String>
    Description: Identity lambda Role ARN
    Default: /dev/example/identity_role_arn
Enter fullscreen mode Exit fullscreen mode

The only thing is, you'll still need to run this solution twice (chicken egg problem) to set the AWS SAM created parameters in the Terraform dev.tfvars file. I haven't got a better solution for this yet

Collapse
 
dnsanche profile image
Daniela Sanchez

Hello! Thanks for your detailed post!! Terraform is the IaC tool of choice of my org, but since it doesn't provide additional support for local lambda testing I'm considering to use SAM too. I'm thinking to setup everything using Terraform except the lambdas. In your solution, everytime you update the lambda code in the sam repo, do you re trigger terraform to update the lambdas? Could you just do this directly from sam repo? Why to still use terraform? Thanks!

Collapse
 
rolfstreefkerk profile image
Rolf Streefkerk

Thanks for reading! I'll try and answer below.

"do you re trigger terraform to update the lambdas?"

The trigger is on the Codepipeline configuration for the source code, you could have it trigger on git push to a branch that it will automatically start the pipeline.

"Could you just do this directly from sam repo?"

You can, sam features a deploy feature on the cli tool itself that you can use to deploy the stack directly to AWS. It's the same configuration that is in the CodePipeline build spec file.

"Why to still use terraform?"

I don't particularly like CloudFormation to perform resource deployments with, it's clunky it doesn't work well with changing resource states especially if they happen outside of the tooling for whatever reason. The drift "feature" is pointless without an automated way to correct it. Terraform state recording is much superior to fix Resource drift in my opinion.

Generally I only deploy Lambda related resources via AWS SAM, the API and Lambda's. The rest I configure and manage with Terraform.

Collapse
 
johannesmathes profile image
johannes-mathes

Really interesting idea. I followed your example.
In my organziation, we already use CodeBuild and CodePipeline for terraform deployments.
We deploy also our ECS fargate services via terraform and additional CodeDeploy steps.

I mixed our terraform CodeBuild stuff and your example and we have a pipeline which does a terraform plan, approval action with the plan, a terraform deploy and then the create changeset and execute changeset.

For the communication between terraform and CloudFormation I did not use SSM parameters. I defined parameters in the CloudFormation template.
According the SAM / CF documentation you can either override such parameters in CodePipeline or you can specify a configuration.json

The trick I did is that my terraform output is directly the output for the configuration json.
So in my terraform apply step in CodeBuild I do
terraform apply -input=false -lock-timeout=30s ./.pipeline/plan.tfplan

and then I do terraform output -json | jq .configuration_cloudformation.value > configuration.json

My terraform output statement looks like:

output "configuration_cloudformation" {
value = {
Parameters = {
SecurityGroupIds = aws_security_group.lambda.id
LambdaRoleARN = aws_iam_role.jds_monitoring.arn
Tags = var.complete_tags
...
StackPolicy = {
}
}

Collapse
 
rolfstreefkerk profile image
Rolf Streefkerk

That kind of chaining would solve the issue, thanks for sharing.