SLS ACCT#

Each state in an SLS file defaults to using the “default” profile for the associated provider.

Idem determines which profile is appropriate by looking for ACCT on the hub in the root of the state definition. For example, in idem_aws/states/aws/init.py we might see the following code:

def __init__(hub):
    hub.states.aws.ACCT = ["aws"]

The code specifies that all plugins under hub.states.aws should use profiles under the “aws” provider key in the account file.

An account file with AWS credentials might look like this:

aws:
  default:
    id: XXXXXXXXXXXXXXXXX
    key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    region: us-east-1
  other:
    id: XXXXXXXXXXXXXXXXX
    key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    region: us-east-1

A single SLS file can reference multiple AWS credential profiles as shown in the following example:

# No profile is specified, so the "default" AWS profile is used.
ensure_vpc:
  aws.vpc.present:
     - kwarg1: value1

# The "other" AWS profile is specified for use.
ensure_vpc:
  aws.vpc.present:
     - acct_profile: other
     - kwarg1: value1

States from one cloud can depend on states from another cloud. Idem will associate the right profiles with the right plugins and keep the profiles separate in their own contexts.

Consider the following multi-cloud account file:

aws:
  default:
    id: XXXXXXXXXXXXXXXXX
    key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    region: us-east-1
azure:
  default:
    client_id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
    secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    subscription_id: "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
    tenant: "cccccccc-cccc-cccc-cccc-cccccccccccc"

Profiles under the “aws” provider are only sent to plugins that specify the “aws” provider for authenticaton. Profiles under the “azure” provider are only sent to plugins that specify the “azure” provider for authenticaton.

# The "default" "aws" profile is used.
ensure_vpc:
  aws.vpc.present:
     - kwarg1: value1

# The "default" "azure" profile is used.
ensure_vpc:
  azure.vpc.present:
     - kwarg1: value1

In this way, Idem seamlessly integrates multiple requisites and profiles across different clouds, all within a single SLS file.

Aggregate State#

You can dynamically extend account information using the acct.profile state. In the following example, test.present represents data from an arbitrary resource. Its values are passed via arg_bind to an acct.profile state. The third state requires the new_profile state and then makes use of the profile created in that state.

Warning

Use this feature with arg_binding to use information generated in one state as credentials in other states. You can use the feature to create roles and dynamically assume those roles in subsequent states. Do NOT use this feature to bypass encrypting your credentials file. Exercise caution and do not abuse this feature.

mock_acct:
  test.present:
    - new_state:
        key_1: value_1
        key_2: value_2

new_profile:
  acct.profile:
    - provider_name: test
    - key_1: ${test:mock_acct:key_1}
    - key_2: ${test:mock_acct:key_2}

test_result:
  test.acct:
    - acct_profile: new_profile
    - require:
      - acct: new_profile

Note

This can also be done without “require” blocks by using the reconciliation loop.

Single-use Profiles#

In the following code block, acct_data is passed directly into the state. The profiles defined here will be used in place of all the profiles defined for the rest of the RUN. This acct_data is not preserved and only exists in the context of the state that uses it.

mock_acct:
  test.present:
    - new_state:
        key_1: value_1
        key_2: value_2

test_result:
  test.acct:
    - acct_profile: new_profile
    - acct_data:
        profiles:
          test:
            new_profile:
              key_1: ${test:mock_acct:key_1}
              key_2: ${test:mock_acct:key_2}

If arg_binding is not required, account data that isn’t sensitive can be saved in a Jinja variable and explicitly passed to each state that needs it. However, you get better value and security from writing an acct plugin.

{% set acct_data = {"profiles": {"test": {"new_profile": {"key_1": "value_1", "key_2": "value_2"}}}} %}

test_result:
  test.acct:
    - acct_profile: new_profile
    - acct_data: {{acct_data}}

Copy From Existing Profiles#

To copy from an existing profile, specify the “source_profile” key in the acct.profile state. The profile matching the “source_profile” name under the given provider will be used as a base for constructing the new profile.

Consider the following acct_file:

test:
  source:
    key_1: overwritten
    key_3: copied

The following state copies the existing profile under the given provider in the acct_file. “key_1” is defined in both places, so the new profile will overwrite that value. “key_3” is not defined in the new_profile, so it will be copied from the existing profile in the acct_file to the new profile.

new_profile:
  acct.profile:
    - provider_name: test
    - source_profile: source
    - key_1: value_1
    - key_2: value_2

test_result:
  test.acct:
    - acct_profile: new_profile
    - require:
      - acct: new_profile