Encryption¶
One of the core assumption behind serverless-builder was to simplify a process of building reliable and secure services with best practices applied by default - that means full support for encryption at rest and in transit.
serverless-builder
has a built-in support for AWS KMS encryption with per service encryption key.
Enabling encryption feature
from serverless.service.environment import Environment
from serverless.aws.provider import Provider as AWSProvider
from serverless import Service
from serverless.aws.features.encryption import Encryption
service = Service(
"serverless-builder-demo",
"serverless-builder demo service",
environment=Environment(),
provider=AWSProvider()
)
service.enable(Encryption())
service.render()
Importing an Encryption feature will perform a coupe of things:
- Create a new Customer managed key with AWS KMS with relevant usage policy (Resource name:
ServiceEncryptionKey
) - Create a new KMS Alias matching
alias/${self:service}-${sls:stage}
pattern (Resource name:ServiceEncryptionKeyAlias
) - Import and configure serverless-kms-grants plugin for managing usage permissions on service encryption key
Side effects
Each function registered with serverless-builder will be added to serverless-kms-grants
plugin configuration without any additional work.
service.builder.function.generic("show", "Show function")
will be translated into:
kmsGrants:
- kmsKeyId: alias/${self:service}-${sls:stage}
roleName: ${self:service}-${sls:stage}-${aws:region}-service-6dbb8
Please note that IAM roles have autogenerated suffixes to enforce globally unique names.
Please check serverless-builder
naming conventions for more details.
LogGroups¶
By default serverless framework is using unencrypted logs. If you enable Encryption feature serverless-builder
will overwrite this behaviour for all registered lambda functions
and will enable log encryption with created KMS key.
Secrets¶
If you need to store secrets in your application you should use AWS Secrets Manager,
serverless-builder
makes this integration much simpler.
from serverless.aws.iam.secrets_manager import SecretsManagerReader
from serverless.aws.resources.kms import EncryptableResource
from troposphere.secretsmanager import Secret
secret = "/services/${self:service}/${sls:stage}"
self.provider.iam.apply(SecretsManagerReader(secret))
self.resources.add(Secret(title="ServiceSecret", KmsKeyId=EncryptableResource.encryption_alias(), Name=secret))
AWS by default uses default AWS managed KMS key for encrypting secrets, but you can change that behaviour to use service owned encryption key.
DynamoDB¶
serverless-builder
is providing a troposphere
compatible DynamoDB
resource definition with some extra features including
integrated support for server side encryption.
Whenever you need to create a new DynamoDB table it’s recommend to use implementation provided by serverless-builder
from serverless.aws.resources.dynamodb import Table
from troposphere.dynamodb import AttributeDefinition, KeySchema
table = Table(
"SampleTable",
BillingMode="PAY_PER_REQUEST",
AttributeDefinitions=[
AttributeDefinition(AttributeName="id", AttributeType="S"),
],
KeySchema=[
KeySchema(AttributeName="id", KeyType="HASH"),
],
)
service.resources.add(table)
serverless-builder
will translate that into a valid table definition with KMS encryption enabled, it will also define DepndsOn
to ensure that table is created after encryption key and aliases are available.
SampleTable:
Properties:
TableName: ServerlessBuilderDemoSampleTable-${sls:stage}
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: true
SSESpecification:
SSEEnabled: true
SSEType: KMS
KMSMasterKeyId:
Ref: ServiceEncryptionKey
Type: AWS::DynamoDB::Table
DeletionPolicy: Retain
DependsOn:
- ServiceEncryptionKeyAlias
S3 Buckets¶
serverless-builder
is providing a S3 Bucket wrapper which is supporting server side encryption by default, you should use it
whenever you need to create new S3 bucket.
from serverless.aws.resources.s3 import S3Bucket
bucket = S3Bucket(
"sample-bucket"
)
service.resources.add(bucket)
S3Bucket
class will automatically take care of setting up encryption for your bucket, and will generate yaml similar to
that one:
SampleBucket:
Properties:
AccessControl: Private
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Enabled
BucketName: sample-bucket.${aws:region}.${ssm:/global/primary-domain}
BucketEncryption:
ServerSideEncryptionConfiguration:
- BucketKeyEnabled: true
ServerSideEncryptionByDefault:
KMSMasterKeyID:
Ref: ServiceEncryptionKey
SSEAlgorithm: aws:kms
Type: AWS::S3::Bucket
Kinesis¶
KinesisStream
wrapper provided by serverless-builder
has as well built-in support for encryption feature detection.
All you need to do is to use it instead of default one.
from serverless.aws.resources.kinesis import KinesisStream
stream = KinesisStream("sample-name")
service.resources.add(stream)
Generated Yaml syntax
SampleName:
Properties:
Name: ${self:service}-${sls:stage}-sample-name
StreamEncryption:
KeyId:
Ref: ServiceEncryptionKey
EncryptionType: KMS
Type: AWS::Kinesis::Stream