github aws-powertools/powertools-lambda-python v2.33.0

latest releases: v2.40.1, v2.40.0, v2.39.1...
5 months ago

Summary

We are pleased to announce our first security feature: Data Masking. You can now encrypt, decrypt, or irreversibly erase sensitive information to protect data confidentiality.

We also made enhancements to our OpenAPI utility, and fixed some bugs!

⭐ Huge thanks to our new contributor: @maauk

Data masking

Docs

You can now encrypt, decrypt, or irreversibly erase sensitive information to protect data confidentiality.

image

We partnered with the AWS Crypto team to offer a thin layer on top of the AWS Encryption SDK and Amazon KMS, optimized to run on AWS Lambda ephemeral environments.

At launch, Data Masking solves three common use cases, with a fourth one (field encryption) coming.

  1. Selectively erase confidential data. You want to remove sensitive information from one or more fields for a given payload, however nested these fields might be.
  2. Encrypt and decrypt an entire payload. You want to protect the entire payload while ensuring data integrity, and optionally add metadata to each operation for further protection.
  3. Use multiple keys for high availability. You want to use more than one Amazon KMS key to encrypt while allowing decryption with any of the keys used for encryption.

It wouldn't be awesome if we didn't mention that we spent a few months crafting several code snippets, use cases, diagrams, and a simplified terminology to help you digest common industry security practices.

Enough with the talk :) Here's a working code snippet with these use cases combined.

from __future__ import annotations

import os

from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.data_masking import DataMasking
from aws_lambda_powertools.utilities.data_masking.provider.kms.aws_encryption_sdk import (
    AWSEncryptionSDKProvider,
)
from aws_lambda_powertools.utilities.typing import LambdaContext

KEY_ONE = os.getenv("KMS_KEY_ARN", "")
KEY_TWO = os.getenv("KMS_KEY_TWO_ARN", "")

logger = Logger()

encryption_provider = AWSEncryptionSDKProvider(keys=[KEY_ONE, KEY_TWO])  # encrypt/decrypt operations
data_masker = DataMasking(provider=encryption_provider)


@logger.inject_lambda_context
def lambda_handler(event: dict, context: LambdaContext) -> dict:
    data: dict = event.get("body", {})

    logger.info("Erasing fields email, address.street, and company_address")

    erased: dict = data_masker.erase(data, fields=["email", "address.street", "company_address"])  # values become '*****'

    # tenant_id being optional metadata that must match in decrypt for further protection
    encrypted: str = data_masker.encrypt(data, tenant_id=event.get("tenant_id", ""))

    decrypted: dict = data_masker.decrypt(data, tenant_id=event.get("tenant_id", ""))

    return erased

⭐⭐ Huge thanks to @seshubaws for the extensive work on this feature!

Header parameter validation in OpenAPI schema

Docs

Our enhanced OpenAPI utility now enables you to seamlessly incorporate headers into your API specifications.

from typing import List

from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.event_handler.openapi.params import Header
from aws_lambda_powertools.shared.types import Annotated  
from aws_lambda_powertools.utilities.typing import LambdaContext

app = APIGatewayRestResolver(enable_validation=True)

@app.get("/hello")
def get_hello(header2: Annotated[List[str], Header()], header1: Annotated[str, Header()]):
    print(header2)

def lambda_handler(event: dict, context: LambdaContext) -> dict:
    return app.resolve(event, context)

Changes

📜 Documentation updates

  • feat(event_handler): support Header parameter validation in OpenAPI schema (#3687) by @leandrodamascena
  • docs(data-masking): add docs for data masking utility (#3186) by @seshubaws
  • docs(proccess): add versioning and maintenance policy (#3682) by @leandrodamascena
  • chore(deps): bump squidfunk/mkdocs-material from 9aad7af to a4a2029 in /docs (#3679) by @dependabot
  • chore(deps): bump squidfunk/mkdocs-material from 58eef6c to 9aad7af in /docs (#3670) by @dependabot
  • feat(event_handler): add support for multiValueQueryStringParameters in OpenAPI schema (#3667) by @leandrodamascena
  • docs(metrics): fix empty metric warning filter (#3660) by @maauk

🔧 Maintenance

  • chore(deps-dev): bump aws-cdk from 2.124.0 to 2.125.0 (#3693) by @dependabot
  • docs(data-masking): add docs for data masking utility (#3186) by @seshubaws
  • chore(deps-dev): bump ruff from 0.1.14 to 0.1.15 (#3685) by @dependabot
  • chore(deps-dev): bump sentry-sdk from 1.39.2 to 1.40.0 (#3684) by @dependabot
  • chore(deps): bump codecov/codecov-action from 3.1.5 to 3.1.6 (#3683) by @dependabot
  • chore(deps-dev): bump aws-cdk from 2.123.0 to 2.124.0 (#3678) by @dependabot
  • chore(deps): bump squidfunk/mkdocs-material from 9aad7af to a4a2029 in /docs (#3679) by @dependabot
  • chore(deps): bump codecov/codecov-action from 3.1.4 to 3.1.5 (#3674) by @dependabot
  • chore(deps-dev): bump aws-cdk from 2.122.0 to 2.123.0 (#3673) by @dependabot
  • chore(deps): bump squidfunk/mkdocs-material from 58eef6c to 9aad7af in /docs (#3670) by @dependabot
  • chore(deps): bump the layer-balancer group in /layer/scripts/layer-balancer with 1 update (#3665) by @dependabot
  • chore(deps-dev): bump ruff from 0.1.13 to 0.1.14 (#3656) by @dependabot
  • chore(deps): bump pydantic from 1.10.13 to 1.10.14 (#3655) by @dependabot

This release was made possible by the following contributors:

@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @leandrodamascena, @maauk and @seshubaws

Don't miss a new powertools-lambda-python release

NewReleases is sending notifications on new releases.