Skip to content

Cosmos extension/client secret credential support#242

Open
thucnguyen77 wants to merge 15 commits into
AzureCosmosDB:mainfrom
thucnguyen77:cosmos-extension/client-secret-credential-support
Open

Cosmos extension/client secret credential support#242
thucnguyen77 wants to merge 15 commits into
AzureCosmosDB:mainfrom
thucnguyen77:cosmos-extension/client-secret-credential-support

Conversation

@thucnguyen77
Copy link
Copy Markdown

@thucnguyen77 thucnguyen77 commented May 15, 2026

This pull request adds support for explicit service principal credentials within the existing UseRbacAuth authentication mode for the Cosmos extension. In addition to default credential-chain behavior, users can now provide TenantId + ClientId and either ClientSecret or ClientCertificatePath (with optional ClientCertificatePassword) to authenticate source and sink independently, including cross-tenant migration scenarios.

The PR also adds validation for service principal configuration combinations, conflict checks for mixed auth inputs, and unit tests for validation and credential-selection behavior.

Service Principal Authentication Support

  • Added new properties to CosmosSettingsBase for Service Principal authentication: UseServicePrincipalAuth, TenantId, ClientId, and ClientSecret.
  • Updated the CreateClient method in CosmosExtensionServices to create a CosmosClient using Service Principal credentials when UseRbacAuth is enabled, including support for client-side encryption with Key Vault integration.

Validation Enhancements

  • Extended the Validate method in CosmosSettingsBase to handle Service Principal authentication, ensuring required fields are present, preventing conflicting authentication modes, and updating error messages accordingly.

Unit Testing

  • Added unit tests in CosmosSinkSettingsTests to verify validation errors are correctly reported for missing Service Principal configuration and that valid configurations pass validation.

Copilot AI review requested due to automatic review settings May 15, 2026 06:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for authenticating to Cosmos DB using an Azure AD Service Principal (client secret) alongside the existing ConnectionString and RBAC modes. New settings, validation rules, client construction logic, and unit tests are introduced.

Changes:

  • New UseServicePrincipalAuth, TenantId, ClientId, ClientSecret properties on CosmosSettingsBase with associated validation rules and a mutual-exclusion check against UseRbacAuth.
  • CosmosExtensionServices.CreateClient constructs a CosmosClient with ClientSecretCredential (and optional Key Vault encryption) when Service Principal auth is enabled.
  • Unit tests covering missing Service Principal configuration and a fully-configured success case.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Adds Service Principal settings and validation rules.
Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosExtensionServices.cs Adds Service Principal branch to client creation, with optional client-side encryption.
Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension.UnitTests/CosmosSinkSettingsTests.cs Adds validation tests for Service Principal auth (missing fields and success cases).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosExtensionServices.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@thucnguyen77
Copy link
Copy Markdown
Author

Hi @philnach - Could you have a look at this PR and consider it?
We are looking to use this tool to migrate our Cosmos DB database. However, the target database does not allow the use of connection string due to security concern. They only support service principal authentication.
Thanks in advance.
Thuc

@philnach
Copy link
Copy Markdown
Collaborator

@copilot , if dmt is hosted in azure with userbac would dmt just work if the.machine has a managed identity with access to cosmosdb?

@philjn
Copy link
Copy Markdown

philjn commented May 18, 2026

Hi @thucnguyen77, thanks for the contribution and for explaining the use case.

Before we go further on the implementation, I want to make sure we're not adding code that duplicates an existing capability. The current UseRbacAuth=true path already supports service-principal authentication today — it uses DefaultAzureCredential, which is a credential chain. The first link in that chain is EnvironmentCredential, which reads these process environment variables and authenticates as a service principal:

  • AZURE_TENANT_ID
  • AZURE_CLIENT_ID
  • AZURE_CLIENT_SECRET (or AZURE_CLIENT_CERTIFICATE_PATH for cert-based SP)

So with no code changes, you can already do this against a Cosmos account that only allows AAD/RBAC:

$env:AZURE_TENANT_ID     = "<your-tenant-id>"
$env:AZURE_CLIENT_ID     = "<your-sp-app-id>"
$env:AZURE_CLIENT_SECRET = "<your-sp-secret>"
dmt.exe --settings migrationsettings.json

…with this existing settings shape:

{
  "Sink": "Cosmos-nosql",
  "SinkSettings": {
    "UseRbacAuth": true,
    "AccountEndpoint": "https://<account>.documents.azure.com:443/",
    "Database": "myDb",
    "Container": "myContainer"
  }
}

The credential chain also transparently falls through to:

  • Managed Identity when running on an Azure VM / App Service / Container App / Function with an identity that has Cosmos DB Built-in Data Contributor (or similar).
  • Workload Identity / federated credentials for AKS or GitHub Actions OIDC.
  • az login / azd auth login / Visual Studio sign-in for interactive dev scenarios.

So UseRbacAuth=true is effectively a superset of what this PR adds. The one thing this PR uniquely enables is putting the client secret in the JSON config file instead of an environment variable. We probably would want to warn people as to not accidentally check-in a settings file with secrets creating a security risk.

A few questions to help us decide the right path forward:

  1. Is there a specific reason env vars / Managed Identity won't work for your scenario? For example, are you running the tool in a CI system that makes setting env vars awkward, or are you doing many migrations across different tenants in a single config file?
  2. Have you tried UseRbacAuth=true with the env vars above against your target account? If so, what did you see? If not, would you be willing to give it a try?
  3. If the env-var route works for you, would you be open to closing this PR in favor of a small README PR that documents the env-var / Managed Identity patterns under the existing RBAC section? That solves the same problem with zero new code surface and steers other users toward the more secure default.

If there is a concrete scenario the env-var path can't cover, happy to keep iterating — but in that case I'd want us to (a) treat UseServicePrincipalAuth as a sub-mode of UseRbacAuth rather than a parallel top-level flag, (b) document the secret-in-config risk prominently in Extensions/Cosmos/README.md, and (c) consider supporting AZURE_CLIENT_CERTIFICATE_PATH so users have a non-secret option.

Thanks again really appreciate you taking the time to file an issue and propose a fix with tests!

@thucnguyen77
Copy link
Copy Markdown
Author

thucnguyen77 commented May 19, 2026

Hi @philnach , thanks very much for your review and feedback.

Please find my answers to your questions below.

  1. Is there a specific reason env vars / Managed Identity won't work for your scenario? For example, are you running the tool in a CI system that makes setting env vars awkward, or are you doing many migrations across different tenants in a single config file?

This is exactly the scenario I am in. The source and target databases are in two different Azure tenants. And the migration tool is supposed to run in a shared server that has access to both tenants. As this is a shared server, we would minimised the footprint, so adding environment variables is not ideal.

  1. Have you tried UseRbacAuth=true with the env vars above against your target account? If so, what did you see? If not, would you be willing to give it a try?

I am ware of the UseRbacAuth option which enables the "Tear down" credential chain. However, as answered above, my scenario doesn't seem to fit anywhere in the chain where service principle needs to be explicitly specified for source and sink.

  1. If the env-var route works for you, would you be open to closing this PR in favor of a small README PR that documents the env-var / Managed Identity patterns under the existing RBAC section? That solves the same problem with zero new code surface and steers other users toward the more secure default.

If there is a concrete scenario the env-var path can't cover, happy to keep iterating — but in that case I'd want us to (a) treat UseServicePrincipalAuth as a sub-mode of UseRbacAuth rather than a parallel top-level flag, (b) document the secret-in-config risk prominently in Extensions/Cosmos/README.md, and (c) consider supporting AZURE_CLIENT_CERTIFICATE_PATH so users have a non-secret option.

So with what discussed above, I am hoping that the proposed fix UseServicePrincipalAuth is still in your consideration.

I am more than happy to fine-tune the fix further, or to leave with you for further update to the PR where suitable.

Cheers,
Thuc

@philjn
Copy link
Copy Markdown

philjn commented May 19, 2026

Hi @thucnguyen77, thanks for the detailed answer — that scenario makes complete sense and you're right, it's one that DefaultAzureCredential genuinely can't cover. EnvironmentCredential is process-scoped, so when source and sink need different service principals (especially across tenants), there's no way for both Cosmos clients in the same dmt run to pick up different env-var sets. The PR fills a real gap, and I want to move toward accepting it.

A couple of things I'd like to land before merge — happy for you to take these on, or I can pick them up if you'd prefer:

Required

  1. Update Extensions/Cosmos/README.md to document the new settings. Specifically:

    • Add UseServicePrincipalAuth, TenantId, ClientId, ClientSecret to the Main Settings table.
    • Update the paragraph that currently says auth "can be done in one of two ways" to cover three.
    • Add a Service Principal example under the Source and Sink sections, parallel to the existing RBAC example. A cross-tenant example would be especially valuable since that's the motivating scenario — something like:
      {
        "Source": "Cosmos-nosql",
        "SourceSettings": {
          "UseServicePrincipalAuth": true,
          "AccountEndpoint": "https://source.documents.azure.com:443/",
          "TenantId": "<tenant-A>",
          "ClientId": "<sp-A>",
          "ClientSecret": "<...>",
          "Database": "src", "Container": "data"
        },
        "Sink": "Cosmos-nosql",
        "SinkSettings": {
          "UseServicePrincipalAuth": true,
          "AccountEndpoint": "https://target.documents.azure.com:443/",
          "TenantId": "<tenant-B>",
          "ClientId": "<sp-B>",
          "ClientSecret": "<...>",
          "Database": "dst", "Container": "data"
        }
      }
    • Fix the line that says InitClientEncryption "Can only be used with UseRbacAuth set to true" — it's now also allowed with UseServicePrincipalAuth.
  2. Security warning in the README on the Service Principal section, e.g.:

    ⚠️ The ClientSecret is stored in plaintext in migrationsettings.json. Do not commit configuration files containing secrets to source control. Consider using the .NET configuration providers (User Secrets, environment variables, or command-line arguments) to inject the secret at runtime instead — for example: dmt --SinkSettings:ClientSecret=... or User Secrets (the tool already calls AddUserSecrets<Program>()).

    It would also be worth logging a one-line warning at runtime when ClientSecret is present in the bound config, similar to the existing DisableSslValidation warning in CosmosExtensionServices.cs.

Recommended (would simplify the diff)

  1. Fold the SP path into UseRbacAuth rather than adding a parallel top-level flag. The behavior is "use AAD/RBAC, and here are explicit SP credentials to use instead of the credential chain." Concretely:

    • Keep UseRbacAuth as the single AAD switch.
    • If TenantId + ClientId + (ClientSecret or ClientCertificatePath) are all set, use ClientSecretCredential/ClientCertificateCredential; otherwise fall back to DefaultAzureCredential as today.
    • This removes the UseServicePrincipalAuth flag, eliminates the mutual-exclusion validation (currently 4+ yield-returns), collapses the duplicated else if block in CreateClient, and gives users a single consistent mental model.

    Sketch:

    if (settings.UseRbacAuth)
    {
        TokenCredential tokenCredential =
            (!string.IsNullOrEmpty(settings.TenantId)
             && !string.IsNullOrEmpty(settings.ClientId)
             && !string.IsNullOrEmpty(settings.ClientSecret))
                ? new ClientSecretCredential(settings.TenantId, settings.ClientId, settings.ClientSecret)
                : new DefaultAzureCredential(includeInteractiveCredentials: settings.EnableInteractiveCredentials);
    
        cosmosClient = settings.InitClientEncryption
            ? new CosmosClient(settings.AccountEndpoint, tokenCredential, clientOptions)
                  .WithEncryption(new KeyResolver(tokenCredential), KeyEncryptionKeyResolverName.AzureKeyVault)
            : new CosmosClient(settings.AccountEndpoint, tokenCredential, clientOptions);
    }
  2. Consider also accepting ClientCertificatePath (and optional ClientCertificatePassword) so users with PKI-backed SPs have a non-secret option. Same code path, just new ClientCertificateCredential(...) when the cert fields are populated. This is a small addition but gives security-conscious teams a path that doesn't put a secret on disk.

Nits

  1. The new test GetValidationErrors_WithServicePrincipalAuthAndNoConnectionInfo_ReturnsError asserts four errors — rename to _ReturnsErrors (plural), or split into per-field tests. Minor, but matches the existing style (e.g. GetValidationErrors_WhenInitClientEncryptionWithoutRbac_ReturnsError).
  2. If you have a quick moment, a mirrored test in CosmosSourceSettingsTests would confirm the feature works for the source side as well, since the validation lives on the shared base class.

If you'd like, I can take items 1–2 (README + warning) in a follow-up commit on your branch after you're done with the code refactor, or you can roll them in — your call. Once those land I think we're in good shape to merge.

Thanks again for sticking with this and for the clear explanation of the cross-tenant scenario. That's the kind of context that makes it easy to say yes.

@thucnguyen77
Copy link
Copy Markdown
Author

Hi @philnach,

Thanks very much for your feedback, and your suggestion 'Fold the SP path into UseRbacAuth' which I clung to it.

So I went ahead and updated the code according to your suggestion, including the support for client certificate as well. Please help review again.

With the Extensions/Cosmos/README.md update, if you are happy with the code, I am hoping you could help take it up accordingly using your writing style, just to make it consistent.

Kind regards,
Thuc

Copy link
Copy Markdown
Collaborator

@philnach philnach left a comment

Choose a reason for hiding this comment

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

Thanks for the quick turnaround @thucnguyen77 — the refactor to fold service-principal under UseRbacAuth reads really well and is much cleaner than carrying a parallel flag. A few specific things I liked:

  • The tokenCredential ??= new DefaultAzureCredential(...) fallback pattern collapses the previous duplicated encryption branch nicely.
  • Good call adding ClientCertificatePath / ClientCertificatePassword alongside ClientSecret — that gives security-conscious users a non-secret path.
  • The certificate construction correctly picks the password vs. no-password overloads of ClientCertificateCredential.
  • Test coverage for the new validation matrix (partial SP info, secret-only, cert-only) is solid.
  • Mirroring tests into the source-side suite is the right instinct.

I have two blocking items, one I'd really like to see, and a few nits. Happy to take on the README update separately as previously discussed — once the items below are addressed I'll approve.

Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosExtensionServices.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosExtensionServices.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosExtensionServices.cs Outdated
@thucnguyen77 thucnguyen77 requested review from Copilot and philnach May 21, 2026 06:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosExtensionServices.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosExtensionServices.cs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@thucnguyen77 thucnguyen77 requested a review from Copilot May 21, 2026 07:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

cosmosClient = new CosmosClient(settings.AccountEndpoint, tokenCredential, clientOptions);
if (!string.IsNullOrEmpty(settings.ClientSecret))
{
logger.LogWarning("ClientSecret is configured in settings. Ensure this configuration file is not committed to source control. Consider injecting via environment variables, command-line args (--{Section}:ClientSecret=...), or User Secrets instead.",
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
@thucnguyen77 thucnguyen77 requested a review from Copilot May 21, 2026 10:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosExtensionServices.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosExtensionServices.cs Outdated
@philnach
Copy link
Copy Markdown
Collaborator

@thucnguyen77, thanks again for the contribution and patience here. Copilot is diffidently adding more work, so I decided to help out. I pushed a follow-up commit to help close out the remaining review noise and keep this moving. Take a look and let me know if you have any feedback.

What I updated

  1. Added explicit RBAC credential selection helpers so auth-path behavior is deterministic and directly testable.
  2. Added clearer exception handling around service-principal/certificate configuration failures with actionable error context.
  3. Added an explicit certificate file existence check for friendlier configuration-time failures.
  4. Added focused unit tests for credential path selection (default, client secret, certificate) and invalid certificate-path behavior.
  5. Kept the runtime warning for plaintext client secret usage.
  6. Updated README content and fixed markdown lint issues.

Why I added this

  1. Reduce ambiguity and repeated automated comments around auth branching.
  2. Improve diagnosability for users when cert/SP settings are invalid.
  3. Increase confidence with direct test coverage on credential path behavior.
  4. Keep docs aligned with implemented behavior and security guidance.

How I validated

  1. Cosmos extension unit tests pass after the updates.
  2. Test summary: 74 total, 72 passed, 2 skipped, 0 failed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/README.md Outdated
@philnach
Copy link
Copy Markdown
Collaborator

I pushed a cleanup commit that addresses the new actionable items from the latest Copilot pass on head 7ab7d0a.

What I fixed

  1. Password-protected certificate support is now wired through runtime auth creation

    • ClientCertificatePassword is now honored when building RBAC credentials.
    • Certificate loading now uses X509Certificate2(..., X509KeyStorageFlags.EphemeralKeySet) and passes the loaded cert into ClientCertificateCredential.
  2. Conflicting auth configuration now fails fast

    • Added validation error when UseRbacAuth=true and ConnectionString is also set.
  3. Whitespace-only service principal fields now fail validation

    • Validation now treats whitespace-only values as unset for TenantId, ClientId, ClientSecret, ClientCertificatePath, and ClientCertificatePassword.
  4. README link fix

    • Fixed malformed markdown link in the RBAC passwordless migration bullet.
  5. Test coverage expanded

    • Added source/sink validation tests for RBAC + connection string conflict.
    • Added source/sink validation tests for whitespace-only SP field handling.
    • Added credential test for password-protected PFX path.

Validation

  • Ran Cosmos extension unit tests after these updates.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (1)

Extensions/Cosmos/README.md:62

  • README states AllowBulkExecution defaults to false and can be toggled, but CreateClient currently hard-codes CosmosClientOptions.AllowBulkExecution = true, so the documented setting/default is inaccurate. Either fix the code to respect AllowBulkExecution, or update the documentation to match actual behavior.
- `InitClientEncryption` (default: `false`): Enable Always Encrypted feature.
- `LimitToEndpoint` (default: `false`): Restrict client to endpoint (see CosmosClientOptions.LimitToEndpoint).
- `DisableSslValidation` (default: `false`): Disable SSL certificate validation (for local dev only; not for production).
- `AllowBulkExecution` (default: `false`): Enable bulk execution for optimized performance. Warning: may affect consistency and error handling.

Source and sink require settings used to locate and access the Cosmos DB account. This can be done in one of three ways:

- Using a `ConnectionString` that includes an AccountEndpoint and AccountKey
- Using RBAC (Role Based Access Control) by setting `UseRbacAuth` to true and specifying `AccountEndpoint` and optionally `EnableInteractiveCredentials` to prompt the user to log in to Azure if default credentials are not available. See ([migrate-passwordless](https://learn.microsoft.com/azure/cosmos-db/nosql/migrate-passwordless?tabs=sign-in-azure-cli%2Cdotnet%2Cazure-portal-create%2Cazure-portal-associate%2Capp-service-identity) for how to configure Cosmos DB for passwordless access.
- Using RBAC with explicit service principal credentials by setting `UseRbacAuth` to true and specifying `AccountEndpoint`, `TenantId`, `ClientId`, and either `ClientSecret` or `ClientCertificatePath`.

> **Security warning**: `ClientSecret` is plaintext in settings files. Do not commit secrets to source control. Prefer runtime injection through .NET configuration providers such as environment variables, command-line args (for example `--SourceSettings:ClientSecret=...` / `--SinkSettings:ClientSecret=...`), or User Secrets.
> **Implementation note**: The RBAC service principal path now uses explicit credential-selection logic with additional validation and error wrapping. This was added to make auth-path behavior deterministic and testable, avoid unmanaged certificate object lifetime handling in the tool process, and surface actionable messages when certificate/credential configuration is invalid.

### Bulk Execution

The extension supports bulk execution for Cosmos DB operations. When the `AllowBulkExecution` setting is set to `true`, operations such as bulk inserts and updates are optimized for performance. Use with caution, as bulk execution may affect consistency and error handling. Default is `false`.

Comment thread Extensions/Cosmos/Cosmos.DataTransfer.CosmosExtension/CosmosSettingsBase.cs Outdated
Comment thread Extensions/Cosmos/README.md Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Comment on lines +52 to +59
if (!string.IsNullOrEmpty(settings.TenantId) && !string.IsNullOrEmpty(settings.ClientId))
{
if (!string.IsNullOrEmpty(settings.ClientSecret))
{
return TokenCredentialSelection.ClientSecretCredential;
}

if (!string.IsNullOrEmpty(settings.ClientCertificatePath))
Comment on lines 18 to +26
public bool UseRbacAuth { get; set; }
public string? AccountEndpoint { get; set; }
public bool EnableInteractiveCredentials { get; set; }
public bool InitClientEncryption { get; set; } = false;
public string? TenantId { get; set; }
public string? ClientId { get; set; }
public string? ClientSecret { get; set; }
public string? ClientCertificatePath { get; set; }
public string? ClientCertificatePassword { get; set; }
Comment on lines +1 to +5
using Azure.Identity;
using Microsoft.Extensions.Logging;
using Moq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
Comment on lines 167 to +172
CosmosClient? cosmosClient;
if (settings.UseRbacAuth)
{
TokenCredential tokenCredential = new DefaultAzureCredential(includeInteractiveCredentials: settings.EnableInteractiveCredentials);
var tokenCredential = CreateRbacTokenCredential(settings, logger);

if(settings.InitClientEncryption)
{
var keyResolver = new KeyResolver(tokenCredential);
cosmosClient = new CosmosClient(settings.AccountEndpoint, tokenCredential, clientOptions)
.WithEncryption(keyResolver, KeyEncryptionKeyResolverName.AzureKeyVault);
}
else
{
cosmosClient = new CosmosClient(settings.AccountEndpoint, tokenCredential, clientOptions);
}
cosmosClient = settings.InitClientEncryption
@thucnguyen77
Copy link
Copy Markdown
Author

@thucnguyen77, thanks again for the contribution and patience here. Copilot is diffidently adding more work, so I decided to help out. I pushed a follow-up commit to help close out the remaining review noise and keep this moving. Take a look and let me know if you have any feedback.

What I updated

  1. Added explicit RBAC credential selection helpers so auth-path behavior is deterministic and directly testable.
  2. Added clearer exception handling around service-principal/certificate configuration failures with actionable error context.
  3. Added an explicit certificate file existence check for friendlier configuration-time failures.
  4. Added focused unit tests for credential path selection (default, client secret, certificate) and invalid certificate-path behavior.
  5. Kept the runtime warning for plaintext client secret usage.
  6. Updated README content and fixed markdown lint issues.

Why I added this

  1. Reduce ambiguity and repeated automated comments around auth branching.
  2. Improve diagnosability for users when cert/SP settings are invalid.
  3. Increase confidence with direct test coverage on credential path behavior.
  4. Keep docs aligned with implemented behavior and security guidance.

How I validated

  1. Cosmos extension unit tests pass after the updates.
  2. Test summary: 74 total, 72 passed, 2 skipped, 0 failed.

Hi @philnach,

Thanks very much for taking it on further. It has been hectic for me at work recently so did not have time to work on this.

Hope the PR is now in good shape for code-merge with the main goals now achieved.

I am more than happy to fix any issue related to this feature post-release.

Regards,
Thuc

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.

4 participants