Metadata-Version: 2.4
Name: cloud-run-readonly-proxy
Version: 0.1.1
Summary: A renewable read-only local proxy for private Google Cloud Run services
Project-URL: Documentation, https://github.com/alexei-ciobanu/cloud-run-readonly-proxy#readme
Project-URL: Issues, https://github.com/alexei-ciobanu/cloud-run-readonly-proxy/issues
Project-URL: Source, https://github.com/alexei-ciobanu/cloud-run-readonly-proxy
Author: Alexei Ciobanu
License-Expression: MIT
License-File: LICENSE
Keywords: cloud-run,google-cloud,proxy
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
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: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Requires-Python: >=3.11
Requires-Dist: aiohttp<4,>=3.11
Requires-Dist: google-auth[requests]<3,>=2.38
Requires-Dist: truststore<1,>=0.10
Description-Content-Type: text/markdown

# cloud-run-readonly-proxy

A local reverse proxy for read-only access to IAM-protected Google Cloud Run
services. It uses Application Default Credentials (ADC), either directly or as
the source for service-account impersonation, and renews Cloud Run ID tokens
without restarting the local listener. Only `GET` and `HEAD` requests are
accepted.

## Requirements

- Python 3.11 or newer and [uv](https://docs.astral.sh/uv/)
- The Google Cloud CLI (`gcloud`) for initializing or refreshing ADC
- ADC initialized with `gcloud auth login --update-adc`
- `roles/run.invoker` on the Cloud Run service for either the ADC user or the
  impersonated service account

Service-account impersonation additionally requires
`roles/iam.serviceAccountTokenCreator` on the impersonated service account.

## Run

From PyPI:

```bash
uvx cloud-run-readonly-proxy@0.1.1 \
  --target-url TAGGED_OR_UNTAGGED_URL
```

Or install it with `pip` and invoke the Python module (module names use
underscores rather than dashes):

```bash
python -m pip install cloud-run-readonly-proxy
python -m cloud_run_readonly_proxy \
  --target-url TAGGED_OR_UNTAGGED_URL
```

Directly from a pinned public Git commit:

```bash
uvx --from 'git+https://github.com/alexei-ciobanu/cloud-run-readonly-proxy@COMMIT_SHA' \
  cloud-run-readonly-proxy \
  --target-url TAGGED_OR_UNTAGGED_URL
```

The local page opens automatically at <http://localhost:8080>. Pass
`--no-browser` to leave it unopened, such as when running in a headless
environment.

Direct mode uses the user represented by ADC. That user must have Cloud Run
Invoker on the service. Google documents these generic user ID tokens for
development use; they are not bound to one target audience and are therefore
more replayable than service-account ID tokens.

For an audience-bound token, use service-account impersonation:

```bash
uvx cloud-run-readonly-proxy@0.1.1 \
  --target-url TAGGED_OR_UNTAGGED_URL \
  --audience UNTAGGED_SERVICE_URL \
  --impersonate-service-account INVOKER_SA
```

For a traffic-tag URL, `--target-url` is the tagged URL while `--audience`
remains the untagged service URL. `--audience` and
`--impersonate-service-account` must be supplied together.

Other options:

```text
--port PORT                 Local port; default: 8080
--auth-retry-seconds N      Delay after a failed token refresh; default: 5
--reauth-command COMMAND    Command launched or shown when ADC needs refreshing
--no-browser                Do not open the local proxy in the default browser
```

## Authentication and proxying

In direct mode the tool:

1. loads user ADC directly through the Google authentication library;
2. refreshes ADC and reads the returned OpenID Connect ID token; and
3. starts a listener bound to `127.0.0.1` only.

When impersonation is requested, it instead uses ADC to call the IAM
Credentials API and mint an audience-bound ID token for the explicitly
configured service account.

The proxy reads each token's JWT expiration and refreshes it before expiry. If
ADC expires while the process is running, the listener remains alive and
serves a local recovery page instead of exiting. Select **Sign in** to run:

```bash
gcloud auth login --update-adc --quiet
```

The command opens the Google Cloud login flow in the system browser. After
authentication succeeds, the originally requested page reloads automatically.
The command is also displayed for manual use.

Only `GET` and `HEAD` requests are proxied. Authorization headers supplied by
the browser are discarded and replaced with the generated Cloud Run token.
Responses are streamed, redirects back to the Cloud Run origins are rewritten
to localhost, and the system trust store is used for outbound TLS.

## Local development

```bash
uv sync --dev
uv run ruff check .
uv run ruff format --check .
uv run ty check src
uv run cloud-run-readonly-proxy --help
```

## License

MIT
