Skip to content

Commit

Permalink
Specify AWS region for IC sessions
Browse files Browse the repository at this point in the history
There are two use cases for an IC session from a region perspective:
1. AWS Identity Center could be deployed in a region different to the
   one the actual project resources;
2. The project could use several regions.

The `--aws-region` fully covers the first use case and partially covers
the second one since a user can set one region. The multiple regions
could be supported by duplicating aliases with corresponding region
configurations or adding some selection login in the alias function.
  • Loading branch information
extsoft committed Jun 27, 2024
1 parent 907121a commit fedf034
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 22 deletions.
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ to unset the environment variables.

After the successful authentication, the following AWS-related environment variables are set:
- `AWS_ACCESS_KEY_ID`
- `AWS_DEFAULT_REGION`
- `AWS_SECRET_ACCESS_KEY`
- `AWS_SESSION_TOKEN`
- `AWS_REGION`

Please visit [this AWS page](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html#envvars-list) for details.

Expand Down Expand Up @@ -109,19 +109,21 @@ options:
```shell
~ aws-creds session-ic --help
usage: aws-creds session-ic [-h] --ic-start-url URL --ic-region region --account-id id --role-name
name [--no-prompt-update]
name [--aws-region region] [--no-prompt-update]
The command exports the environment variables suitable for authenticating CLI tools by creating an
AWS login session based on the AWS IAM Identity Center role. Any AWS IAM Identity Center alias will
use this command to authenticate.
options:
-h, --help show this help message and exit
--ic-start-url URL AWS IAM Identity Center start URL (like `https://xxxxxx.awsapps.com/start`)
--ic-region region AWS IAM Identity Center region (like `us-east-1`)
--account-id id AWS Account ID
--role-name name Role name
--no-prompt-update Disables a shell prompt modification if specified
-h, --help show this help message and exit
--ic-start-url URL AWS IAM Identity Center start URL (like `https://xxxxxx.awsapps.com/start`)
--ic-region region AWS IAM Identity Center region (like `us-east-1`)
--account-id id AWS Account ID
--role-name name Role name
--aws-region region An AWS region where the AWS resources are located ('--ic-region' value is
used if unset).
--no-prompt-update Disables a shell prompt modification if specified
```
### `aws-creds session-access-key`
Expand Down
42 changes: 28 additions & 14 deletions aws-creds.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import sys
from typing import Dict, Optional, Literal, TextIO

__version__ = "0.7.1"
__version__ = "0.7.1+20240627-143439"
_prog = Path(__file__).name.split(".")[0]
_dependencies_home = Path.home().joinpath(".cache").joinpath(_prog)
_clear_session_function_name = f"{_prog}-clear-session"
Expand Down Expand Up @@ -193,6 +193,7 @@ def _print_identity_center_alias(
+ f" --ic-start-url {ic.ic_start_url} \\\n"
+ f" --ic-region {ic.ic_region} \\\n"
+ f" --account-id {account_id} \\\n"
+ f" --aws-region {ic.ic_region} \\\n"
+ f" --role-name {role_name}\n"
+ ' )"\n'
+ "}"
Expand All @@ -219,7 +220,7 @@ def _print_session_commands_footer():
print(f"2. Run `{_clear_session_function_name}` resets current CLI credentials.", file=sys.stderr)


def _session_ic(ic: IdentityCenter, account_id: str, role: str, prompt: ShellPrompt) -> None:
def _session_ic(ic: IdentityCenter, account_id: str, role: str, aws_region: str, prompt: ShellPrompt) -> None:
sso = Session().create_client("sso", region_name=ic.ic_region)
token = _token(ic)
role_creds = sso.get_role_credentials(roleName=role, accountId=account_id, accessToken=token)["roleCredentials"]
Expand All @@ -234,12 +235,12 @@ def _session_ic(ic: IdentityCenter, account_id: str, role: str, prompt: ShellPro
print(f'export AWS_CREDS_ACCOUNT_NAME="{account_name}"', file=sys.stdout)
print(f'export AWS_CREDS_ACCOUNT_ID="{account_id}"', file=sys.stdout)
print(f'export AWS_CREDS_ROLE_NAME="{role}"', file=sys.stdout)
print(f'export AWS_DEFAULT_REGION="{ic.ic_region}"', file=sys.stdout)
print(f'export AWS_REGION="{aws_region}"', file=sys.stdout)
print(f'export AWS_ACCESS_KEY_ID="{role_creds["accessKeyId"]}"', file=sys.stdout)
print(f'export AWS_SECRET_ACCESS_KEY="{role_creds["secretAccessKey"]}"', file=sys.stdout)
print(f'export AWS_SESSION_TOKEN="{role_creds["sessionToken"]}"', file=sys.stdout)
print("AWS environment variables are exported!\n", file=sys.stderr)
_print_ic_information(account_name, account_id, role)
_print_ic_information(account_name, account_id, role, aws_region)
print(
_clear_session_function(
"AWS_CREDS_ORIGIN_PS1",
Expand All @@ -248,7 +249,7 @@ def _session_ic(ic: IdentityCenter, account_id: str, role: str, prompt: ShellPro
"AWS_CREDS_ACCOUNT_NAME",
"AWS_CREDS_ACCOUNT_ID",
"AWS_CREDS_ROLE_NAME",
"AWS_DEFAULT_REGION",
"AWS_REGION",
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
"AWS_SESSION_TOKEN",
Expand All @@ -258,10 +259,11 @@ def _session_ic(ic: IdentityCenter, account_id: str, role: str, prompt: ShellPro
_print_session_commands_footer()


def _print_ic_information(account_name: str, account_id: str, role_name: str) -> None:
def _print_ic_information(account_name: str, account_id: str, role_name: str, aws_region: str) -> None:
print("Auth type: AWS IAM Identity Center", file=sys.stderr)
print(f"Account : {account_name} ({account_id})", file=sys.stderr) # noqa: E999
print("Used role: ", role_name, file=sys.stderr)
print("Region : ", aws_region, file=sys.stderr)


def _access_key(name: str, access_key: str, secret_key: str, region: str, printer: Printer) -> None:
Expand Down Expand Up @@ -365,7 +367,7 @@ def perform(self, mfa_device: Optional[str], mfa_code: Optional[str]) -> None:
print(f'export AWS_ACCESS_KEY_ID="{temp_credentials["AccessKeyId"]}"', file=sys.stdout)
print(f'export AWS_SECRET_ACCESS_KEY="{temp_credentials["SecretAccessKey"]}"', file=sys.stdout)
print(f'export AWS_SESSION_TOKEN="{temp_credentials["SessionToken"]}"', file=sys.stdout)
print(f'export AWS_DEFAULT_REGION="{self._region}"', file=sys.stdout)
print(f'export AWS_REGION="{self._region}"', file=sys.stdout)
print("AWS environment variables are exported!\n", file=sys.stderr)
_print_assume_role(self._session_name, self._user_name, self._account_id, self._region, self._role_arn)
print(
Expand All @@ -380,7 +382,7 @@ def perform(self, mfa_device: Optional[str], mfa_code: Optional[str]) -> None:
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
"AWS_SESSION_TOKEN",
"AWS_DEFAULT_REGION",
"AWS_REGION",
),
file=sys.stdout,
)
Expand Down Expand Up @@ -420,7 +422,7 @@ def perform(self, mfa_device: Optional[str], mfa_code: Optional[str]) -> None:
print(f'export AWS_ACCESS_KEY_ID="{temp_credentials["AccessKeyId"]}"', file=sys.stdout)
print(f'export AWS_SECRET_ACCESS_KEY="{temp_credentials["SecretAccessKey"]}"', file=sys.stdout)
print(f'export AWS_SESSION_TOKEN="{temp_credentials["SessionToken"]}"', file=sys.stdout)
print(f'export AWS_DEFAULT_REGION="{self._region}"', file=sys.stdout)
print(f'export AWS_REGION="{self._region}"', file=sys.stdout)
print("AWS environment variables are exported!\n", file=sys.stderr)
_print_access_key(self._session_name, self._user_name, self._account_id, self._region)
print(
Expand All @@ -434,7 +436,7 @@ def perform(self, mfa_device: Optional[str], mfa_code: Optional[str]) -> None:
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
"AWS_SESSION_TOKEN",
"AWS_DEFAULT_REGION",
"AWS_REGION",
),
file=sys.stdout,
)
Expand Down Expand Up @@ -487,21 +489,24 @@ def _describe_credentials() -> None:
session_type = os.getenv("AWS_CREDS_SESSION_TYPE", "")
if session_type == "ic":
_print_ic_information(
os.getenv("AWS_CREDS_ACCOUNT_NAME"), os.getenv("AWS_CREDS_ACCOUNT_ID"), os.getenv("AWS_CREDS_ROLE_NAME")
os.getenv("AWS_CREDS_ACCOUNT_NAME"),
os.getenv("AWS_CREDS_ACCOUNT_ID"),
os.getenv("AWS_CREDS_ROLE_NAME"),
os.getenv("AWS_REGION"),
)
elif session_type == "ak":
_print_access_key(
os.getenv("AWS_CREDS_SESSION_NAME"),
os.getenv("AWS_CREDS_USER_NAME"),
os.getenv("AWS_CREDS_ACCOUNT_ID"),
os.getenv("AWS_DEFAULT_REGION"),
os.getenv("AWS_REGION"),
)
elif session_type == "ar":
_print_assume_role(
os.getenv("AWS_CREDS_SESSION_NAME"),
os.getenv("AWS_CREDS_USER_NAME"),
os.getenv("AWS_CREDS_ACCOUNT_ID"),
os.getenv("AWS_DEFAULT_REGION"),
os.getenv("AWS_REGION"),
os.getenv("AWS_CREDS_SESSION_ROLE"),
)
else:
Expand Down Expand Up @@ -559,7 +564,7 @@ def main():
)
print("\n\n", file=sys.stderr) # noqa: F821
_clear_session()
_session_ic(identity_center, sys.argv[4], sys.argv[5], ShellPrompt(enabled=False))
_session_ic(identity_center, sys.argv[4], sys.argv[5], sys.argv[3], ShellPrompt(enabled=False))
exit(0)
parser = ArgumentParser(
description="Painless CLI authentication using various AWS identities.",
Expand Down Expand Up @@ -631,6 +636,12 @@ def main():
)
session_ic.add_argument("--account-id", metavar="id", required=True, help="AWS Account ID")
session_ic.add_argument("--role-name", metavar="name", required=True, help="Role name")
session_ic.add_argument(
"--aws-region",
metavar="region",
default=None,
help="An AWS region where the AWS resources are located ('--ic-region' value is used if unset).",
)
session_ic.add_argument(
"--no-prompt-update", action="store_true", help="Disables a shell prompt modification if specified"
)
Expand Down Expand Up @@ -660,10 +671,13 @@ def main():
_identity_center_scan(IdentityCenter(args.ic_start_url, args.ic_region), Printer("realtime", sys.stdout))
elif args.subcommand == "session-ic":
_clear_session()
if args.aws_region is None:
args.aws_region = args.ic_region
_session_ic(
IdentityCenter(args.ic_start_url, args.ic_region),
args.account_id,
args.role_name,
args.aws_region,
ShellPrompt(enabled=not args.no_prompt_update),
)
elif args.subcommand == "session-access-key":
Expand Down

0 comments on commit fedf034

Please sign in to comment.