Skip to content

Commit adc48e3

Browse files
whummerclaude
andcommitted
aws-proxy: replace deprecated CLI with direct Python/HTTP proxy startup
Remove dependency on `localstack aws proxy` CLI (no longer functional). Start the proxy server via AuthProxyAWS.start_from_config_file() and register with LocalStack via AuthProxyAWS.register_proxy(), both invoked as Python one-liners inside the proxy container. Update README to document curl-based enable/disable and reference the LocalStack Web App. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7af47c9 commit adc48e3

File tree

4 files changed

+83
-77
lines changed

4 files changed

+83
-77
lines changed

aws-proxy/README.md

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,52 +21,55 @@ The AWS Cloud Proxy can be used to forward certain API calls in LocalStack to re
2121

2222
**Warning:** Be careful when using the proxy - make sure to _never_ give access to production accounts or any critical/sensitive data!
2323

24-
**Note:** The Cloud Proxy CLI currently works only when installing the `localstack` CLI via `pip`.
25-
If you're downloading the `localstack` CLI as a [binary release](https://docs.localstack.cloud/getting-started/installation/#localstack-cli), then please use the proxy configuration UI described below.
26-
2724
### Usage
2825

29-
#### CLI
30-
For example, in order to forward all API calls for DynamoDB/S3/Cognito to real AWS, the proxy can be started via the CLI as follows:
26+
#### Using curl (API)
3127

32-
1. Start LocalStack via CLI
33-
```
34-
$ localstack start -d
35-
```
36-
2. Enable LocalStack AWS Proxy from the Web Application Extension Library
37-
3. After installation restart Localstack
38-
4. Install the AWS Proxy CLI package
39-
```
40-
$ pip install localstack-extension-aws-proxy
41-
```
42-
5. Configure real cloud account credentials in a new terminal session to allow access
28+
The proxy can be enabled and disabled via the LocalStack internal API. This is the recommended approach.
29+
30+
1. Start LocalStack and install the AWS Proxy extension (restart LocalStack after installation).
31+
32+
2. Enable the proxy for specific services (e.g., DynamoDB, S3, Cognito) by posting a configuration along with your AWS credentials:
4333
```
44-
$ export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=...
34+
$ curl -X POST http://localhost:4566/_localstack/aws/proxies \
35+
-H 'Content-Type: application/json' \
36+
-d '{
37+
"config": {
38+
"services": {
39+
"dynamodb": {},
40+
"s3": {},
41+
"cognito-idp": {}
42+
}
43+
},
44+
"env_vars": {
45+
"AWS_ACCESS_KEY_ID": "<your-access-key-id>",
46+
"AWS_SECRET_ACCESS_KEY": "<your-secret-access-key>",
47+
"AWS_SESSION_TOKEN": "<your-session-token>"
48+
}
49+
}'
4550
```
46-
6. Start proxy in aforementioned terminal session via the CLI
51+
52+
3. Check the proxy status:
4753
```
48-
$ localstack aws proxy -s dynamodb,s3,cognito-idp
54+
$ curl http://localhost:4566/_localstack/aws/proxies/status
4955
```
50-
7. Now, when issuing an API call against LocalStack (e.g., via `awslocal`), the invocation gets forwarded to real AWS and should return data from your real cloud resources.
5156

52-
#### Proxy Configuration UI
53-
54-
1. Start Localstack with extra CORS
57+
4. Disable the proxy:
5558
```
56-
EXTRA_CORS_ALLOWED_ORIGINS=https://aws-proxy.localhost.localstack.cloud:4566 localstack start -d
59+
$ curl -X POST http://localhost:4566/_localstack/aws/proxies/status \
60+
-H 'Content-Type: application/json' \
61+
-d '{"status": "disabled"}'
5762
```
5863

59-
2. Enable Localstack AWS Proxy from the Web Application Extension Library
60-
61-
3. Once the extension is installed, it will expose a small configuration endpoint in your LocalStack container under the following endpoint: http://localhost:4566/_localstack/aws-proxy/index.html .
64+
5. Now, when issuing an API call against LocalStack (e.g., via `awslocal`), the invocation gets forwarded to real AWS and should return data from your real cloud resources.
6265

63-
4. Use this Web UI to define the proxy configuration (in YAML syntax), as well as the AWS credentials (AWS access key ID, secret access key, and optionally session token) and save configuration. The proxy should report enabled state and on the host a proxy container should spawn.
66+
#### Using the LocalStack Web App
6467

65-
![configuration settings](etc/proxy-settings.png)
68+
You can also configure the proxy from the LocalStack Web App at https://app.localstack.cloud. Navigate to your instance and use the AWS Proxy extension settings to enable/disable the proxy and manage credentials.
6669

67-
5. Now we can communicate with the real AWS cloud resources, directly via LocalStack.
70+
Alternatively, the extension exposes a local configuration UI at http://localhost:4566/_localstack/aws-proxy/index.html (requires starting LocalStack with `EXTRA_CORS_ALLOWED_ORIGINS=https://aws-proxy.localhost.localstack.cloud:4566`). Use this Web UI to define the proxy configuration (in YAML syntax) and AWS credentials, then save the configuration. To clean up the running proxy container, click "disable" in the UI.
6871

69-
To clean up the running proxy container simply click "disable" on the Cloud Proxy UI.
72+
![configuration settings](etc/proxy-settings.png)
7073

7174
### Resource-specific proxying
7275

@@ -90,10 +93,7 @@ services:
9093
execute: false
9194
```
9295

93-
Store the configuration above to a file named `proxy_config.yml`, then we can start up the proxy via:
94-
```
95-
localstack aws proxy -c proxy_config.yml
96-
```
96+
Pass this configuration in the `config` field of the `POST /_localstack/aws/proxies` request body (as shown above).
9797

9898
If we then perform local operations against the S3 bucket `my-s3-bucket`, the proxy will forward the request and will return the results from real AWS:
9999
```
@@ -118,8 +118,6 @@ In addition to the proxy services configuration shown above, the following confi
118118
* `PROXY_LOCALSTACK_HOST`: the target host to use when the proxy container connects to the LocalStack main container (automatically determined by default)
119119
* `PROXY_DOCKER_FLAGS`: additional flags that should be passed when creating the proxy Docker containers
120120

121-
**Note:** Due to some recent changes in the core framework, make sure to start up your LocalStack container with the `GATEWAY_SERVER=hypercorn` configuration enabled, for backwards compatibility. This will be fixed in an upcoming release.
122-
123121
## Resource Replicator CLI (deprecated)
124122

125123
Note: Previous versions of this extension also offered a "replicate" mode to copy/clone (rather than proxy) resources from an AWS account into the local instance.
@@ -129,6 +127,7 @@ If you wish to access the deprecated instructions, they can be found [here](http
129127

130128
## Change Log
131129

130+
* `0.2.4`: Replace deprecated `localstack aws proxy` CLI command with direct Python/HTTP-based proxy startup; update README with curl-based usage instructions
132131
* `0.2.3`: Enhance proxy support and tests for several services (API Gateway v1/v2, CloudWatch, AppSync, Kinesis, KMS, SNS, Cognito-IDP)
133132
* `0.2.2`: Refactor UI to use WebAppExtension pattern
134133
* `0.2.1`: Restructure project to use pyproject.toml

aws-proxy/aws_proxy/client/auth_proxy.py

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
import logging
44
import os
55
import re
6-
import subprocess
7-
import sys
6+
import time
87
from functools import cache
98
from typing import Dict, Optional, Tuple
109
from urllib.parse import urlparse, urlunparse
@@ -24,10 +23,6 @@
2423
LOCALHOST_HOSTNAME,
2524
)
2625
from localstack.http import Request
27-
from localstack.pro.core.bootstrap.licensingv2 import (
28-
ENV_LOCALSTACK_API_KEY,
29-
ENV_LOCALSTACK_AUTH_TOKEN,
30-
)
3126
from localstack.utils.aws.aws_responses import requests_response
3227
from localstack.utils.bootstrap import setup_logging
3328
from localstack.utils.collections import select_attributes
@@ -50,6 +45,7 @@
5045
from aws_proxy.shared.models import AddProxyRequest, ProxyConfig
5146

5247
LOG = logging.getLogger(__name__)
48+
5349
LOG.setLevel(logging.INFO)
5450
if localstack_config.DEBUG:
5551
LOG.setLevel(logging.DEBUG)
@@ -75,16 +71,34 @@ def __init__(self, config: ProxyConfig, port: int = None):
7571
super().__init__(port=port)
7672

7773
def do_run(self):
74+
self.register_in_instance()
75+
self.run_server()
76+
77+
def run_server(self):
7878
# note: keep import here, to avoid runtime errors
7979
from .http2_server import run_server
8080

81-
self.register_in_instance()
8281
bind_host = self.config.get("bind_host") or DEFAULT_BIND_HOST
8382
proxy = run_server(
8483
port=self.port, bind_addresses=[bind_host], handler=self.proxy_request
8584
)
8685
proxy.join()
8786

87+
@classmethod
88+
def start_from_config_file(cls, config_file: str, port: int):
89+
config = json.load(open(config_file))
90+
config["bind_host"] = "0.0.0.0"
91+
cls(config, port=port).run_server()
92+
93+
@staticmethod
94+
def register_proxy(
95+
config_file: str, port: int, localstack_host: str, localstack_port: int = 4566
96+
):
97+
time.sleep(2)
98+
config = json.load(open(config_file))
99+
url = f"http://{localstack_host}:{localstack_port}{HANDLER_PATH_PROXIES}"
100+
requests.post(url, json={"port": port, "config": config})
101+
88102
def proxy_request(self, request: Request, data: bytes) -> Response:
89103
parsed = self._extract_region_and_service(request.headers)
90104
if not parsed:
@@ -464,8 +478,7 @@ def start_aws_auth_proxy_in_container(
464478
"AWS_ACCESS_KEY_ID",
465479
"AWS_SESSION_TOKEN",
466480
"AWS_DEFAULT_REGION",
467-
ENV_LOCALSTACK_API_KEY,
468-
ENV_LOCALSTACK_AUTH_TOKEN,
481+
"LOCALSTACK_AUTH_TOKEN",
469482
]
470483
env_vars = env_vars or os.environ
471484
env_vars = select_attributes(dict(env_vars), env_var_names)
@@ -477,42 +490,33 @@ def start_aws_auth_proxy_in_container(
477490
target_host = get_docker_host_from_container()
478491
env_vars["LOCALSTACK_HOST"] = target_host
479492

480-
# Use the Docker SDK command either if quiet mode is enabled, or if we're executing
481-
# in Docker itself (e.g., within the LocalStack main container, as part of an init script)
482-
use_docker_sdk_command = quiet or localstack_config.is_in_docker
483-
484493
try:
485494
print("Proxy container is ready.")
486-
command = f"{venv_activate}; localstack aws proxy -c {CONTAINER_CONFIG_FILE} -p {port} --host 0.0.0.0 > {CONTAINER_LOG_FILE} 2>&1"
487-
if use_docker_sdk_command:
488-
DOCKER_CLIENT.exec_in_container(
489-
container_name,
490-
command=["bash", "-c", command],
491-
env_vars=env_vars,
492-
interactive=True,
493-
)
494-
else:
495-
env_vars_list = []
496-
for key, value in env_vars.items():
497-
env_vars_list += ["-e", f"{key}={value}"]
498-
# note: using docker command directly, as our Docker client doesn't fully support log piping yet
499-
command = [
500-
"docker",
501-
"exec",
502-
"-it",
503-
*env_vars_list,
504-
container_name,
505-
"bash",
506-
"-c",
507-
command,
508-
]
509-
subprocess.run(command, stdout=sys.stdout, stderr=sys.stderr)
495+
# Start proxy server in background using Python directly (no CLI dependency)
496+
start_server_cmd = (
497+
f"{venv_activate}; "
498+
f'python -c "from aws_proxy.client.auth_proxy import AuthProxyAWS; '
499+
f"AuthProxyAWS.start_from_config_file('{CONTAINER_CONFIG_FILE}', {port})\" "
500+
f">> {CONTAINER_LOG_FILE} 2>&1 &"
501+
)
502+
# Register proxy with LocalStack, passing the port
503+
register_cmd = (
504+
f"{venv_activate}; "
505+
f'python -c "from aws_proxy.client.auth_proxy import AuthProxyAWS; '
506+
f"AuthProxyAWS.register_proxy('{CONTAINER_CONFIG_FILE}', {port}, '{target_host}')\" "
507+
f">> {CONTAINER_LOG_FILE} 2>&1"
508+
)
509+
command = f"{start_server_cmd} {register_cmd}"
510+
DOCKER_CLIENT.exec_in_container(
511+
container_name,
512+
command=["bash", "-c", command],
513+
env_vars=env_vars,
514+
interactive=False,
515+
)
510516
except KeyboardInterrupt:
511517
pass
512518
except Exception as e:
513519
LOG.info("Error: %s", e)
514-
if isinstance(e, subprocess.CalledProcessError):
515-
LOG.info("Error in called process - output: %s\n%s", e.stdout, e.stderr)
516520
finally:
517521
try:
518522
if repl_config.CLEANUP_PROXY_CONTAINERS:

aws-proxy/aws_proxy/client/cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import re
22
import sys
33

4+
# Note: This CLI plugin is deprecated and may be removed in a future version.
5+
# Use the LocalStack internal API or the LocalStack Web App to configure the proxy instead.
6+
47
import click
58
import yaml
69
from localstack.cli import LocalstackCli, LocalstackCliPlugin, console

aws-proxy/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
66
[project]
77
name = "localstack-extension-aws-proxy"
88
readme = "README.md"
9-
version = "0.2.3"
9+
version = "0.2.4"
1010
description = "LocalStack extension that proxies AWS resources into your LocalStack instance"
1111
authors = [
1212
{ name = "LocalStack Team", email = "info@localstack.cloud"}

0 commit comments

Comments
 (0)