Hoppa till innehållet
  • Tjänster
    Vår arbetsmetod
    Personlig, djupgående teknisk vägledning på global nivå som hjälper organisationer uppnå sina mål för digital transformering.
    Läs mer
    • Vår arbetsmetod
    • Skräddarsydd utveckling
    • Design
    • DXP
    • Data och analys
    • Moln & DevOps
    • Support
  • Projekt
    Våra projekt
    Genom vår expertis inom strategi, design och teknik hjälper vi kunder att leverera digital transformation i stor skala.
    Läs mer
    • Våra projekt
    • Sjukvård
    • Jordbruk
    • Tillverkning
    • Finansiella tjänster
    • Utbildning
  • Företaget
    Om Oss
    Under mer än 20 år har vi ingått partnerskap med organisationer i alla storlekar och branscher för att lösa deras mest komplexa företagsproblem.
    Läs mer
    • Om Oss
    • Ledning
    • Platser
    • Evenemang
    • Nyheter
  • Karriärer
    Bli en del av vårt team
    Ta din karriär till nästa nivå. Vi erbjuder spännande möjligheter i alla skeden av livscykeln inom mjukvaruutvecklingen.
    Läs mer
    • Bli en del av vårt team
    • Lediga jobb
    • Rekryteringsprocess
    • Förmåner
    • Lärande och utveckling
  • Insikter
    Från våra experter
    Läs våra senaste bloggar, titta på våra nyaste videor och bläddra i vårt bibliotek med e-böcker där våra experter ger värdefulla insikter.
    Läs mer
    • Från våra experter
    • Blogg
    • Video
    • E-bok
  • Kontakta оss
Menu
November 10, 2021

Terraform and Serverless Framework Integration in AWS

Develop your infrastructure rapidly and with less overhead by leveraging the strong sides of Serverless Framework and Terraform.

Introduction

Terraform is a declarative resource configuration language with extensive support for the AWS cloud computing platform, and it is one of the go-to solutions for managing infrastructure as code. Data sources allow Terraform to use the information defined outside of it, defined by separate Terraform configuration, or modified by functions or other IaC implementations.

Serverless Framework is an application framework that helps you develop and deploy your AWS Lambda functions, along with the AWS infrastructure resources they require. It manages your code as well as the underlying infrastructure.

Challenge 

The main problem when providing the application development team with access to their own infrastructure (so that they have a flexible deployment process) is defining and retaining the security boundaries over their actions. By default, this is not easily achieved in the Serverless Framework, and here is where the Terraform-defined IaC comes in.

When you separate the infrastructure resources between the two, you can draw a clear line of responsibility for the Security management. By using both of them, you can achieve a separation between the shared and app-specific infrastructure. Managing the shared infrastructure of core resources, such as Networking, Security, RDS, Persistent Storage, etc., with Terraform, gives you a single source of truth for all application-specific infrastructures.

This allows you to completely separate responsibilities for the application and infrastructure deployments. Leveraging the Serverless Framework allows you to iterate your application release without touching your shared infrastructure. Software releases are decoupled from shared infrastructure, enabling you to focus on the application itself without worrying about infrastructure changes.

Solution

Let’s take a look at how to integrate both of them in a complex deployment pipeline. For example, we’ll use a Pipeline with a couple of Terraform deployments that handle the Infrastructure not as a single deployment but as multiple deployments that have complex dependencies between elements.

We define the application deployment dependencies order so that all dependencies get resolved in the correct order. Each deployment exports a set of SSM Parameter Store parameters that will be used as a Data Source for the next deployments. We can even encrypt the parameters with a specific KMS key to ensure that the development team of the Application 1 doesn’t have access to parameters for Application 2 and vice versa.

Picture of a pipeline example

  1. At the start, we have a Git repository that holds all of our deployments code or just references to it like the pre-deployment version.
  2. In the next step, we deploy all of our shared infrastructures, such as VPC networking, basic security groups, and underlying resources, shared between all applications and services. We export references to different resources that will be used as Data sources for the Application Terraform and Serverless Framework deployments either as separate parameters in the SSM Parameter Store per application or as a single parameter that is shared between them. 
  3. Next, we deploy our Cognito-related elements, such as UserPools, IdentityProviders, and all other Cognito-related resources, such as IAM roles, for example. We also export the reference values of the resources that will be used as Data sources for the next deployment. As of this step, the shared infrastructure deployment and Cognito deployment do not have any references to each other.
  4. We continue with the Terraform deployment of the Application 1 stateful infrastructures, such as its RDS security groups, DynamoDB tables, SNS, SQS, and its CodeDeployment project used for the Serverless Framework deployment. Here we reference the SSM Parameter Store parameter as a Data Source that has been exported in the shared infrastructure Terraform deployment so that we can place the resources in the predefined subnets.
  5. Next, we run the Serverless Framework deployment for Application 1, which references the shared SSM Parameter Store for both shared infrastructures, Cognito and Application 1 Terraform deployments, and use them to deploy our Application code and its app-specific infrastructure, such as Lambda functions, API Gateways, etc.
  6. The Application 2 Terraform deployment is the next step, and it uses the same logic as Application 1, referencing the shared infrastructure SSM Parameter Store parameters.
  7. Then we run the Application 2 Serverless Framework deployment and reference the shared infrastructure, Cognito, Application 2 Terraform, and the Application 1 Serverless Framework exported SSM Parameter Store parameters. Application 2 will require some data from Application 1 and, therefore, will access the Private API Gateway created from Application 1. We don’t share direct access to the Database between Applications but access through specific private API endpoints.
  8. We continue with the deployment of our Front-End application, which again uses a Terraform infrastructure deployment that handles the CloudFront distribution, S3 bucket, WAF configuration, etc.
  9. In the end, we have the Front-End Application deployment that references the Cognito, Front-End Terraform SSM Parameter Store parameters, the Application 1 and Application 2 parameters so that it can have their public endpoints.

Now let’s take a look at the exact code used for exporting references to SSM Parameter Store parameters and then the backward process of ingesting it back as a Data Source to the next steps.

In the shared infrastructure deployment we create the resources and then export them in the SSM Parameter Store as parameters:

resource "aws_security_group" "app1_egress_only" {
 name        = "${local.name}-app1-egress-only"
 description = "${local.name}-app1-egress-only"
 vpc_id      = local.vpc_id
 
 egress {
   description = "${local.name}-application1-egress-only"
   from_port   = 0
   to_port     = 0
   protocol    = "-1"
   cidr_blocks = ["0.0.0.0/0"]
 }
 tags        = local.org_tags
}
 
resource "aws_kms_key" "app1" {
 deletion_window_in_days = 7
 enable_key_rotation     = true
 policy                  = data.aws_iam_policy_document.app1_kms_key.json
 tags                    = local.org_tags
}
 
resource "aws_ssm_parameter" "app1_kms_arn" {
 name        = "/shared_infra/application1/kms_arn"
 description = "The parameter description"
 type        = "SecureString"
 value       = aws_kms_key.app1.arn
 key_id      = aws_kms_key.app1.arn
 tags        = local.org_tags
}
 
resource "aws_ssm_parameter" "app1_security_group_id" {
 name        = "/shared_infra/application1/security_group_id"
 description = "The parameter description"
 type        = "SecureString"
 value       = aws_security_group.app1_egress_only.id
 key_id      = aws_kms_key.app1.arn
 tags        = local.org_tags
}

Then we can reference the parameters in the Application 1 Terraform deployment:

data "aws_ssm_parameter" "kms_arn" {
 name = "/shared_infra/application1/kms_arn"
}
 
data "aws_ssm_parameter" "security_group_id" {
 name = "/shared_infra/application1/security_group_id"
}
 
locals {
 kms_arn           = data.aws_ssm_parameter.kms_arn.value
 security_group_id = data.aws_ssm_parameter.security_group_id.value
}

Viable option is to reference them in the serverless.yml in the Application 1 Serverless Framework deployment, export the desired resources that this deployment creates and are necessary for the next ones:

provider:
 name: aws
 runtime: nodejs12.x
 stage: ${opt:stage, 'main'}
 region: ${opt:region, 'eu-west-2'}
 versionFunctions: false
 environment:
   # Static
   AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1
   COGNITO_USER_POOL_ARN: ${self:custom.cognito.endUserPoolArn}
   
Custom: 
 # Custom configurations here starting with the SSM Prefixes
 ssmSharedInfraPrefix: /shared_infra/application1/
 ssmCognitoPrefix: /cognito/application1/
 ssmOutputPrefix: /${self:service}/${self:provider.stage}/
 # Custom configuration for the VPC config that is reused by the functions
 VpcConfig:
   securityGroupIds: ${ssm:${self:custom.ssmSharedInfraPrefix}security_group_id~split}
   subnetIds: ${ssm:${self:custom.ssmSharedInfraPrefix}subnet_ids~split}
 # Cognito UserPool references to the ssm parameters
 cognito:
   endUserPoolArn: ${ssm:${self:custom.ssmCognitoPrefix}END_USER_POOL_ARN}
   endUserPoolId: ${ssm:${self:custom.ssmCognitoPrefix}END_USER_POOL_ID}
 CustomerAuthorizer:
   arn: ${self:provider.environment.COGNITO_USER_POOL_ARN}
 # Custom config for the CORS config that is reused by the functions
 CorsConfig:
   origin: '*'
   headers:
     - Content-Type
     - Authorization
     - Access-Control-Allow-Headers
   allowCredentials: false
 
functions:
 debug-route:
   handler: functions/function1/function1.handler
   events:
     - http:
         path: /debug
         method: GET
         authorizer: ${self:custom.CustomerAuthorizer}
         cors: ${self:custom.CorsConfig}
   vpc: ${self:custom.VpcConfig}
resources:
 Resources:
   gatewayApiId:
     Type: AWS::SSM::Parameter
     Properties:
       Type: String
       Name: ${self:custom.ssmOutputPrefix}GATEWAY_API_ID
       Value:
         Ref: ApiGatewayRestApi
   gatewayUrl:
     Type: AWS::SSM::Parameter
     Properties:
       Type: String
       Name: ${self:custom.ssmOutputPrefix}GATEWAY_URL
       Value:
         Fn::Join:
           - ''
           - - 'https://'
             - Ref: ApiGatewayRestApi
             -  
'.execute-api.${self:provider.region}.amazonaws.com/${self:provider.stage}
'

By implementing the same logic in the rest of the deployments, we can easily handle all dependencies and follow a clear separation over the resources. This enables us to achieve separation by leveraging different KMS keys for the encryptions of the SSM Parameter Store parameters that give access to them, based on IAM permissions for using the KMS keys.

Conclusion

By combining both methods to build your infrastructure, you are leveraging the strong sides of the Serverless Framework to develop more rapidly with radically less overhead by directly managing the app-specific infrastructure. Referencing the shared infrastructure, managed by Terraform, and using the SSM Parameter Store parameters to target resources from one to the other is another benefit. Serverless Framework’s flexibility to develop and deploy your application is just a layer above the IaC that Terraform manages. Both of them are an integral part of your software delivery pipeline.

 

Tags
  • Cloud & DevOps
Share
  • Share on Facebook
  • Share on LinkedIn
  • Share on Twitter
Share
  • Share on Facebook
  • Share on LinkedIn
  • Share on Twitter

Read what's next.

Blog

Infrastructure as Code: Terraform vs CloudFormation

Blog

Digital Transformation in Manufacturing

  • Twitter
  • LinkedIn
  • Instagram
  • Facebook
United States
MentorMate1350 Lagoon Ave, Suite 800
Minneapolis
, MN 55408

+1 612 823 4000
Bulgaria
67 Prof. Tsvetan Lazarov Blvd.
Sofia 1592, Bulgaria,
+359 2 862 2632
Sweden
Drottninggatan 29
411 14 Göteborg

+46 3 199 0180
Paraguay
Carlos M. Gimenez 4855
Asunción, Paraguay

+595 21 327 9463

Copyright © 2023 MentorMate, LLC

  • Cookie Policy
  • Sekretesspolicy
This site is registered on wpml.org as a development site.