Single spokes

What are we going to do?

You will need to bootstrap spoke accounts so you can share portfolios with them and provision products into them.

Bootstrapping a spoke account will create an AWS CloudFormation stack in it. This stack will contain the Puppet IAM Role (PuppetRole) which is needed by framework to perform actions in the spoke account.

Using the CLI

The following steps should be executed using the Service Catalog Puppet CLI which is an application built using Python 3.7.

If you have not already installed the framework you can do so by following these steps:

Create an isolated Python environment

It is good practice to install Python libraries in isolated environments.

You can create the a virtual environment using the following command:

virtualenv --python=python3.7 venv
source venv/bin/activate

Install the package locally

Once you have decided where to install the library you can install the package:

pip install aws-service-catalog-puppet

This will install the library and all of the dependencies.

Restricting spokes

The PuppetRole created by the framework has the AdministratorAccess IAM managed policy attached to it. It is reccommended that you can define an IAM Permission Boundary for the PuppetRole for any production applications of this framework.

The IAM Permission Boundary you provide should permit the PuppetRole to interact with AWS Service Catalog to accept shares, manage portfolios and to add, provision and terminate products. In addition the IAM Role should allow the use of AWS SNS, AWS EventBridge, AWS OpsCenter if you are making use of those features.

In order to use an IAM Permission Boundary you will need to append the following to your commands:

--permission-boundary arn:aws:iam::aws:policy/AdministratorAccess

There will be an example of this for each command in these how tos.

Bootstrapping a spoke

You should export the credentials for the spoke account or set your profile so that AWS CLI commands will execute as a role in the spoke account.

Then you can run the following command:

Without a permission boundary

servicecatalog-puppet bootstrap-spoke <ACCOUNT_ID_OF_YOUR_PUPPET>

With a permission boundary

servicecatalog-puppet bootstrap-spoke <ACCOUNT_ID_OF_YOUR_PUPPET> --permission-boundary arn:aws:iam::aws:policy/AdministratorAccess

Ensure you replace <ACCOUNT_ID_OF_YOUR_PUPPET> with the AWS Account id of the AWS Account you will be using as your puppet account.

Bootstrapping a spoke as

If you want to assume a role into the spoke from your currently active role you can use the following command.

Without a boundary

servicecatalog-puppet bootstrap-spoke-as <ACCOUNT_ID_OF_YOUR_PUPPET> <ARN_OF_ASSUMABLE_ROLE_IN_SPOKE>

With a boundary

servicecatalog-puppet bootstrap-spoke-as <ACCOUNT_ID_OF_YOUR_PUPPET> <ARN_OF_ASSUMABLE_ROLE_IN_SPOKE> --permission-boundary arn:aws:iam::aws:policy/AdministratorAccess

This will assume the role <ARN_OF_ASSUMABLE_ROLE_IN_SPOKE> before running boostrap-spoke. This is useful if you do not want to perform the AWS STS assume-role yourself.

Ensure you replace <ACCOUNT_ID_OF_YOUR_PUPPET> with the account id of the account you will be using as your puppet account.

You can use the following AWS CloudFormation template to provision the needed role:

# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

AWSTemplateFormatVersion: '2010-09-09'
Description: IAM Role needed to use AWS Organizations to assume role into member AWS Accounts.

Parameters:
  ServiceCatalogFactoryAccountId:
    Description: The account you will be installing AWS Service Catalog Factory into
    Type: String

  OrganizationAccountAccessRole:
    Description: Name of the IAM role used to access cross accounts for AWS Orgs usage
    Default: OrganizationAccountAccessRole
    Type: String

Resources:
  RoleForBootstrappingSpokes:
    Type: AWS::IAM::Role
    Description: |
      IAM Role needed by the account vending machine so it can create and move accounts
    Properties:
      Path: /servicecatalog-puppet/
      Policies:
        - PolicyName: Organizations
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - sts:AssumeRole
                Resource: !Sub "arn:aws:iam::*:role/${OrganizationAccountAccessRole}"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              AWS: !Sub "arn:aws:iam::${ServiceCatalogFactoryAccountId}:root"
            Action:
              - "sts:AssumeRole"

Outputs:
  RoleForBootstrappingSpokesArn:
    Description: The ARN for your Assumable role in root account
    Value: !GetAtt RoleForBootstrappingSpokes.Arn