mpryahin / saas-tenant-isolation-architecture

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Saas Tenant Isolation Architecture

This repository contains a small application that implements the principles discussed in the Saas Tenant Isolation Architecture blogpost.

What's the problem this work aims to solve? Ideally IAM roles should be scoped to the smallest set of resource and actions permissions required. In a multi-tenant application, the combination of multiple tenants and services can result in a high number of roles to manage.

Overview

This project contains source code and supporting files to deploy the application. It implements two lambda functions and a DynamoDB table.

Export Tenant Data Diagram

  1. A CodeCommit repository contains IAM Policy templates. Changes to the templates can be tracked using version control.

  2. The creation of a git tag with the prefix release invokes a CodePipeline execution, that zips the templates and uploads the file to S3.

  3. The Template Bucket contains the uploaded template files. Each object is of the form templates/$GIT_HASH/policies.zip

  4. A multitenant application makes a request to the ExportTenantData Function, containing the Authorization Header. The header is of the form Authorization: Bearer $JWT. $JWT represents a JSON Web Token (JWT). The JWT contains a custom claim, custom:tenant_id. This custom claim is used by the Token Vending Layer to scope credentials to just the responsible tenant.

  5. The [Token Vending Layer](#Token Vending Layer) retrieves the templates from the S3 Bucket. TODO explain further

  6. The credentials from the [Token Vending Layer](#Token Vending Layer) are used to access the multi-tenant DynamoDB table. These credentials are scoped to the tenant, and don't have permission to access other tenants data.

ExportTenantData Function

The ExportTenantData function demonstrates a small microservice used by tenants of an application. The ExportTenantData function can store and retrieve data from a multi-tenant DynamoDB table.

The ExportTenantData function uses the Lambda Layer TokenVendingLayer to assume a role with credentials scoped to the tenant making the request.

Template Pipeline

An AWS CodeCommit repository contains templated IAM Policies. Upon the creation of a tag with prefix release, for example release-1.0, Amazon CodePipeline creates a zip file of the templates and stores it as an object in S3. The Token Vending Layer retrieves the zipped templates file from S3. An AWS CodePipeline executes on change to the repository.

Token Vending Layer

This sample uses the Dynamic Policy Generation library. Read more on the Dynamic Policy Generation blogpost

⚠️ Warning
This sample uses a hardcoded secret for verifying the JSON web token signature.
This shouldn't copied in an application.
Instead, the application should retrieve the secret from AWS Systems Manager Parameter Store or AWS Secrets Manager.

Multi-Tenant DynamoDB Table

AssumeRoleWatchDog

The AssumeRoleWatchDog resource is a lambda function. The purpose of the AssumeRoleWatchDog is safeguard against the assumption of a role without an inline policy included. This is important in a multi-tenant environment It inspects AssumeRole events of the account. If a role in the account is assumed without an inline policy, the watchdog sends a notification to the WatchdogSnsTopic defined in the template.

Deploy the sample application

The application uses several AWS resources, including Lambda functions and an API Gateway API. The Resources section of the file template.yaml defines the resources in this project.

  1. Prerequisites

  2. Clone the repository

    git clone git+https://github.com/aws-samples/saas-tenant-isolation-architecture
  3. To build and deploy your application for the first time, run the following in your shell:

    export STACK_NAME=<Define the stack name>
    
    # The packaged template is uploaded to an S3 bucket.
    export DEPLOYMENT_S3_BUCKET="$STACK_NAME"-packaging-bucket
    
    # The S3 Bucket containing the zipped policy templates to bootstrap the CodeCommit repository
    export TEMPLATE_BUCKET_NAME=<template s3 bucket>
    export TEMPLATE_OBJECT_KEY=<template zip file>
    
    # Create the bucket if it doesn't exist
    # aws s3 mb s3://$DEPLOYMENT_S3_BUCKET
    
    # Build the source
    make build
    
    # Deploy
    make deploy

    The first command will build the source of your application. The second command will package the application and deploy your application to AWS.

    You can find the API Gateway Endpoint URL in the output values displayed after deployment.

Testing the Application

Test that the deployment was successful by posting and retrieving data from the /tenant endpoint.

Post data to the endpoint Set the URL variable to the API Gateways Endpoint Output from the CloudFormations stack Set the AUTH to a valid JWT token.

URL=<ENDPOINT URL>
AUTH=<JWT TOKEN>

curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "Authorization: Bearer $AUTH" \
    --data '{"data":"test-data"}' \
    $URL 

Get data from the endpoint

curl \
    --header "Authorization: Bearer $AUTH" \
    $URL

Cleanup

To delete the deployed sample application, follow the steps below.

  1. Delete contents of S3 buckets included in the application.
    • PipelineArtefactBucket
    • TemplateOutputBucket
  2. Delete CloudFormation stack.
    • To delete the stack with the aws cli, use the following command.
aws cloudformation delete-stack --stack-name <STACK NAME>

License

This sample is licensed under the MIT-0 license.

About

License:MIT No Attribution


Languages

Language:Java 95.5%Language:Makefile 4.5%