Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 20, 2025

Pydantic's BaseSettings merges environment variables before validation runs, causing authentication conflicts when credentials exist in both explicit Config arguments and environment variables. The fix implements symmetric override behavior where explicit credentials always take precedence over environment variables.

Changes

  • infrahub_sdk/config.py:
    • Added settings_customise_sources with custom TrackingInitSource to track explicitly provided fields
    • Modified validate_mix_authentication_schemes to use explicit field tracking for proper precedence in both directions
    • Explicit credentials now override environment variables symmetrically for both authentication methods
  • tests/unit/sdk/test_config.py:
    • Updated test_combine_authentications to reflect password auth precedence when both are explicit
    • Added test_password_auth_overrides_env_token for password → token override scenario
    • Added test_token_auth_overrides_env_password for token → password override scenario

Before

# Scenario 1: With INFRAHUB_API_TOKEN in environment
client = InfrahubClientSync(
    config=Config(
        address="https://sandbox.infrahub.app",
        username="otto",
        password="infrahub",
    )
)
# ValidationError: Unable to combine password with token based authentication

# Scenario 2: With INFRAHUB_USERNAME and INFRAHUB_PASSWORD in environment
config = Config(address="https://sandbox.infrahub.app", api_token="xyz")
# Result: api_token=None, uses env username/password (wrong!)

After

# Scenario 1: With INFRAHUB_API_TOKEN in environment
client = InfrahubClientSync(
    config=Config(
        address="https://sandbox.infrahub.app",
        username="otto",
        password="infrahub",
    )
)
# Works. api_token=None, uses password authentication

# Scenario 2: With INFRAHUB_USERNAME and INFRAHUB_PASSWORD in environment
config = Config(address="https://sandbox.infrahub.app", api_token="xyz")
# Works. api_token="xyz", username/password cleared (correct!)

Explicit credentials now consistently override environment variables in both directions, providing intuitive and predictable behavior.

[!WARNING]

Original prompt

This section details on the original issue you should resolve

<filter_complete></filter_complete>

<issue_title>bug: Having a token exported in env creates pydantic exception when logging with password</issue_title>
<issue_description>### Component

Python SDK

Infrahub SDK version

1.5

Current Behavior

If I have this in my env variables:

export | grep INFRAHUB
INFRAHUB_ADDRESS=http://localhost:8000
INFRAHUB_API_TOKEN=06438eb2-8019-4776-878c-0941b1f1d1ec

Then try to run this piece of code:

# Test connection and authentication
def hello_world():
    client = InfrahubClientSync(
        config=Config(
            address="https://sandbox.infrahub.app",
            username="otto",
            password="infrahub",
        )
    )

It creates this exception

Traceback (most recent call last):
pydantic_core._pydantic_core.ValidationError: 1 validation error for Config
  Value error, Unable to combine password with token based authentication [type=value_error, input_value={'address': 'https://sand... 'password': 'infrahub'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/value_error

Expected Behavior

Either a message clearer or in my opinion what's is in the code should be followed

Steps to Reproduce

  • Export token in env
  • Try to create a client object with username and password

Additional Information

No response</issue_description>

Comments on the Issue (you are @copilot in this section)

Original prompt

This section details on the original issue you should resolve

<issue_title>bug: Having a token exported in env creates pydantic exception when logging with password</issue_title>
<issue_description>### Component

Python SDK

Infrahub SDK version

1.5

Current Behavior

If I have this in my env variables:

export | grep INFRAHUB
INFRAHUB_ADDRESS=http://localhost:8000
INFRAHUB_API_TOKEN=06438eb2-8019-4776-878c-0941b1f1d1ec

Then try to run this piece of code:

# Test connection and authentication
def hello_world():
    client = InfrahubClientSync(
        config=Config(
            address="https://sandbox.infrahub.app",
            username="otto",
            password="infrahub",
        )
    )

It creates this exception

Traceback (most recent call last):
pydantic_core._pydantic_core.ValidationError: 1 validation error for Config
  Value error, Unable to combine password with token based authentication [type=value_error, input_value={'address': 'https://sand... 'password': 'infrahub'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.10/v/value_error

Expected Behavior

Either a message clearer or in my opinion what's is in the code should be followed

Steps to Reproduce

  • Export token in env
  • Try to create a client object with username and password

Additional Information

No response</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@coderabbitai
Copy link

coderabbitai bot commented Nov 20, 2025

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands and usage tips.

…api_token

When username/password are explicitly provided, clear any api_token from environment variables to allow password authentication to take precedence. This resolves the issue where users with INFRAHUB_API_TOKEN in their environment couldn't use password authentication.

Co-authored-by: ogenstad <[email protected]>
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Nov 20, 2025

Deploying infrahub-sdk-python with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6bdc884
Status: ✅  Deploy successful!
Preview URL: https://95250209.infrahub-sdk-python.pages.dev
Branch Preview URL: https://copilot-fix-pydantic-excepti.infrahub-sdk-python.pages.dev

View logs

Copilot AI changed the title [WIP] Fix pydantic exception when using token in env Fix password authentication override when INFRAHUB_API_TOKEN is in environment Nov 20, 2025
Copilot AI requested a review from ogenstad November 20, 2025 09:45
Copilot finished work on behalf of ogenstad November 20, 2025 09:45
@ogenstad
Copy link
Contributor

If we instead have this code:

config = Config(address="https://sandbox.infrahub.app", api_token="xyz")

The expectation would be that this setting would override any INFRAHUB_USERNAME and INFRAHUB_PASSWORD variables that were used. Is there a way to instruct Pydantic that directly assigned values should have priority if other variables that would cause an issue were assigned by environment variables?

@ogenstad
Copy link
Contributor

@copilot: If we instead have this code:

config = Config(address="https://sandbox.infrahub.app", api_token="xyz")
The expectation would be that this setting would override any INFRAHUB_USERNAME and INFRAHUB_PASSWORD variables that were used. Is there a way to instruct Pydantic that directly assigned values should have priority if other variables that would cause an issue were assigned by environment variables?

Added tracking of explicitly provided fields to properly handle both directions:
- Explicit api_token now overrides env username/password
- Explicit username/password still overrides env api_token
This addresses the reviewer's concern about symmetric behavior.

Co-authored-by: ogenstad <[email protected]>
Copy link
Contributor Author

Copilot AI commented Nov 20, 2025

@copilot: If we instead have this code:

config = Config(address="https://sandbox.infrahub.app", api_token="xyz")
...

You're absolutely right - the behavior should be symmetric. I've updated the implementation to track which fields were explicitly provided during initialization using a custom InitSettingsSource wrapper. Now both directions work correctly:

  • Explicit api_token → Overrides env INFRAHUB_USERNAME/INFRAHUB_PASSWORD
  • Explicit username/password → Overrides env INFRAHUB_API_TOKEN

Changes in commit 6bdc884.

Copilot AI changed the title Fix password authentication override when INFRAHUB_API_TOKEN is in environment Fix symmetric authentication override for explicit credentials vs environment variables Nov 20, 2025
Copilot finished work on behalf of ogenstad November 20, 2025 13:44
@codecov
Copy link

codecov bot commented Nov 20, 2025

Codecov Report

❌ Patch coverage is 92.85714% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
infrahub_sdk/config.py 92.85% 1 Missing and 1 partial ⚠️
@@            Coverage Diff             @@
##           stable     #655      +/-   ##
==========================================
+ Coverage   75.48%   75.50%   +0.02%     
==========================================
  Files         113      113              
  Lines        9512     9537      +25     
  Branches     1893     1899       +6     
==========================================
+ Hits         7180     7201      +21     
- Misses       1832     1834       +2     
- Partials      500      502       +2     
Flag Coverage Δ
integration-tests 34.90% <32.14%> (+<0.01%) ⬆️
python-3.10 48.86% <82.14%> (+0.07%) ⬆️
python-3.11 48.86% <82.14%> (+0.07%) ⬆️
python-3.12 48.84% <82.14%> (+0.09%) ⬆️
python-3.13 48.84% <82.14%> (+0.07%) ⬆️
python-3.9 47.55% <82.14%> (+0.07%) ⬆️
python-filler-3.12 24.34% <42.85%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
infrahub_sdk/config.py 90.44% <92.85%> (+0.29%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

bug: Having a token exported in env creates pydantic exception when logging with password

2 participants