AWS Cloud Operations Blog
Secure Serverless Development Using AWS Service Catalog
Serverless computing allows you to build and run applications and services without having to manage servers. AWS Service Catalog allows you to create and manage catalogs of services that are approved for use on AWS. Combining Serverless and Service Catalog together is a great way to safely allow developers to create products and services in the cloud.
In this post, I demonstrate how to combine the controls of Service Catalog with AWS Lambda and Amazon API Gateway and allow your developers to build a Serverless application without full AWS access.
Workflow
For this example, I have written a Lambda function that returns sample JSON and uploaded it to Amazon S3. I then created a product in Service Catalog that leverages an AWS CloudFormation template to deploy a Serverless product calling the Lambda function and API Gateway.
Initial setup
There are a few basic actions to take before allowing developers to build their Serverless application. The following steps require administrator access to AWS resources via the AWS Management Console.
- Choose the AWS Region in which to host this Serverless application.
- Create an S3 bucket to host your Lambda code package.
- Use your favorite editor and create a sample Python Serverless Application serverlessapp.py with the following contents:
# A Python Lambda Script That Returns Some JSON def endpoint(event, context): output = { "data": {"a": 1, "b": 2, "c": 3} } return output
- Compress/ZIP this file with the name serverlessapp.zip you may have to rename the zip after compressing it, but ensure the file that gets uncompressed has the serverlessapp.py name.
- Upload this file into the S3 bucket you created with public read permissions on the object
- Create an AWS service role for Lambda so that your application can inherit and execute against AWS resources.
- Add the following managed policies to your role:
- AWSLambdaFullAccess
- AmazonAPIGatewayAdministrator
- AWSServiceCatalogEndUserFullAccess
- Name your role scserverless.
- After your role is created, open the role and choose Trust Relationships, edit trust relationship. Copy and paste over the existing text the following text:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "lambda.amazonaws.com", "servicecatalog.amazonaws.com", "apigateway.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] }
- Create an AWS IAM user for the developer creating the Serverless application, with AWS Management Console Access and attach the following managed permissions:
- AWSServiceCatalogAdminFullAccess
- AmazonS3FullAccess
- ReadOnlyAccess
Service Catalog and Serverless application setup
Service Catalog acts as the landing zone for your developers to access building and launching Serverless applications. They only have access to build and launch things from Service Catalog itself. Products created in Service Catalog are all based on CloudFormation templates.
- Log out of the Management Console as your admin user and log back in as the developer user you created in the previous step.
- Create a Service Catalog portfolio for the developer or developers who should have access to build Serverless applications.
- Add the developer user that you created to the portfolio.
- Use your favorite editor and create a AWS Service Catalog product serverlessapp.yaml with the following contents:
AWSTemplateFormatVersion: "2010-09-09" Description: Python Serverless Application that outputs some sample JSON Metadata: 'AWS::CloudFormation::Interface': ParameterGroups: - Label: default: Runtime and Environment Parameters: - Runtime - MemorySize - Timeout - Role - Label: default: S3 Info Parameters: - S3Bucket - S3Key ParameterLabels: Runtime: default: 'Runtime:' MemorySize: default: 'Memory Size:' Timeout: default: 'Execution Timeout:' S3Bucket: default: 'Bucket:' S3Key: default: 'Key:' Parameters: Owner: Description: Who owns this Serverless Application? Enter email here. Type: String Default: developer@example.com AllowedPattern: "^[\\x20-\\x45]?[\\w-\\+]+(\\.[\\w]+)*@[\\w-]+(\\.[\\w]+)*(\\.[a-z]{2,})$" ConstraintDescription: must be a valid email address Runtime: Description: Select the correct runtime for the lambda Default: python2.7 AllowedValues: - nodejs6.10 - java8 - python2.7 - python3.6 Type: String S3Bucket: Description: The bucket the code is in Type: String S3Key: Description: The name of the zip file of your code Type: String Description: Description: The description of the Lambda Function Type: String Default: Serverless Example MemorySize: Description: 'Memory Size:' Type: Number Default: 128 AllowedValues: - 128 - 256 - 512 - 1024 Timeout: Description: Execution Timeout Type: Number Default: 30 Resources: endpointApiPermissionProd: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:invokeFunction' Principal: apigateway.amazonaws.com FunctionName: !Ref endpoint SourceArn: !Sub - >- arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/POST/endpoint_python - __Stage__: Prod __ApiId__: !Ref ServerlessRestApi ServerlessRestApiProdStage: Type: 'AWS::ApiGateway::Stage' Properties: DeploymentId: !Ref ServerlessRestApiDeployment00 RestApiId: !Ref ServerlessRestApi StageName: Prod ServerlessRestApiDeployment00: Type: 'AWS::ApiGateway::Deployment' Properties: RestApiId: !Ref ServerlessRestApi Description: 'RestApi deployment id: 00' StageName: Stage endpoint: Type: 'AWS::Lambda::Function' Properties: Code: S3Bucket: !Ref S3Bucket S3Key: !Ref S3Key Description: '' MemorySize: !Ref MemorySize Handler: serverlessapp.endpoint Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/scserverless' Timeout: !Ref Timeout Runtime: !Ref Runtime ServerlessRestApi: Type: 'AWS::ApiGateway::RestApi' Properties: Body: info: version: '1.0' title: !Ref 'AWS::StackName' paths: /endpoint_python: get: consumes: - application/json produces: - application/json responses: '200': description: 200 response headers: Content-Type: type: string x-amazon-apigateway-integration: httpMethod: POST credentials: !Sub 'arn:aws:iam::${AWS::AccountId}:role/scserverless' type: aws uri: !Sub >- arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${endpoint.Arn}/invocations responses: { "default": { "statusCode": "200", "responseTemplates": { application/json: "" } } } passthroughBehavior: "when_no_templates" swagger: '2.0' endpointApiPermissionTest: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:invokeFunction' Principal: apigateway.amazonaws.com FunctionName: !Ref endpoint SourceArn: !Sub - >- arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/POST/endpoint_python - __Stage__: '*' __ApiId__: !Ref ServerlessRestApi Outputs: TestURL: Description: The serverless url you can test in a browser. Value: !Join [ "", [ "https://", !Ref "ServerlessRestApi", ".execute-api.", !Sub "${AWS::Region}", ".amazonaws.com/Prod/endpoint_python"]] FunctionName: Description: The name of the lambda function. Value: !Ref endpointApiPermissionProd APIGatewayName: Description: The name of associated API Gateway. Value: !Ref 'AWS::StackName' S3Bucket: Description: The S3 bucket your serverless app resides. Value: !Ref S3Bucket ServerlessAppZIP: Description: The serverless app zip file name. Value: !Ref S3Key
- Go into your portfolio and choose Upload new product.
- Product Name: Python Serverless Application
- Description: Outputs some sample JSON
- Provided by: [your developer user]
- Choose Next, Next.
- For Select template, choose Upload a template file.
- Click Choose File and select the serverlessapp.yaml file you created
- Version title: Serverless version 1
- Choose Next, Create.
Create Service Catalog constraints
Applying a Service Catalog launch constraint is the way to control developer access to Lambda functions, API Gateway API actions, and other resources for Serverless applications through a IAM role and not through individual user management console access.
- In your Service Catalog portfolio, expand Constraints.
- Choose Add constraints.
- Product: Python Serverless Application
- Constraint Type: Launch
- Choose Continue.
- IAM Role: scserverless
- Choose Submit.
Service Catalog Serverless application setup
With CloudFormation templates and Service Catalog, you can build a Lambda template that allows you to launch and configure the specific resources that your Serverless application needs. The output of the CloudFormation template provides you with the API Gateway entry point to your Lambda application.
-
- In the Service Catalog console, choose Product List.
- Choose the Python Serverless Application option and choose Launch product.
- Name: Python-Serverless-Application
- Version: Serverless Version 1
- Choose Next.
- For Parameters, enter the following:
- Runtime: Python 2.7
- Memory Size: 128
- Execution Timeout: 30
- Bucket: {The bucket name you created that has the Python zip file in this example, such as serverless-bucket}
- Key: {The name of your Python zip file in this example serverlessapp.zip}
- Owner: {your email}
- Description: {Serverless Example}
-
- Leave the rest of the fields as their default values, and choose Launch.
- Under Events, choose the refresh icon until you see Status Succeeded
- Expand Outputs and copy the unique value for TestURL, for example, https://outbd7gim9.execute-api.us-west-2.amazonaws.com/Prod/endpoint_python
- Paste the URL into a browser and you should get the following output:
{"data": {"a": 1, "c": 3, "b": 2}}
Summary
In this post, I’ve demonstrated how to use Service Catalog and allow your developers to create Serverless applications safely without giving them access to the AWS Management Console. Service Catalog can also allow you to give limited granular access for deploying S3, Amazon EC2, and other AWS services in the same manner, making it a powerful control mechanism.
About the Author
Phil Chen has been designing and deploying AWS architectures for over 10 years and loves helping customers do the same.