Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Resolve #1283] Deprecating iam_role, role_arn, and template_path; Introducing sceptre_role, cloudformation_service_role #1295

Merged
merged 17 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/_source/docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,14 @@ How do I call AWS services or use AWS-based tools in my custom hook/resolver/tem
In order to call AWS services in your custom hook/resolver/template handler properly, you should use
the IAM configurations of the stack where the resolver is being used (unless you need to use a
different configuration for a specific reason). This means your hook/resolver/handler should honor the
``profile``, ``region``, and ``iam_role`` configurations as set for your project and/or Stack Config.
``profile``, ``region``, and ``sceptre_role`` configurations as set for your project and/or Stack Config.
Simply invoking ``boto3.client('s3')`` is _not_ going to regard those and could end up using the
wrong credentials or not even working.

There is a simple interface available for doing this properly, the
:py:class:`sceptre.connection_manager.ConnectionManager`. The ConnectionManager is an interface that
will be pre-configured with each stack's profile, region, and iam_role and will be ready for you to use.
If you are using an `iam_role`, it will automatically assume that role via STS for making calls to
will be pre-configured with each stack's profile, region, and sceptre_role and will be ready for you to use.
If you are using an ``sceptre_role``, it will automatically assume that role via STS for making calls to
AWS so you can just use it the way you want. It is accessible on hooks and resolvers via
``self.stack.connection_manager`` and on template_handlers via ``self.connection_manager``.

Expand Down
36 changes: 18 additions & 18 deletions docs/_source/docs/permissions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ Permissions Configurations
--------------------------

There are three main configurations for Sceptre that can modify default permissions behavior to
provide more flexibility, control, and safety within an organization: **role_arn**, **iam_role**, and
**profile**. These can be applied in a very targeted way, on a stack by stack basis or can be applied
broadly to a whole StackGroup.
provide more flexibility, control, and safety within an organization: **cloudformation_service_role**,
**sceptre_role**, and **profile**. These can be applied in a very targeted way, on a stack by stack
basis or can be applied broadly to a whole StackGroup.

.. _role_arn_permissions:
.. _cloudformation_service_role_permissions:

role_arn
^^^^^^^^
cloudformation_service_role
^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is the **CloudFormation service role** that will be attached to a given CloudFormation stack.
This IAM role needs to be able to be assumed by **CloudFormation**, and must provide all the
necessary permissions for all create/read/update/delete operations for all resources defined in that
Expand All @@ -53,14 +53,14 @@ the use case.
For more information on using CloudFormation service roles, see the `AWS documentation <https://docs.aws
.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-servicerole.html>`_.

As a resolvable property, Sceptre allows you to use a resolver to populate the ``role_arn`` for a
As a resolvable property, Sceptre allows you to use a resolver to populate the ``cloudformation_service_role`` for a
Stack or StackGroup Config. This means you could define that role within your project, output its
ARN, and then reference it using `!stack_output`.

.. _iam_role_permissions:
.. _sceptre_role_permissions:

iam_role
^^^^^^^^
sceptre_role
^^^^^^^^^^^^

This is a **role that Sceptre will assume** when taking any actions on the Stack. It is not a service
role for CloudFormation. Instead, this is simply a role that the current user assumes to execute
Expand All @@ -69,20 +69,20 @@ any Sceptre actions on that stack. This has some benefits over a CloudFormation
* This is not permanently attached to the Stack after you've used it once. If you ever *don't* want
to assume this role, you could comment it out or remove it from the Stack Config and Sceptre simply
won't use it. This is useful if the user executing Sceptre already has the right permissions to
take those actions. In other words, it doesn't lock you in (unlike using ``role_arn``).
take those actions. In other words, it doesn't lock you in (unlike using ``cloudformation_service_role``).
* CloudFormation can continue to use it's default behavior of executing Stack actions with the
permissions of the current user, but it interprets the current user to hold the indicated ``iam_role``,
permissions of the current user, but it interprets the current user to hold the indicated ``sceptre_role``,
which could grant additional permissions.

Using the ``iam_role`` configuration on a Stack or StackGroup Config allows the user to *temporarily*
Using the ``sceptre_role`` configuration on a Stack or StackGroup Config allows the user to *temporarily*
"step into" a different set of permissions in order to execute Sceptre actions on Stack(s) in the
project without having to permanently hold those permissions.

In order to use an ``iam_role`` on a Sceptre Stack Config, that role needs to have an
In order to use an ``sceptre_role`` on a Sceptre Stack Config, that role needs to have an
AssumeRolePolicyDocument that allows the current user to assume it and permissions to perform all
deployment actions on the stack and all its resources.

As a resolvable property, Sceptre allows you to use a resolver to populate the ``iam_role`` for a
As a resolvable property, Sceptre allows you to use a resolver to populate the ``sceptre_role`` for a
Stack or StackGroup Config. This means you could define that role within your project, output its
ARN, and then reference it using `!stack_output`.

Expand All @@ -91,7 +91,7 @@ ARN, and then reference it using `!stack_output`.
profile
^^^^^^^

This is different from ``role_arn`` and ``iam_role``, as both of those cause CloudFormation or
This is different from ``cloudformation_service_role`` and ``sceptre_role``, as both of those cause CloudFormation or
Sceptre to *assume* a different role with different permissions than the permissions the current
user has.

Expand All @@ -107,7 +107,7 @@ Tips for working with Sceptre, IAM, and a CI/CD system

* Rather than giving your CI/CD system blanket, admin-level permissions, you can define an IAM role
with Sceptre to use for deploying the rest of your infrastructure, outputing its ARN in the template.
Then, in the rest of your project's stacks, you can set the ``iam_role`` using ``!stack_output``
Then, in the rest of your project's stacks, you can set the ``sceptre_role`` using ``!stack_output``
to get that role's arn. This will mean your CI/CD system will temporarily "step into" that role
when using Sceptre to interact with those specific stacks. It will also establish a dependency on
your deployment role stack with every other stack in your project.
Expand All @@ -131,7 +131,7 @@ Tips for working with Sceptre, IAM, and a CI/CD system
condition applied.

* If you define your deployment role (and any other related resources) using Sceptre and then
reference it on all *other* stacks using ``iam_role: !stack_output ...``, this means that your
reference it on all *other* stacks using ``sceptre_role: !stack_output ...``, this means that your
CI/CD system will not be able to deploy changes to the deployment role or its resources, but that
every deployment will depend on those. This is good! It means that, so long as those resources
remain unchanged, automated deployment can proceed without issue. It also means that the scope of
Expand Down
8 changes: 4 additions & 4 deletions docs/_source/docs/resolvers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ nested values in dicts and lists using "." to separate key/index segments. For e
- "some random value"
- "the value we want to select"

iam_role: !stack_output roles.yaml::RoleArn
sceptre_role: !stack_output roles.yaml::RoleArn

parameters:
# This will pass the value of "the value we want to select" for my_parameter
my_parameter: !stack_attr sceptre_user_data.key.1
# You can also access the value of another resolvable property like this:
use_role_arn: !stack_attr iam_role
use_role: !stack_attr sceptre_role


stack_output
Expand Down Expand Up @@ -325,7 +325,7 @@ Resolver arguments can be a simple string or a complex data structure.
Resolving to nothing
^^^^^^^^^^^^^^^^^^^^
When a resolver returns ``None``, this means that it resolves to "nothing". For resolvers set for
single values (such as for ``template_bucket_name`` or ``role_arn``), this just means the value is
single values (such as for ``template_bucket_name`` or ``cloudformation_service_role``), this just means the value is
``None`` and treated like those values aren't actually set. But for resolvers inside of containers
like lists or dicts, when they resolve to "nothing", that item gets completely removed from their
containing list or dict.
Expand Down Expand Up @@ -365,7 +365,7 @@ A few examples...
"pretty" as the sort of placeholder used for stack parameters, but the use of sceptre_user_data is
broader, so it placeholder values can only be alphanumeric to reduce chances of it breaking the
template.
* Resolvable properties that are *always* used when performing template operations (like ``iam_role``
* Resolvable properties that are *always* used when performing template operations (like ``sceptre_role``
and ``template_bucket_name``) will resolve to ``None`` and not be used for those operations if they
cannot be resolved.

Expand Down
59 changes: 45 additions & 14 deletions docs/_source/docs/stack_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ particular Stack. The available keys are listed below.
- `parameters`_ *(optional)*
- `protected`_ *(optional)*
- `role_arn`_ *(optional)*
- `cloudformation_service_role`_ *(optional)*
- `iam_role`_ *(optional)*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it make sense to mark these as deprecated here as well? something like [Deprecated] iam_role_ *(optional)*

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about that... that's easy enough to do.

- `sceptre_role`_ (*optional)*
- `iam_role_session_duration`_ *(optional)*
- `sceptre_role_session_duration`_ *(optional)*
- `sceptre_user_data`_ *(optional)*
- `stack_name`_ *(optional)*
- `stack_tags`_ *(optional)*
Expand All @@ -47,7 +50,7 @@ from the Stack config filename.

.. warning::

This key is deprecated in favor of the `template`_ key.
This key is deprecated in favor of the `template`_ key. It will be removed in version 5.0.0.

template
~~~~~~~~
Expand Down Expand Up @@ -312,49 +315,77 @@ role_arn
* Can be inherited from StackGroup: Yes
* Inheritance strategy: Overrides parent if set

.. warning::
This field is deprecated as of v4.0.0 and will be removed in v5.0.0. It has been renamed to
`cloudformation_service_role`_ as a clearer name for its purpose.

cloudformation_service_role
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Resolvable: Yes
* Can be inherited from StackGroup: Yes
* Inheritance strategy: Overrides parent if set

The ARN of a `CloudFormation Service Role`_ that is assumed by *CloudFormation* (not Sceptre)
to create, update or delete resources. For more information on this configuration, its implications,
and its uses see :ref:`Sceptre and IAM: role_arn <role_arn_permissions>`.
and its uses see :ref:`Sceptre and IAM: cloudformation_service_role <cloudformation_service_role_permissions>`.

iam_role
~~~~~~~~
* Resolvable: Yes
* Can be inherited from StackGroup: Yes
* Inheritance strategy: Overrides parent if set

.. warning::
This field is deprecated as of v4.0.0 and will be removed in v5.0.0. It has been renamed to
`sceptre_role`_ as a clearer name for its purpose.

sceptre_role
~~~~~~~~~~~~
* Resolvable: Yes
* Can be inherited from StackGroup: Yes
* Inheritance strategy: Overrides parent if set

This is the IAM Role ARN that **Sceptre** should *assume* using AWS STS when executing any actions
on the Stack.

This is different from the ``role_arn`` option, which sets a CloudFormation service role for the
stack. The ``iam_role`` configuration does not configure anything on the stack itself.
This is different from the ``cloudformation_service_role`` option, which sets a CloudFormation
service role for the stack. The ``sceptre_role`` configuration does not configure anything on the
stack itself.

.. warning::

If you set the value of ``iam_role`` with ``!stack_output``, that ``iam_role``
If you set the value of ``sceptre_role`` with ``!stack_output``, that ``sceptre_role``
will not actually be used to obtain the stack_output, but it *WILL* be used for all subsequent stack
actions. Therefore, it is important that the user executing the stack action have permissions to get
stack outputs for the stack outputting the ``iam_role``.
stack outputs for the stack outputting the ``sceptre_role``.

For more information on this configuration, its implications, and its uses, see
:ref:`Sceptre and IAM: iam_role <iam_role_permissions>`.
:ref:`Sceptre and IAM: sceptre_role <sceptre_role_permissions>`.

iam_role_session_duration
~~~~~~~~~~~~~~~~~~~~~~~~~
* Resolvable: No
* Can be inherited from StackGroup: Yes
* Inheritance strategy: Overrides parent if set

This is the session duration when **Sceptre** *assumes* the **iam_role** IAM Role using AWS STS when
.. warning::
This field is deprecated as of v4.0.0 and will be removed in v5.0.0. It has been renamed to
`sceptre_role_session_duration`_ as a clearer name for its purpose.

sceptre_role_session_duration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Resolvable: No
* Can be inherited from StackGroup: Yes
* Inheritance strategy: Overrides parent if set

This is the session duration when **Sceptre** *assumes* the **sceptre_role** IAM Role using AWS STS when
executing any actions on the Stack.

.. warning::

If you set the value of ``iam_role_session_duration`` to a number that *GREATER* than 3600, you
will need to make sure that the ``iam_role`` has a configuration of ``MaxSessionDuration``, and
its value is *GREATER* than or equal to the value of ``iam_role_session_duration``.

For more information on this configuration, its implications, and its uses, see
:ref:`Sceptre and IAM: iam_role_session_duration <iam_role_permissions>`.
If you set the value of ``sceptre_role_session_duration`` to a number that *GREATER* than 3600, you
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a vestigial "that" here. I think this is supposed to read: "to a number GREATER than"

will need to make sure that the ``sceptre_role`` has a configuration of ``MaxSessionDuration``, and
its value is *GREATER* than or equal to the value of ``sceptre_role_session_duration``.

sceptre_user_data
~~~~~~~~~~~~~~~~~
Expand Down
6 changes: 3 additions & 3 deletions docs/_source/docs/stack_group_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,8 @@ and concerns of the project. These include:
* The S3 bucket where templates are uploaded to and then referenced from for stack actions (i.e. the
``template_bucket_name`` config key).
* The CloudFormation service role added to the stack(s) that CloudFormation uses to execute stack
actions (i.e. the ``role_arn`` config key).
* The role that Sceptre will assume to execute stack actions (i.e. the ``iam_role`` config key).
actions (i.e. the ``cloudformation_service_role`` config key).
* The role that Sceptre will assume to execute stack actions (i.e. the ``sceptre_role`` config key).
* SNS topics that cloudformation will notify with the results of stack actions (i.e. the
``notifications`` config key).

Expand All @@ -212,7 +212,7 @@ dependencies.
.. warning::

You might have already considered that this might cause a circular dependency for those
dependency stacks, the ones that output the template bucket name, role arn, iam_role, or topic arns.
dependency stacks, the ones that output the template bucket name, role arn, sceptre_role, or topic arns.
In order to avoid the circular dependency issue, you can either:

1. Set the value of those configurations to ``!no_value`` in the actual stacks that define those
Expand Down
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/1/A.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
stack_timeout: 1
template_path: malformed_template.json
template:
path: malformed_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/10/A.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: sam_template.yaml
template:
path: sam_template.yaml
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/11/A.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: sam_updated_template.yaml
template:
path: sam_updated_template.yaml
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/12/1/2/3/C.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
template_path: valid_template.json
template:
path: valid_template.json
stack_tags:
Project: '{{ project }}'
Key: '{{ keyC }}'
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/12/1/2/B.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
template_path: valid_template.json
template:
path: valid_template.json
stack_tags:
Project: '{{ project }}'
Key: '{{ keyB }}'
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/12/1/A.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
template_path: valid_template.json
template:
path: valid_template.json
stack_tags:
Key: '{{ keyA }}'
Project: '{{ project }}'
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/2/A.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: updated_template.json
template:
path: updated_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/2/B.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: updated_template.json
template:
path: updated_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/2/C.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: updated_template.json
template:
path: updated_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/3/A.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/3/B.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dependencies:
- 3/A.yaml
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/3/C.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dependencies:
- 3/B.yaml
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/4/A.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/4/B.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/4/C.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
template_path: valid_template.json
template:
path: valid_template.json
dependencies:
- 3/A.yaml
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/5/1/A.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/5/1/B.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/5/1/C.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/5/2/A.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/5/2/B.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/5/2/C.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: valid_template.json
template:
path: valid_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/6/1/A.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
template_path: dependencies/independent_template.json
template:
path: dependencies/independent_template.json
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/6/1/B.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
template_path: dependencies/dependent_template.json
template:
path: dependencies/dependent_template.json
parameters:
DependentStackName: !stack_output 6/1/A.yaml::StackName
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/6/1/C.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
template_path: dependencies/dependent_template.json
template:
path: dependencies/dependent_template.json
parameters:
DependentStackName: !stack_output 6/1/B.yaml::StackName
3 changes: 2 additions & 1 deletion integration-tests/sceptre-project/config/6/2/A.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
template_path: dependencies/independent_template.json
template:
path: dependencies/independent_template.json
region: eu-west-1
Loading