Sharing a portfolio

What is sharing and how does it work?

Note

This was added in version 0.1.14

This framework allows you to create portfolios in other accounts that mirror the portfolio in your hub account. The framework will create the portfolio for you and either copy or import the products (along with their versions) from your hub account into the newly created portfolio.

In addition to this, you can specify associations for the created portfolio and add launch constraints for the products.

Warning

Once a hub product version has been copied into a spoke portfolio it will not be updated.

How can I set it up?

The following is an example of how to add the portfolio example-simple-central-it-team-portfolio to all spokes tagged scope:spoke:

spoke-local-portfolios:
  account-vending-for-spokes:
    portfolio: example-simple-central-it-team-portfolio
    product_generation_method: copy
    depends_on:
      - account-iam-for-spokes
    associations:
      - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    constraints:
      launch:
        - product: account-vending-account-creation-shared
          roles:
            - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    deploy_to:
      tags:
        - tag: scope:spoke
          regions: default_region

The example above will create the portfolio once the depends_on launches have completed successfully.

The valid values for regions are: - enabled - this will deploy to each enabled region for the account - regions_enabled - this will deploy to each enabled region for the account - default_region - this will deploy to the default region specified for the account - all - this will deploy to all regions enabled in your config (whilst setting up Puppet) - list of AWS regions - you can type in a list of AWS regions (each region selected should be present in your config)

What are the settings for product_generation_method?

Note

Being able to configure this was added in version 0.72.0, previous versions always assume a copy

Using spoke-local-portfolios, a spoke portfolio is always created as a copy of the hub portfolio - that is, it has a different portfolio ID, but the same name and metadata as the hub portfolio. This ensures changes made to the portfolio in the spoke (such as associations and constraints) cannot affect other spokes or the hub portfolio.

There are 2 options for populating products inside the spoke portfolios, Copy or Import.

product_generation_method: copy (the default) means that products and provisioning artifacts are deep-copied into the spoke local portfolio using the Service Catalog CopyProduct API call.
They will get new product and provisioning artifact IDs, but have the same names and metadata as hub products.
This ensures isolation between hub and spoke - changes to products and versions in the hub will only be reflected in the spoke on the next puppet run.
product_generation_method: import setting will import (using the AssociateProductWithPortfolio Service Catalog API call) the product and its provisioning artifacts into the spoke from the hub portfolio with the same IDs as the hub portfolio.
This is useful for occasions where is it necessary to have the same product ID in the spoke as in the hub - for example if changes to provisioning artifacts in the hub need to be instantly reflected in the spoke without requiring a puppet run.

How can I add an association?

The example above will add an association for the IAM principal:

arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole

so the portfolio will be accessible for anyone assuming that role. In addition to roles, you can also specify the ARN of users and groups.

Note

Using ${AWS::AccountId} will evaluate in the spoke account.

How can I add a launch constraint?

The example above will add a launch constraint for the IAM role:

arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole

so they can launch the product account-vending-account-creation-shared in the spoke account.

Warning

You can only specify an IAM role and the role must be assumable by the AWS service principal servicecatalog.amazonaws.com

Note

Using ${AWS::AccountId} will evaluate in the spoke account.

Note

Support for using products was added in version 0.3.0.

You can use products instead of product to specify either a list of products or use a regular expression. The regular expression is matched using Python3 re.match.

Using a list:

spoke-local-portfolios:
  account-vending-for-spokes:
    portfolio: example-simple-central-it-team-portfolio
    depends_on:
      - account-iam-for-spokes
    associations:
      - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    constraints:
      launch:
        - products:
            - account-vending-account-bootstrap-shared
            - account-vending-account-creation-shared
          roles:
            - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    deploy_to:
      tags:
        - tag: scope:spoke
          regions: default_region

Using a regular expression:

spoke-local-portfolios:
  account-vending-for-spokes:
    portfolio: example-simple-central-it-team-portfolio
    depends_on:
      - account-iam-for-spokes
    associations:
      - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    constraints:
      launch:
        - products: "account-vending-account-*"
          roles:
            - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    deploy_to:
      tags:
        - tag: scope:spoke
          regions: default_region

How can I unshare a portfolio?

You can set the status on a spoke-local-portfolio. When you set it to terminated the spoke-local-portfolio is ‘terminated’.

If the account hosting the spoke-local-portfolio is not the puppet account it will have the associations and constraints removed, the local portfolio will be deleted and the share with the puppet account will be deleted.

If the account hosting the spoke-local-portfolio is the puppet account it will delete the associations and the constraints but will leave the portfolio in place and will have no share to delete.

spoke-local-portfolios:
  account-vending-for-spokes:
    portfolio: example-simple-central-it-team-portfolio
    status: terminated
    depends_on:
      - account-iam-for-spokes
    associations:
      - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    constraints:
      launch:
        - products: "account-vending-account-*"
          roles:
            - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    deploy_to:
      tags:
        - tag: scope:spoke
          regions: default_region

Note

This was added in version 0.73.0

Sharing mode

Note

This was added in version 0.88.0

When you write a spoke-local-portfolio, the framework will share the portfolio used with each spoke account you are deploying into. The framework shares with each account and accepts the share within each account. You can tell the framework to share with an OU (using Organizational sharing) instead and then accept the share from within each account still. This reduces the time taken to share portfolios but means all accounts in the same OU will have the portfolio shared with them - those account will not have the portfolio share accepted. To enable this behaviour you need to set the sharing_mode:

spoke-local-portfolios:
  account-vending-for-spokes:
    portfolio: example-simple-central-it-team-portfolio
    sharing_mode: AWS_ORGANIZATIONS
    depends_on:
      - account-iam-for-spokes
    associations:
      - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    constraints:
      launch:
        - products: "account-vending-account-*"
          roles:
            - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    deploy_to:
      tags:
        - tag: scope:spoke
          regions: default_region

To revert back you can set sharing_mode back to ACCOUNT:

spoke-local-portfolios:
  account-vending-for-spokes:
    portfolio: example-simple-central-it-team-portfolio
    sharing_mode: ACCOUNT
    depends_on:
      - account-iam-for-spokes
    associations:
      - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    constraints:
      launch:
        - products: "account-vending-account-*"
          roles:
            - arn:aws:iam::${AWS::AccountId}:role/MyServiceCatalogAdminRole
    deploy_to:
      tags:
        - tag: scope:spoke
          regions: default_region

If you are using this feature you must be able to share using Organizations in your puppet account. To do this you must have installed puppet into your AWS Organizations management account or you must have delegated your puppet account as an AWS Service Catalog organizations master account.

The default value for sharing_mode is ACCOUNT unless you change it using the following command:

servicecatalog-puppet set-named-config-value global_sharing_mode_default AWS_ORGANIZATIONS

Alternatively, you can also add the following to your config:

global_sharing_mode_default: AWS_ORGANIZATIONS

When you change the global_sharing_mode_default it affects launches and spoke-local-portfolios.

Is there anything else I should know?

  1. It would be good to become familar with the AWS Service Catalog pricing before using this feature.