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. Annika Hey Design Principal Atanas Atanasov Software Development Manager – Agile Frameworks Björn Stansvik Founder & Chief Executive Officer Daniela Nazim MentorMate Alumni Dimitar Dobrev MentorMate Alumni Craig Knighton Chief Operating Officer Eleonora Georgieva Global VP, Delivery George Dormishev System Administration Manager Ivaylo Kostadinov Director, Software Engineering - .NET Jamie Bolseth MentorMate Alumni Jay Miller President Jeni Kyuchukova Director, Quality Engineering Jessica Anderson VP of Finance and Administration Liz Spolyar Global Director, Continuation Engineering Nick Curran Technical Architect Nikolay Lyubchev Global Director, Talent Acquisition, MentorMate Stefan Tsvyatkov Director, Software Engineering - Mobile Stefan Tzanev Chief Financial Officer Vesselin Dobrev General Manager (Bulgaria) Sylvia Vassileva Software Development Manager - Spok Filip Gajtanovski Software Development Manager - Storyworks Krasimir K. Nikolov VP of Technology Katherine Kelly Director of Operations (USA) Carrie Siewert Strategic Account Manager Brady Swanson Global Director, Marketing Eve Poeschl MentorMate Alumni Ryan Peña MentorMate Alumni Vassil Vassilev Software Development Manager - .NET Pavel Petrov Director, Software Engineering - LAMP&FE Ivan Peev Senior Technology Manager Bob Reuss MentorMate Alumni Vera Kasapova QA Manager Greta Yamacheva QA Manager Robert Samuelsson General Manager (Sweden) Kyle Simmons Solutions Architect Robin Thomas Solutions Architect Nataliya Naydenova MentorMate Alumni Adam Malone Alexander Dimitrov Enterprise Architect Andrea Kates CEO, LaunchPad Central Andrew Eklund CEO, Ciceron Andrew Marinov Angel Nikolov MentorMate Alumni Anurag Shukla Aron Wolde MentorMate Alumni Ashley Goodridge Office Assistant Benjamin Gramlich MentorMate Alumni Chris Black MentorMate Alumni Christa Haeg MentorMate Alumni Colin Lee MentorMate Alumni Deyan Stoynov MentorMate Alumni Dimitar Danailov MentorMate Alumni Dobrinka Tabakova Doug Leatherman Emily Genco MentorMate Alumni Fanka Vassileva Gabriela Zagarova MentorMate Alumni Gary Conkright CEO, physIQ Gary Fingerhut Executive Director, Cleveland Clinic Innovations Gavin Finden MentorMate Alumni Georgi Graham Klang Hyusein Hyuseinov Senior Automation QA Ian Good Global VP, Operations Iva Jack Cosentino James Williams John Byrne Kaloyan Stoilkov MentorMate Alumni Kosta Hristov Krasimir Gatev Senior Android Developer Lazar Petrakiev Lyubomir Dobrev Senior .NET Developer Lubomir Velkov Marin Yotovski Mark Smith MentorMate Alumni Martin Dimitrov MentorMate Alumni Martin Kalyonski Mike Hagan MentorMate Alumni Nikolay Andonov Nikolay Arhangelov Riley Panko Guest Contributor Roger Ferguson MentorMate Alumni Ryan Sysko Chairman, WellDoc Ryan Blake MentorMate Alumnus Sarah Rockholt MentorMate Alumni Sean McDevitt CEO, Sensei Siyana Slavova Stanislas Walden MentorMate Alumni Stanislav Atanasov Stanislava Bogdanova MentorMate Alumni Stefanie Trimble MentorMate Alumnus Stephen Fluin Stoyan Stoyanov MentorMate Alumnus Tessa Cacek Staffing Manager Tom Clemens MentorMate Alumnus V8 JavaScript Engine Viktor Mitev Yolanda Petkova Marketing Design Lead Pete Anderson Lead Product Owner, Target Vasil Nonchev Java Software Development Manager Dilyana Totseva QA Manager Stanimir Nikolov Software Development Lead - iOS, MentorMate Rosen Kolev Technology Principal Dimitar Mihaylov MentorMate Alumni Nikola Genov Software Architect - .NET Neli Todorova Software Development Manager - LAMP Yavor Dimitrov MentorMate Alumni Georgi Karanedyalkov Software Development Lead - Android, MentorMate Denislav Ganchev Technology Principal Stefan Shopov QA Manager Konstantin Rusev Java Developer Borislav Dimitrov Senior Android Developer, MentorMate Tsvetelina Lazarova MentorMate Alumni Dimitar Gadzhev Developer Plamen Stoev Software Development Manager - Front-end Jake Nelsen Senior Experience Designer Zlati Pehlivanov Senior Software Engineer II Kate Tolmie Senior Experience Designer Martin Angelov Director, Software Engineering - LAMP&FE, MentorMate Dimitar Zhelev Senior .NET Developer Joel Swenson Content Manager Kiril Ivanov Quality Assurance Analyst Viktor Hristoskov Software Development Lead - iOS, MentorMate Violeta Nikolcheva Database Developer Biliana Kadakevlieva Senior Quality Assurance Analyst Chris McLeod Senior Solutions Consultant Antonii Georgiev Junior .NET Developer Alexander Rusev Front-End Developer Matt Erickson MentorMate Alumni Brian Buchkosky Global Director, PMO David Tran MentorMate Alumni Kristin Krueger MentorMate Alumni Magdalena Chervenkova Business Analyst Denny Royal Chief Design Officer Joe Bodell MentorMate Alumni Viktoria Chuchumisheva HR Manager Kalina Tekelieva Senior Content Marketing Artist Daniel Rankov MentorMate Alumni Alexander Alexandrov BA Lead MentorMate Clint Rowles VP, Business Development Nikola Donev SysOps & DevOps Lead Tseko Tsolov Frontend Developer Denislav Lefterov Automation QA Analyst Dilyana Kodjamanova MentorMate Alumni Emma Jorstad Project Manager, Lead Georgi Georgiev Software Development Lead - LAMP, MentorMate Martin Panayotov Senior iOS Developer, MentorMate John Blake Senior Account Manager Tyler Compton Solutions Architect Nikola Peevski Software Developer — Lamp & Front-End Aaron Whitney Director of Client Strategy Veliko Ivanov Senior Cloud Engineer Suzanne O’Brien Senior Project Manager Svetlin Stanchev Software Development Lead - Front-end, MentorMate Todor Todorov Senior Cloud Engineer Kate Stamatova Senior QA Analyst Frank Anselmo Global Director, Project Management Gyuner Zeki Solutions Architect Galin Stanchev QA Analyst Sarah Hoops Business Development Manager Brenden Diehl Business Development Manager Anna Krivova Software Development Lead - Front-end, MentorMate Ivelina Kavalova Senior Business Analyst, MentorMate Paul Sanders MentorMate Alumni Jim Cikanek Senior Client Strategist Samuil Yanovski Software Development Manager - Android, MentorMate Krasimir Gatev Senior Android Developer, MentorMate Kristina Goryalova Talent Acquisition Manager Elena Petrova HR Specialist Jay Matre Senior Business Architect, MentorMate Lilyana Dimitrova QA Specialist Josh Marquart Chief Strategy Officer Mario Gorki Senior Mobile Developer Simeon Zhekov Cloud Engineer Hristo Stoyanov Cloud & DevOps Lead Ben Wallace Enterprise Architect Boyan Stoyanov Data & Dota Specialist Petya Ivanova Director, Software Engineering - Java Sebastian Ortiz-Chamorro VP of Engineering, Latin America Consuelo Merino Director of Operations, MentorMate Carlos Rodríguez Data & Analytics Manager, MentorMate Joel Hernandez CTO, eLumen 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. 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. 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. 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. 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. 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. 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. 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. 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. 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 Sign up for our monthly newsletter. Sign up for our monthly newsletter.