Metadata-Version: 2.4
Name: ss-cloud-cli
Version: 0.2.1
Summary: Unified cloud and platform CLI for AWS, Kubernetes, and registry workflows.
Project-URL: Homepage, https://github.com/sszhu/cloudcli
Project-URL: Documentation, https://github.com/sszhu/cloudcli#readme
Project-URL: Issues, https://github.com/sszhu/cloudcli/issues
Project-URL: Repository, https://github.com/sszhu/cloudcli
Project-URL: ChangeLog, https://github.com/sszhu/cloudcli/blob/main/CHANGELOG.md
Author-email: Shanshan Zhu <sszhu.soft@gmail.com>
License: MIT
License-File: LICENSE
Keywords: aws,cli,cloud,devops,eks,kubernetes,platform
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.11
Requires-Dist: rich<14.0,>=13.9
Requires-Dist: typer<1.0,>=0.16
Provides-Extra: dev
Requires-Dist: mypy>=1.15; extra == 'dev'
Requires-Dist: pre-commit>=4.1; extra == 'dev'
Requires-Dist: pytest-cov>=6.0; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.9; extra == 'dev'
Requires-Dist: twine>=6.1; extra == 'dev'
Description-Content-Type: text/markdown

# cloud

`cloud` is a unified CLI for AWS authentication, context switching, Kubernetes workflows, registry login, IAM operations, and S3 bucket-policy management.

It replaces ad hoc combinations of `aws`, `kubectl`, `docker`, `saml2aws`, and shell aliases with one command surface, one config file, and consistent table or JSON output.

## Highlights

- Interactive and explicit profile selection for `login` and `ctx`
- Context switching with optional cluster selection and credential validation
- Credential expiration visibility in `whoami`, `login`, `ctx`, and `env`
- Kubernetes pod, namespace, context, and log helpers
- ECR login automation
- Cluster inventory and plugin discovery commands
- Declarative IAM management and JSON generators
- S3 bucket-policy inspection, diff, grant, and revoke workflows

## Install

Install the CLI with `pip`:

```bash
pip install ss-cloud-cli
```

Install the CLI with `uv`:

```bash
uv tool install ss-cloud-cli
```

Upgrade later with:

```bash
uv tool upgrade ss-cloud-cli
```

For local development:

```bash
make install-dev

# or directly
uv sync --extra dev
```

## Quickstart

Create `~/.cloud/config.toml`:

```toml
version = 1

[defaults]
profile = "dev"
region = "us-east-1"
output = "table"
namespace = "default"
color = true

[profiles.dev]
auth_provider = "saml2aws"
aws_profile = "dev"
region = "us-east-1"
cluster = "dev-main"
namespace = "platform"
registry = "123456789012.dkr.ecr.us-east-1.amazonaws.com"

[clusters.dev-main]
kube_context = "arn:aws:eks:us-east-1:123456789012:cluster/dev-main"
namespace = "platform"
region = "us-east-1"
profile = "dev"
```

Then run:

```bash
cloud login dev
cloud ctx dev dev-main
cloud whoami
cloud k8s pods
cloud ecr login
cloud doctor
```

## Authentication And Context

Interactive commands:

```bash
cloud login
cloud ctx
```

Behavior:

- `cloud login` can prompt for a profile when no positional profile is provided.
- `cloud ctx` can prompt for a profile first and then prompt for a cluster if that profile has multiple configured cluster targets.
- `cloud ctx` validates the selected profile before switching context. If the profile is expired or otherwise not usable, `cloud` logs in first and then completes the switch.
- `cloud login <profile> --force` refreshes credentials even when the current session is still valid.
- For `saml2aws` profiles, `cloud login <profile> --force` passes `--force` through to `saml2aws login` so provider-side cached credentials are actually refreshed.

For teams already using `saml2aws login -a <account> -p <profile>`, `cloud login <profile>` can infer that flow directly from the profile config. `login_command` still wins if you need a fully custom auth command.

To bootstrap `~/.cloud/config.toml` from existing AWS and `saml2aws` files:

```bash
cloud init import-aws --stdout
cloud init import-aws --target ~/.cloud/config.toml
```

Imported profiles are classified as:

- `saml2aws` when a matching section exists in `~/.saml2aws`
- `aws-sso` when the AWS config contains SSO settings
- `external` when `cloud` can use the AWS profile but cannot initiate login itself

Static access-key profiles from `~/.aws/credentials` are supported through `external` mode. In that case, `cloud` will use the profile for AWS CLI-backed operations such as `cloud whoami` and `cloud ecr login`, but `cloud login` will not create or refresh those credentials.

Example:

```toml
[profiles.abc]
auth_provider = "external"
aws_profile = "abc"
region = "us-east-1"
```

## Credential Expiration Visibility

`cloud whoami`, `cloud login`, `cloud ctx`, and `cloud env` expose the current AWS session timing when the active profile uses temporary credentials.

These commands may include:

- `credentials_expires_at`: normalized UTC expiration timestamp
- `credentials_expires_at_local`: the same expiration rendered in your local timezone
- `credentials_expired`: whether the current session is already expired

Example:

```bash
cloud whoami
cloud login dev
cloud login dev --force
cloud ctx dev dev-main
cloud env
```

Sample output:

```text
key                          value
profile                      dev
region                       us-east-1
credentials_expires_at       2026-03-10T10:28:42Z
credentials_expires_at_local 2026-03-10T18:28:42+08:00
credentials_expired          False
```

Notes:

- `cloud login <profile>` reuses an unexpired session when the expiration can be determined.
- For `saml2aws` profiles, `cloud` can read session expiry from `~/.aws/credentials` fields such as `x_security_token_expires` when the AWS CLI export output does not include an expiration.
- `cloud env --export` remains shell-only output and does not append these metadata fields.

## IAM Management

`cloud` can manage IAM roles, managed policies, and role-policy attachments from a JSON or TOML spec file.

Common workflows:

- `cloud iam show --spec examples/iam-github-oidc.json`
- `cloud iam apply --spec examples/iam-github-oidc.json --confirm`
- `cloud iam rollback --spec examples/iam-github-oidc.json --confirm`
- `cloud iam init spec --from-template github-oidc-s3 --output iam-spec.json --workload-name analytics --subject 'repo:example-org/analytics:*'`
- `cloud iam init trust-policy --from-template github-oidc --stdout --subject 'repo:example-org/analytics:*'`
- `cloud iam init policy --output analytics-policy.json --bucket-name example-platform-artifacts --prefix analytics`

Behavior:

- `--confirm` shows the planned IAM changes and asks for approval before applying them.
- `--dry-run` shows the plan without creating, updating, attaching, detaching, or deleting anything.
- `--show-after` is enabled by default so the command prints the updated IAM state after each apply or rollback.
- `cloud iam init ...` generates reviewable JSON for trust policies, S3 prefix policies, or full IAM spec files.
- In `zsh`, quote any `--subject` values that contain `*`, for example `'repo:example-org/tracy:*'`.

Template generation examples:

```bash
cloud iam init spec \
  --from-template github-oidc-s3 \
  --output analytics-iam.json \
  --workload-name analytics \
  --account-id 123456789012 \
  --bucket-name example-platform-artifacts \
  --subject 'repo:example-org/analytics:*' \
  --permissions-boundary-arn arn:aws:iam::999999999999:policy/ExamplePermissionsBoundary

cloud iam init trust-policy \
  --from-template github-oidc \
  --stdout \
  --oidc-provider-arn arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com/example-org \
  --provider-condition-prefix token.actions.githubusercontent.com/example-org \
  --subject 'repo:example-org/analytics:*' \
  --subject 'repo:example-org/analytics-data:*'

cloud iam init policy \
  --output analytics-policy.json \
  --bucket-name example-platform-artifacts \
  --prefix analytics \
  --sid-prefix Analytics
```

Reference spec:

```json
{
  "version": 1,
  "account_id": "123456789012",
  "roles": [
    {
      "name": "GitHubOidcAnalyticsRunner",
      "permissions_boundary": "arn:aws:iam::999999999999:policy/ExamplePermissionsBoundary",
      "assume_role_policy_document": {
        "Version": "2012-10-17",
        "Statement": [
          {
            "Sid": "GitHubOidcTrustAnalytics",
            "Effect": "Allow",
            "Principal": {
              "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com/example-org"
            },
            "Action": "sts:AssumeRoleWithWebIdentity"
          }
        ]
      }
    }
  ],
  "policies": [
    {
      "name": "GitHubOidcAnalyticsS3Access",
      "document": {
        "Version": "2012-10-17",
        "Statement": [
          {
            "Sid": "RWAnalyticsObjects",
            "Effect": "Allow",
            "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
            "Resource": "arn:aws:s3:::example-platform-artifacts/analytics/*"
          }
        ]
      }
    }
  ],
  "attachments": [
    {
      "role_name": "GitHubOidcAnalyticsRunner",
      "policy_name": "GitHubOidcAnalyticsS3Access"
    }
  ]
}
```

## S3 Bucket Policy Management

`cloud` can inspect the current bucket policy and grant or revoke role access to a specific S3 prefix.

Common workflows:

- `cloud s3 bucket-policy show --bucket example-bucket --prefix analytics --output json`
- `cloud s3 bucket-policy diff --action grant --bucket example-bucket --prefix analytics --role-arn arn:aws:iam::123456789012:role/ExampleRole --access read-only`
- `cloud s3 bucket-policy grant --bucket example-bucket --prefix analytics --role-arn arn:aws:iam::123456789012:role/ExampleRole --access read-only --confirm`
- `cloud s3 bucket-policy revoke --bucket example-bucket --prefix analytics --role-arn arn:aws:iam::123456789012:role/ExampleRole --confirm`

Notes:

- `show --prefix ...` filters the output down to statements relevant to that prefix.
- `diff` shows a unified diff between the current bucket policy and the proposed policy after a `grant` or `revoke` operation.
- `grant --access read-only` creates an object statement with `s3:GetObject` only.
- `grant --access read-write` creates an object statement with `s3:GetObject`, `s3:PutObject`, and `s3:DeleteObject`.
- `revoke` removes the role from matching prefix statements and deletes any statement that becomes empty.
- `--sid-prefix` lets you target or create a specific statement pair when your bucket policy already has multiple statement sets for the same prefix.
- `--bucket` accepts either a plain bucket name such as `example-bucket` or an `s3://example-bucket[/optional/path]` style identifier; the bucket name is normalized before AWS API calls.

Example:

```bash
cloud s3 bucket-policy show \
  --bucket example-bucket \
  --prefix analytics \
  --output json

cloud s3 bucket-policy diff \
  --action grant \
  --bucket example-bucket \
  --prefix analytics \
  --role-arn arn:aws:iam::123456789012:role/analytics-service \
  --access read-only \
  --output json

cloud s3 bucket-policy grant \
  --bucket example-bucket \
  --prefix analytics \
  --role-arn arn:aws:iam::123456789012:role/analytics-service \
  --access read-only \
  --sid-prefix AnalyticsWorkspace \
  --confirm \
  --output json

cloud s3 bucket-policy revoke \
  --bucket example-bucket \
  --prefix analytics \
  --role-arn arn:aws:iam::123456789012:role/analytics-service \
  --sid-prefix AnalyticsWorkspace \
  --confirm \
  --output json
```

## Shell Environment Model

`cloud` does not try to mutate the parent shell directly. Instead, it renders explicit exports:

```bash
eval "$(cloud env --export --shell zsh)"
```

For CI and scripts, prefer JSON output or explicit child-process execution over shell mutation.

## Development

Bootstrap the local environment with `uv`:

```bash
uv sync --extra dev
```

Common tasks:

```bash
make install-dev
make fmt
make lint
make typecheck
make test
make build
make check-dist
```

The Makefile uses `uv run`, `uv build`, and `uv publish` so local commands and CI stay aligned.

## Publishing

The repository includes GitHub Actions workflows for:

- PR validation
- TestPyPI publish via Trusted Publishing and `uv publish`
- PyPI publish via Trusted Publishing and `uv publish`

For local release steps and verification commands, see `RELEASE.md`.
