Skip to content

BUG | AWS profile name is re-derived from the SSO permission set, breaking any account whose permission set is renamed #326

Description

@exequielrafaela

Summary

leverage reconstructs the AWS profile name it writes credentials into, instead of using the profile reference it already resolved. The reconstruction is f"{project}-{account_name}-{sso_role.lower()}", which silently produces the wrong name whenever an SSO permission set is not named after the profile's suffix — and the same helper mis-parses stale <project>-sso-* sections into junk profiles.

Found on 3.1.0 while adopting the new aws sso refresh (#315). The refresh command itself works well; these are pre-existing derivation bugs that the new command makes visible (and, for bug 2, amplifies).

Bug 1 — the profile name is coupled to the permission set name

get_layer_profile (leverage/modules/auth.py) resolves a .tf profile reference into raw, then throws raw away and rebuilds the name from account + role:

layer_profile = tf_profile if raw_profile in ("var.profile", "each.value.profile") else None
...
layer_profile = layer_profile or f"{project}-{account_name}-{sso_role.lower()}"

raw is the profile name the .tf will use. Rebuilding it assumes the permission set is named after the profile suffix.

We renamed one account's permission set from DevOps to DevOpsPrd (production gating). Nothing else changed. Immediately:

$ leverage tofu init          # from an apps-prd layer
INFO   Attempting to get temporary credentials for apps-prd account.
INFO   Using already configured temporary credentials.      # it checked bb-apps-prd-devopsprd
Error: validating provider credentials: ... ExpiredToken    # tofu used bb-apps-prd-devops

backend.tfvars says profile = "bb-apps-prd-devops", so that is the profile tofu authenticates with — but leverage can only ever mint bb-apps-prd-devopsprd. The account becomes unusable and there is no way to get the right profile out of the CLI. Cross-account references written as literals (profile = "${var.project}-apps-prd-devops") hit the same wall.

Suggested fix: use the resolved reference. layer_profile should just be raw in _get_sso_profile; the account+role derivation is only needed by refresh_all_accounts_credentials, where there is no .tf reference to resolve.

Related: the tf_profile short-circuit is dead code

key_finder returns the raw HCL string, which for profile = var.profile is "${var.profile}" — never equal to the bare "var.profile" the ternary compares against:

>>> from leverage._utils import key_finder, parse_tf_file
>>> key_finder(parse_tf_file(Path("apps-prd/us-east-1/security-base/config.tf")), "profile", "lookup")
['${var.profile}']

So the tf_profile branch never fires and the derivation always wins, even for the layer's own profile. Same for each.value.profile.

Bug 2 — stale <project>-sso-* sections become junk profiles

_get_sso_profile_from_section treats everything after the prefix as the account name:

account_name = profile_section.replace(f"profile {project}-sso-", "")
layer_profile = f"{project}-{account_name}-{sso_role.lower()}"

Older leverage versions wrote sections named <project>-sso-<account>-<Role>, and configure_sso_profiles never removes them. Our config still had six. aws sso refresh read bb-sso-network-DevOps as account "network-DevOps" and wrote a profile literally named bb-network-DevOps-devops:

INFO   Found 16 account(s) to refresh.        # 10 real accounts + 6 stale sections
INFO   Writing bb-network-DevOps-devops profile
INFO   Writing bb-shared-DevOps-devops profile
INFO   Writing bb-root-Administrator-administrator profile
...
INFO   Credential refresh complete: 11 refreshed, 3 skipped, 2 failed.

Five junk profiles written into ~/.aws/<project>/{config,credentials}, five wasted get-role-credentials calls, and inflated counts in the summary. After deleting the stale sections by hand: Found 10 account(s) → 10 refreshed, 0 skipped, 0 failed.

Validating the suffix against the known account list (or having configure_sso_profiles prune sections it did not just write) would avoid this.

Bug 3 — refresh help is not accepted

The PR description for #315 documents both syntaxes. Only --help works:

$ leverage aws sso refresh help
Error: Got unexpected extra argument (help)

Also, leverage aws sso --help and bare leverage aws sso fall through to the real aws CLI, so there is no way to discover refresh from the SSO subcommand's own help.

Credit where due

The error handling in #315 is a genuine improvement — raise_on_permission_error=False plus the success/failure summary is what surfaced bug 1 at all. The layer-scoped refresh_layer_credentials still hard-exits on the first account whose permission set you lack, writing nothing; that path would benefit from the same treatment.

Environment

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions