Skip to content

fix(awsauth): let CONNECT through the tunnel policy check#167

Merged
mslipper merged 1 commit into
ironsh:mainfrom
0xSplits:diid/awsauth-connect-passthrough
May 29, 2026
Merged

fix(awsauth): let CONNECT through the tunnel policy check#167
mslipper merged 1 commit into
ironsh:mainfrom
0xSplits:diid/awsauth-connect-passthrough

Conversation

@0xdiid

@0xdiid 0xdiid commented May 29, 2026

Copy link
Copy Markdown
Contributor

The proxy replays request transforms against a synthetic CONNECT request to make tunnel-level policy decisions before MITM (proxy.tunnelTransformCheck). The aws_auth transform matched on host only and rejected any matched request lacking a SigV4 signature -- including that synthetic CONNECT, which can never carry one (the signed request only appears after the tunnel is established and TLS is terminated). That short-circuited the tunnel with 400/missing_sigv4 before the real, boto3-signed request was ever seen, so SigV4 re-signing never happened for HTTPS clients tunneling through a CONNECT proxy (e.g. boto3).

Return ActionContinue for CONNECT so the tunnel establishes; signing then happens on the post-MITM request that follows. allowlist/secrets already tolerate the synthetic CONNECT.

The proxy replays request transforms against a synthetic CONNECT request to
make tunnel-level policy decisions before MITM (proxy.tunnelTransformCheck).
The aws_auth transform matched on host only and rejected any matched request
lacking a SigV4 signature -- including that synthetic CONNECT, which can never
carry one (the signed request only appears after the tunnel is established and
TLS is terminated). That short-circuited the tunnel with 400/missing_sigv4
before the real, boto3-signed request was ever seen, so SigV4 re-signing never
happened for HTTPS clients tunneling through a CONNECT proxy (e.g. boto3).

Return ActionContinue for CONNECT so the tunnel establishes; signing then
happens on the post-MITM request that follows. allowlist/secrets already
tolerate the synthetic CONNECT.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@mslipper mslipper merged commit 7159126 into ironsh:main May 29, 2026
5 of 7 checks passed
0xdiid added a commit to 0xSplits/centaur that referenced this pull request May 29, 2026
…NECT fix

0.42.0-rc.4 is the first release containing ironsh/iron-proxy#167, which lets
the synthetic CONNECT through the tunnel transform-policy check so aws_auth
signs the post-MITM inner request instead of rejecting the CONNECT. Required
for the CloudWatch tool's aws_auth path.
mslipper pushed a commit to paradigmxyz/centaur that referenced this pull request Jun 3, 2026
)

* feat(tools): add read-only CloudWatch tool via iron-proxy aws_auth

Add a `cloudwatch` infra tool mirroring the AWS CloudWatch MCP's read-only
surface: log groups, filter log events, Logs Insights queries, metrics, and
alarms (boto3-backed, JSON-safe responses, lazy client so discovery needs no
credentials or network).

AWS auth rides iron-proxy's `aws_auth` transform rather than holding real
credentials in the tool process. SigV4 can't be swapped on the wire like a
bearer token, but iron-proxy re-signs: boto3 signs each request with throwaway
placeholder credentials, and iron-proxy reads the region/service from the
signature scope and re-signs with the real read-only IAM keys it resolves from
the secrets backend. The keys never enter the workload — the SigV4 analogue of
the `secrets` placeholder swap. (aws_auth landed in iron-proxy v0.40.0; Centaur
pins 0.42.0-rc.2, which includes it.)

- tool_manager: AwsAuthSecret type + parser (access_key_id/secret_access_key/
  session_token refs, allowed_regions/services, hosts)
- proxy_config: render the aws_auth transform; add to _MANAGED_TRANSFORMS
- iron-proxy base configs: allowlist x-amz-* so x-amz-target (the CloudWatch
  operation header) survives egress filtering
- cloudwatch tool: declare the aws_auth secret; sign with placeholders; region
  is the only real value (non-secret, read from env, defaults us-east-1)
- kubernetes: expose only AWS_REGION (non-secret, optional) to the tool-server
  sidecar — no AWS credentials in-process
- tests: cloudwatch client, aws_auth parser + renderer, sidecar (creds absent)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(cloudwatch): allow AWS SDK signed headers through the egress filter

aws_auth re-signs CloudWatch requests with the AWS SDK v4 signer, whose
signed-headers set includes the SDK's amz-sdk-request, amz-sdk-invocation-id,
and (for CloudWatch's query-JSON protocol) x-amzn-query-mode headers.
header_allowlist runs after aws_auth and was stripping them, so AWS rebuilt
the canonical request without them and rejected every call with
InvalidSignatureException.

Allow /^amz-sdk-.*$/ and /^x-amzn-.*$/ so the signed headers reach AWS. Pairs
with the /^x-amz-.*$/ allowance already added for the SigV4 headers.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(iron-proxy): bump base image to 0.42.0-rc.4 for the awsauth CONNECT fix

0.42.0-rc.4 is the first release containing ironsh/iron-proxy#167, which lets
the synthetic CONNECT through the tunnel transform-policy check so aws_auth
signs the post-MITM inner request instead of rejecting the CONNECT. Required
for the CloudWatch tool's aws_auth path.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
renxinxing123 pushed a commit to Coral-Protocol/coral_centaur that referenced this pull request Jun 7, 2026
…287)

* feat(tools): add read-only CloudWatch tool via iron-proxy aws_auth

Add a `cloudwatch` infra tool mirroring the AWS CloudWatch MCP's read-only
surface: log groups, filter log events, Logs Insights queries, metrics, and
alarms (boto3-backed, JSON-safe responses, lazy client so discovery needs no
credentials or network).

AWS auth rides iron-proxy's `aws_auth` transform rather than holding real
credentials in the tool process. SigV4 can't be swapped on the wire like a
bearer token, but iron-proxy re-signs: boto3 signs each request with throwaway
placeholder credentials, and iron-proxy reads the region/service from the
signature scope and re-signs with the real read-only IAM keys it resolves from
the secrets backend. The keys never enter the workload — the SigV4 analogue of
the `secrets` placeholder swap. (aws_auth landed in iron-proxy v0.40.0; Centaur
pins 0.42.0-rc.2, which includes it.)

- tool_manager: AwsAuthSecret type + parser (access_key_id/secret_access_key/
  session_token refs, allowed_regions/services, hosts)
- proxy_config: render the aws_auth transform; add to _MANAGED_TRANSFORMS
- iron-proxy base configs: allowlist x-amz-* so x-amz-target (the CloudWatch
  operation header) survives egress filtering
- cloudwatch tool: declare the aws_auth secret; sign with placeholders; region
  is the only real value (non-secret, read from env, defaults us-east-1)
- kubernetes: expose only AWS_REGION (non-secret, optional) to the tool-server
  sidecar — no AWS credentials in-process
- tests: cloudwatch client, aws_auth parser + renderer, sidecar (creds absent)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(cloudwatch): allow AWS SDK signed headers through the egress filter

aws_auth re-signs CloudWatch requests with the AWS SDK v4 signer, whose
signed-headers set includes the SDK's amz-sdk-request, amz-sdk-invocation-id,
and (for CloudWatch's query-JSON protocol) x-amzn-query-mode headers.
header_allowlist runs after aws_auth and was stripping them, so AWS rebuilt
the canonical request without them and rejected every call with
InvalidSignatureException.

Allow /^amz-sdk-.*$/ and /^x-amzn-.*$/ so the signed headers reach AWS. Pairs
with the /^x-amz-.*$/ allowance already added for the SigV4 headers.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(iron-proxy): bump base image to 0.42.0-rc.4 for the awsauth CONNECT fix

0.42.0-rc.4 is the first release containing ironsh/iron-proxy#167, which lets
the synthetic CONNECT through the tunnel transform-policy check so aws_auth
signs the post-MITM inner request instead of rejecting the CONNECT. Required
for the CloudWatch tool's aws_auth path.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0xdiid added a commit to 0xSplits/centaur that referenced this pull request Jun 8, 2026
…aradigmxyz#287)

* feat(tools): add read-only CloudWatch tool via iron-proxy aws_auth

Add a `cloudwatch` infra tool mirroring the AWS CloudWatch MCP's read-only
surface: log groups, filter log events, Logs Insights queries, metrics, and
alarms (boto3-backed, JSON-safe responses, lazy client so discovery needs no
credentials or network).

AWS auth rides iron-proxy's `aws_auth` transform rather than holding real
credentials in the tool process. SigV4 can't be swapped on the wire like a
bearer token, but iron-proxy re-signs: boto3 signs each request with throwaway
placeholder credentials, and iron-proxy reads the region/service from the
signature scope and re-signs with the real read-only IAM keys it resolves from
the secrets backend. The keys never enter the workload — the SigV4 analogue of
the `secrets` placeholder swap. (aws_auth landed in iron-proxy v0.40.0; Centaur
pins 0.42.0-rc.2, which includes it.)

- tool_manager: AwsAuthSecret type + parser (access_key_id/secret_access_key/
  session_token refs, allowed_regions/services, hosts)
- proxy_config: render the aws_auth transform; add to _MANAGED_TRANSFORMS
- iron-proxy base configs: allowlist x-amz-* so x-amz-target (the CloudWatch
  operation header) survives egress filtering
- cloudwatch tool: declare the aws_auth secret; sign with placeholders; region
  is the only real value (non-secret, read from env, defaults us-east-1)
- kubernetes: expose only AWS_REGION (non-secret, optional) to the tool-server
  sidecar — no AWS credentials in-process
- tests: cloudwatch client, aws_auth parser + renderer, sidecar (creds absent)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(cloudwatch): allow AWS SDK signed headers through the egress filter

aws_auth re-signs CloudWatch requests with the AWS SDK v4 signer, whose
signed-headers set includes the SDK's amz-sdk-request, amz-sdk-invocation-id,
and (for CloudWatch's query-JSON protocol) x-amzn-query-mode headers.
header_allowlist runs after aws_auth and was stripping them, so AWS rebuilt
the canonical request without them and rejected every call with
InvalidSignatureException.

Allow /^amz-sdk-.*$/ and /^x-amzn-.*$/ so the signed headers reach AWS. Pairs
with the /^x-amz-.*$/ allowance already added for the SigV4 headers.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(iron-proxy): bump base image to 0.42.0-rc.4 for the awsauth CONNECT fix

0.42.0-rc.4 is the first release containing ironsh/iron-proxy#167, which lets
the synthetic CONNECT through the tunnel transform-policy check so aws_auth
signs the post-MITM inner request instead of rejecting the CONNECT. Required
for the CloudWatch tool's aws_auth path.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants