Skip to content

feat(credentials): add sovereign cloud process (#8762) - #373

Open
Gabriel Pezé (gabriel-peze) wants to merge 2 commits into
mainfrom
issue/8762
Open

Gabriel Pezé (gabriel-peze) wants to merge 2 commits into
mainfrom
issue/8762

Conversation

@gabriel-peze

Copy link
Copy Markdown
Contributor

Proposed changes

  • Use the new inputs fields on OpenAEV to allow the access of sovereign clouds

Testing Instructions

  1. Run Prowler and/or Stratus and use the new fields with the last version of OpenAEV
  2. The inject should run with these new values

FYI : You can test with floci or another mocked cloud

Related issues

  • Relates #8762

@github-actions github-actions Bot added the filigran team Item from the Filigran team. label Oct 29, 2026
@gabriel-peze
Gabriel Pezé (gabriel-peze) marked this pull request as ready for review October 30, 2026 13:08
Copilot AI balanced review requested due to automatic review settings October 30, 2026 13:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Prowler ignores the Google endpoint and access-token overrides, while the Azure authority override incorrectly redirects managed-identity requests to the login server, causing authentication failures.

4 open issues
What changed in this PR

This PR extends credential resolution and materialization with sovereign and mock cloud settings intended for Prowler and Stratus integrations.

Changes:

  • Adds optional AWS, Azure, and GCP endpoint and authentication fields.
  • Exports cloud configuration variables and writes Azure CA certificates to temporary files.
  • Adds tests for parsing, environment mappings, sensitive-value redaction, and certificate cleanup.
File Description
test/​credential/​test_credential_resolved.py Tests new fields, defaults, certificate decoding, and redaction.
test/​credential/​test_credential_materializer.py Tests environment overrides and certificate file lifecycle.
pyoaev/​credential/​resolved.py Adds optional sovereign-cloud fields to credential models.
pyoaev/​credential/​materializer.py Maps new fields to environment variables and temporary CA files.

Review effort: Balanced

Comment thread pyoaev/credential/materializer.py Outdated
if not authority_host.endswith("/"):
authority_host += "/"
env["AZURE_AUTHORITY_HOST"] = authority_host
env["AZURE_POD_IDENTITY_AUTHORITY_HOST"] = authority_host

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking):
I agree with the bot above.
AZURE_POD_IDENTITY_AUTHORITY_HOST is not an Entra authority.

azure-identity uses it as the IMDS base URL, Please set only AZURE_AUTHORITY_HOST, or use a dedicated field

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5abb50e: only AZURE_AUTHORITY_HOST is set from azure_authority_host_uri now, AZURE_POD_IDENTITY_AUTHORITY_HOST is no longer touched.

I didn't add a dedicated field: a managed identity is the host's own identity, so the IMDS endpoint is taken from the host environment instead. Prowler already forwards the host managed-identity variables; Stratus only did it for the AWS instance identity, so I added the same list there (OpenAEV-Platform/injectors#489, AZURE_CLIENT_ID excluded). Our Floci setup already sets AZURE_POD_IDENTITY_AUTHORITY_HOST on the host for managed identity, so local tests keep working.

Tell me if you'd still prefer a dedicated field.

Comment on lines +269 to +271
env["GOOGLE_RESOURCE_MANAGER_CUSTOM_ENDPOINT"] = (
secret.gcp_custom_resource_manager_uri
)
Comment on lines +289 to +292
if secret.gcp_custom_token_uri:
env["GOOGLE_OAUTH2_TOKEN_URI_OVERRIDE"] = secret.gcp_custom_token_uri
if secret.gcp_custom_iam_uri:
env["GOOGLE_IAM_CUSTOM_ENDPOINT"] = secret.gcp_custom_iam_uri
if secret.gcp_custom_iam_uri:
env["GOOGLE_IAM_CUSTOM_ENDPOINT"] = secret.gcp_custom_iam_uri
if secret.gcp_custom_oauth_access_token:
env["GOOGLE_OAUTH_ACCESS_TOKEN"] = secret.gcp_custom_oauth_access_token

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tho work done on that PR.
Sadly i had to put it in request changes for a little thing, in materializer.py about azure-identity that could lead to missbehaviour.

Comment thread pyoaev/credential/materializer.py Outdated
if not authority_host.endswith("/"):
authority_host += "/"
env["AZURE_AUTHORITY_HOST"] = authority_host
env["AZURE_POD_IDENTITY_AUTHORITY_HOST"] = authority_host

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking):
I agree with the bot above.
AZURE_POD_IDENTITY_AUTHORITY_HOST is not an Entra authority.

azure-identity uses it as the IMDS base URL, Please set only AZURE_AUTHORITY_HOST, or use a dedicated field

Comment on lines +289 to +292
if secret.gcp_custom_token_uri:
env["GOOGLE_OAUTH2_TOKEN_URI_OVERRIDE"] = secret.gcp_custom_token_uri
if secret.gcp_custom_iam_uri:
env["GOOGLE_IAM_CUSTOM_ENDPOINT"] = secret.gcp_custom_iam_uri

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (blocking): Which consumer reads GOOGLE_OAUTH2_TOKEN_URI_OVERRIDE / GOOGLE_IAM_CUSTOM_ENDPOINT / GOOGLE_OAUTH_ACCESS_TOKEN?

google-auth ignores them (from_authorized_user_info hard-codes token_uri, "always overrides") and Prowler reads CLOUDSDK_AUTH_ACCESS_TOKEN.

Comment thread pyoaev/credential/materializer.py Outdated


def _aws_endpoint_env(endpoint_url: Optional[str]) -> Dict[str, str]:
# Sovereign or mocked cloud: the same endpoint serves the STS calls.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (non-blocking): AWS_ENDPOINT_URL sends every service to one host. That fits a mock, but not a real sovereign partition (per-service hosts), so the "Sovereign" in the comment is misleading. AWS_ENDPOINT_URL_STS with the same value is redundant too.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed on the comment, reworded in 5abb50e: one host for every service fits a mock or a proxy, real partitions (GovCloud, China) are reached through the region.

I'd keep AWS_ENDPOINT_URL_STS for now: our Floci setup notes that without it, Stratus may send sts:AssumeRole to real AWS. I'll check it again on Floci and drop it if it turns out to be redundant.

Comment on lines +208 to +209
if not authority_host.endswith("/"):
authority_host += "/"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (non-blocking): Validate the new URL fields at parse time (http(s) scheme, https for the Azure authority, no whitespace/userinfo) and raise InvalidResolvedSecretError, like _ini_value does.

Today "https://host " becomes "https://host /" and fails

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 5abb50e: the URL fields are validated at parse time in resolved.py (http/https scheme, https only for the Azure authority, host required, no whitespace, no userinfo) and raise InvalidResolvedSecretError without quoting the value. "https://host " is now rejected.

Comment thread pyoaev/credential/resolved.py Outdated
Comment on lines +127 to +130
# Java ``byte[]``, sent base64 encoded by the platform.
azure_requests_certificate: Optional[bytes] = _parsed_with(
_decode_base64, repr=False, default=None
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Is azure_requests_certificate guaranteed PEM on the platform side? A Java byte[] is often DER (getEncoded()). Written as .pem, OpenSSL fails to load it and Go silently ends up with an empty root pool. A cheap -----BEGIN check would fail early.

- azure: stop setting AZURE_POD_IDENTITY_AUTHORITY_HOST from the authority
  host; azure-identity reads it as the managed identity (IMDS) endpoint
- gcp: also export the access token as CLOUDSDK_AUTH_ACCESS_TOKEN and the
  project as GOOGLE_CLOUD_PROJECT, the variables Prowler reads
- validate endpoint URLs at parse time (http(s), https for the Azure
  authority, host required, no whitespace or userinfo)
- require a PEM Azure CA certificate; DER is rejected early
- aws: reword the endpoint comment (mock or proxy, not a sovereign partition)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

filigran team Item from the Filigran team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants