Skip to content
TaylorGarpow edited this page Jun 8, 2023 · 24 revisions

Frankenstack

Frankenstack is a deployment orchestration tool that is agnostic to the underlying deployment framework. It allows multiple components to be deployed via different tools like AWS CDK, Serverless Framework, AWS CloudFormation. Frankenstack also allows outputs of the components to be referenced across different deployments.

Prerequisites

Installation

  1. Install the software

    • Open your CLI of choice and run the following command to install the software[^note]. [^note]: Starting with npm 7 installation will fail unless the --legacy-peer-deps switch is used.
    • Make sure your local credentials are that for the Frankenstack AWS account.
    npm i -g frankenstack
    
  2. Create a new AWS Profile on your computer

    1. Log into AWS SSO here

    2. Go to the frankenstack account in the accounts list and expand it.

    3. Click Command line or programmatic access, and copy option 2 into NotePad, this will be needed later.

    4. Open the .aws folder on your local machine and then the credentials file. Edit the credentials file with NotePad or your text editor of choice. The .aws folder is usually located in:

      • Windows: C:\Users[replace with your username].aws
      • Linux or Mac: TBD
    5. In the credentials file, you will see [default] with credentials listed below it. Add 2 lines beneath the last default credential and paste what you copied from the AWS SSO account page. Rename what is in the brackets that you copied (most likely something like [########_FrankenstackUser]) to a custom profile name, most use frank or frankenstack.

    6. Save your changes to the document.

    7. You are now able to use your profile to run all Frank commands.

      Here's an example using Component Describe command

      frank component describe env componentName --profile profileName
      

      Your profile will be saved forever in the credentials file. The credentials do expire (usually after 24 hours) so you will only need to get new credentials from the AWS SSO accounts screen and then update this file.

Commands and Usage

Deploy

To deploy components via frankenstack run the following command with a valid yaml file defining your components.

frank deploy path/to/template.yml [--params='{"key": "value"}']
Deployments can be parameterized by passing in parameters via the command line argument or with child templates.

Parametrized Deployments and Child templates

Frankenstack supports referencing child templates in one parent template. This can be used to deploy multiple templates in one deploy. This only works when all templates are deploying to the same environment. A sample parent template can look like (it can also have components of its own):

# template.parent.yml
env: ${params:env}
templates:
  - path: ${self:env}/template.my-stack.yml
    params:
      url: ${self:env}-app.example.com #referenced in the child template

And the child template could look like:

env: ${params:env}
components:
  - name: my-component
    provider:
      name: my-provider
    inputs:
     serviceUrl: ${params:url} # from the parent template

The above templates could be deployed by running the command frank deploy template.parent.yml --params '{"env": "my-env"}'

Remove

To remove components via frankenstack, run the following command. This is only implemented for serverless and AWS CDK.

frank remove env componentName

Where env is the environment in which the component resides and componentName is the name of the component you wish to rollback.

Rollback

A single component can be rolled back using the rollback command. This command only works after a deployment is complete and will not rollback a deployment in progress. To run a rollback on a component run:

frank rollback env componentName

Where env is the environment in which the component resides and componentName is the name of the component you wish to rollback.

Describe a component

To look up the current state of a component you can run:

frank component describe env componentName

This will tell you when the component was last deployed, how it was configured, and any outputs the component has.

IAM

Frankenstack supports user permissions through the use of policies. Users along with their associated policies are provisioned through a template but are authenticated via the AWS IAM user that is configured via the users local AWS profile. Therefore when provisioning users, be sure to make sure that the username matches the AWS IAM user id.

To provision a list of users and policies you can run the following command from the CLI:

frank iam /path/to/template.yml

Where a sample template could be:

policies:
  - name: og:admin
    statements:
      - effect: Allow
        actions:
          - '*'
        resources:
          - '*'
  - name: og:dev
    statements:
      - effect: Deny
        actions:
          - 'deploy:write'
          - 'secrets:*'
        resources:
          - 'prod:*'

users:
  - id: foo.bar
    email: foo@gmail.com
    policies:
      - og:admin
      - og:dev

Currently frankenstack enforces only the deploy:write action.

More 'iam' examples:

Full Admin

policies:
  - name: admin
    statements:
      - effect: Allow
        actions:
          - '*'
        resources:
          - '*'
users:
  - id: foo.bar
    email: foo.bar@gmail.com
    policies:
      - admin

Cross Account Support

New accounts can be added using the aws-account provider, be sure to NEVER push this Yaml file. Delete it once the template has been deployed. A sample template would look like:

env: my-aws-account
components:
  - name: aws
    provider:
      name: aws-account
    inputs:
      accountId: '1234567890'
      AWS_ACCESS_KEY_ID: xxxxxxxxxxxxx
      AWS_SECRET_ACCESS_KEY: xxxxxxxxxxxxxxxxxxxxxxxxxx

Once your account credentials are provisioned you can now deploy your component cross account by editing your component provider in the template to look like this:

provider:
  name: cdk
  config:
    account: ${my-aws-account:aws}

[Important] This feature only supports the cdk provider currently. Support for serverless-framework is coming soon.

Providers

app-params

Frankenstack supports the "app-params" provider when deploying a Frank component. This provider is designed to write both hardcoded app parameters and Frank referenced secrets to a single parameter object in AWS Parameter Store. The app parameters are to be defined within a template that looks something like:

env: dev
components:
  - name: fooservice-app-params
    provider:
      name: app-params
    inputs:
      FOO_CLIENT_ID: ${dev:foo-credentials:FOO_CLIENT_ID}
      FOO_CLIENT_SECRET: ${dev:foo-credentials:FOO_CLIENT_SECRET}
      FOO_USER: test-user
      FOO_PASSWORD: ${dev:foo-credentials:FOO_PASSWORD}
      BAR_REQUEST_URL: https://www.test-request-url.com

The name of the parameter store parameter (following the syntax "/${componentEnvironment}/${componentName}") will be output to the console following a successful deployment.

hardcoded

If the value of an environment variable is not secret, then you can hardcode the value and then reference it in an app-params component to deploy the parameter.

Using this method, you can reference hardcoded values from other environments to simplify creating dynamic environments.

env: test
components:
  - name: fooservice-hardcoded-app-params
	provider:
		name: hardcoded
	inputs:
		REFERENCED_API_URL: https://dev-foo.com
  - name: fooservice-app-params
    provider:
      name: app-params
	  config:
        account: ${aws-account:aws}
        region: us-east-1
    inputs:
      REFERENCED_API_URL: ${test:fooservice-hardcoded-app-params:REFERENCED_API_URL}
	  OTHER_ENVAR: testtesttest
env: test2
components:
  - name: fooservice-app-params
    provider:
      name: app-params
	  config:
        account: ${aws-account:aws}
        region: us-east-1
    inputs:
      REFERENCED_API_URL: ${test:fooservice-hardcoded-app-params:REFERENCED_API_URL}
	  OTHER_ENVAR: testtesttest

secrets

If the value of the environment variable should be secret, you can use the Secrets provider to store it and then reference it.

These templates should never be added to source control.

env: dev
components:
  - name: foo-secrets
	provider:
      name: secrets
	inputs:
		API_KEY: asdf123
env: dev
components:
  - name: fooservice-app-params
    provider:
      name: app-params
	  config:
        account: ${aws-account:aws}
        region: us-east-1
    inputs:
      API_KEY_FROM_SECRETS: ${dev:foo-secrets:API_KEY}