Skip to content
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
829e3a5
add Azure SP option to repo UI
allanyung Nov 14, 2025
e4d1d81
Add functions for retrieving and caching git creds with Azure Service…
allanyung Nov 14, 2025
68e5388
add Azure Service Principal support to repository access queries
allanyung Nov 17, 2025
0789119
Fix repo connect UI bug for Azure SP
allanyung Nov 17, 2025
80448af
HasCredentials check should also return true when Azure SP cred is pr…
allanyung Nov 17, 2025
bb0d048
update CLI to support adding repos/creds with Azure Service Principal
allanyung Nov 17, 2025
92ee406
update documentation for Azure Service Principal repo auth
allanyung Nov 17, 2025
2e298cd
Fix failing CI checks
allanyung Nov 18, 2025
31e22b0
add proxy configuration to Azure Service Principal HTTP client
allanyung Nov 18, 2025
2ca0adc
Fix more linting
allanyung Nov 18, 2025
062cd52
revert reordering of resources.
allanyung Nov 18, 2025
323eb94
Retrigger CI pipeline
allanyung Nov 18, 2025
32445d1
Retrigger CI pipeline
allanyung Nov 18, 2025
1c0d677
Add some tests to improve code coverage
allanyung Nov 19, 2025
4d8d79b
No need to wrap the HTTP client
allanyung Nov 20, 2025
4652f32
Use Wither pattern to improve inelegant function definition
allanyung Nov 20, 2025
891498d
remove incorrect documentation
allanyung Nov 21, 2025
f36d1d1
Retrigger CI pipeline
allanyung Nov 21, 2025
f81c02d
Rerun codegen after rebase
allanyung Dec 11, 2025
a0bae02
Move checks to Wither functions as per PR feedback
allanyung Dec 15, 2025
2c27232
Retrigger CI pipeline
allanyung Dec 15, 2025
58a85aa
Merge branch 'master' into support-azure-service-principal-repo-auth
todaywasawesome Dec 18, 2025
a1bb2b0
Merge branch 'master' into support-azure-service-principal-repo-auth
allanyung Dec 19, 2025
337e55b
cap AzureServicePrincipalCredsExpirationDuration to prevent potential…
allanyung Dec 19, 2025
e7e4f27
Merge branch 'master' into support-azure-service-principal-repo-auth
allanyung Jan 6, 2026
4916053
Merge branch 'master' into support-azure-service-principal-repo-auth
allanyung Jan 8, 2026
156ab46
Merge branch 'master' into support-azure-service-principal-repo-auth
allanyung Jan 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions assets/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 35 additions & 21 deletions cmd/argocd/commands/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {

# Add a private Git repository on Google Cloud Sources via GCP service account credentials
argocd repo add https://source.developers.google.com/p/my-google-cloud-project/r/my-repo --gcp-service-account-key-path service-account-key.json

# Add a private Git repository on Azure Devops via Azure Service Principal credentials
argocd repo add https://dev.azure.com/my-devops-organization/my-devops-project/_git/my-devops-repo --azure-service-principal-client-id 12345678-1234-1234-1234-123456789012 --azure-service-principal-client-secret test --azure-service-principal-tenant-id 12345678-1234-1234-1234-123456789012

# Add a private Git repository on Azure Devops via Azure Service Principal credentials when not using default Azure public cloud
argocd repo add https://dev.azure.com/my-devops-organization/my-devops-project/_git/my-devops-repo --azure-service-principal-client-id 12345678-1234-1234-1234-123456789012 --azure-service-principal-client-secret test --azure-service-principal-tenant-id 12345678-1234-1234-1234-123456789012 --azure-active-directory-endpoint https://login.microsoftonline.de
`

command := &cobra.Command{
Expand Down Expand Up @@ -191,6 +197,10 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
repoOpts.Repo.NoProxy = repoOpts.NoProxy
repoOpts.Repo.ForceHttpBasicAuth = repoOpts.ForceHttpBasicAuth
repoOpts.Repo.UseAzureWorkloadIdentity = repoOpts.UseAzureWorkloadIdentity
repoOpts.Repo.AzureServicePrincipalTenantId = repoOpts.AzureServicePrincipalTenantId
repoOpts.Repo.AzureServicePrincipalClientId = repoOpts.AzureServicePrincipalClientId
repoOpts.Repo.AzureServicePrincipalClientSecret = repoOpts.AzureServicePrincipalClientSecret
repoOpts.Repo.AzureActiveDirectoryEndpoint = repoOpts.AzureActiveDirectoryEndpoint
repoOpts.Repo.Depth = repoOpts.Depth

if repoOpts.Repo.Type == "helm" && repoOpts.Repo.Name == "" {
Expand Down Expand Up @@ -225,27 +235,31 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
// are high that we do not have the given URL pointing to a valid Git
// repo anyway.
repoAccessReq := repositorypkg.RepoAccessQuery{
Repo: repoOpts.Repo.Repo,
Type: repoOpts.Repo.Type,
Name: repoOpts.Repo.Name,
Username: repoOpts.Repo.Username,
Password: repoOpts.Repo.Password,
BearerToken: repoOpts.Repo.BearerToken,
SshPrivateKey: repoOpts.Repo.SSHPrivateKey,
TlsClientCertData: repoOpts.Repo.TLSClientCertData,
TlsClientCertKey: repoOpts.Repo.TLSClientCertKey,
Insecure: repoOpts.Repo.IsInsecure(),
EnableOci: repoOpts.Repo.EnableOCI,
GithubAppPrivateKey: repoOpts.Repo.GithubAppPrivateKey,
GithubAppID: repoOpts.Repo.GithubAppId,
GithubAppInstallationID: repoOpts.Repo.GithubAppInstallationId,
GithubAppEnterpriseBaseUrl: repoOpts.Repo.GitHubAppEnterpriseBaseURL,
Proxy: repoOpts.Proxy,
Project: repoOpts.Repo.Project,
GcpServiceAccountKey: repoOpts.Repo.GCPServiceAccountKey,
ForceHttpBasicAuth: repoOpts.Repo.ForceHttpBasicAuth,
UseAzureWorkloadIdentity: repoOpts.Repo.UseAzureWorkloadIdentity,
InsecureOciForceHttp: repoOpts.Repo.InsecureOCIForceHttp,
Repo: repoOpts.Repo.Repo,
Type: repoOpts.Repo.Type,
Name: repoOpts.Repo.Name,
Username: repoOpts.Repo.Username,
Password: repoOpts.Repo.Password,
BearerToken: repoOpts.Repo.BearerToken,
SshPrivateKey: repoOpts.Repo.SSHPrivateKey,
TlsClientCertData: repoOpts.Repo.TLSClientCertData,
TlsClientCertKey: repoOpts.Repo.TLSClientCertKey,
Insecure: repoOpts.Repo.IsInsecure(),
EnableOci: repoOpts.Repo.EnableOCI,
GithubAppPrivateKey: repoOpts.Repo.GithubAppPrivateKey,
GithubAppID: repoOpts.Repo.GithubAppId,
GithubAppInstallationID: repoOpts.Repo.GithubAppInstallationId,
GithubAppEnterpriseBaseUrl: repoOpts.Repo.GitHubAppEnterpriseBaseURL,
Proxy: repoOpts.Proxy,
Project: repoOpts.Repo.Project,
GcpServiceAccountKey: repoOpts.Repo.GCPServiceAccountKey,
ForceHttpBasicAuth: repoOpts.Repo.ForceHttpBasicAuth,
UseAzureWorkloadIdentity: repoOpts.Repo.UseAzureWorkloadIdentity,
InsecureOciForceHttp: repoOpts.Repo.InsecureOCIForceHttp,
AzureServicePrincipalTenantId: repoOpts.Repo.AzureServicePrincipalTenantId,
AzureServicePrincipalClientId: repoOpts.Repo.AzureServicePrincipalClientId,
AzureServicePrincipalClientSecret: repoOpts.Repo.AzureServicePrincipalClientSecret,
AzureActiveDirectoryEndpoint: repoOpts.Repo.AzureActiveDirectoryEndpoint,
}
_, err = repoIf.ValidateAccess(ctx, &repoAccessReq)
errors.CheckError(err)
Expand Down
10 changes: 10 additions & 0 deletions cmd/argocd/commands/repocreds.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma

# Add credentials with GCP credentials for all repositories under https://source.developers.google.com/p/my-google-cloud-project/r/
argocd repocreds add https://source.developers.google.com/p/my-google-cloud-project/r/ --gcp-service-account-key-path service-account-key.json

# Add credentials with Azure Service Principal to use for all repositories under https://dev.azure.com/my-devops-organization
argocd repocreds add https://dev.azure.com/my-devops-organization --azure-service-principal-client-id 12345678-1234-1234-1234-123456789012 --azure-service-principal-client-secret test --azure-service-principal-tenant-id 12345678-1234-1234-1234-123456789012

# Add credentials with Azure Service Principal to use for all repositories under https://dev.azure.com/my-devops-organization when not using default Azure public cloud
argocd repocreds add https://dev.azure.com/my-devops-organization --azure-service-principal-client-id 12345678-1234-1234-1234-123456789012 --azure-service-principal-client-secret test --azure-service-principal-tenant-id 12345678-1234-1234-1234-123456789012 --azure-active-directory-endpoint https://login.microsoftonline.de
`

command := &cobra.Command{
Expand Down Expand Up @@ -201,6 +207,10 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma
command.Flags().BoolVar(&repo.ForceHttpBasicAuth, "force-http-basic-auth", false, "whether to force basic auth when connecting via HTTP")
command.Flags().BoolVar(&repo.UseAzureWorkloadIdentity, "use-azure-workload-identity", false, "whether to use azure workload identity for authentication")
command.Flags().StringVar(&repo.Proxy, "proxy-url", "", "If provided, this URL will be used to connect via proxy")
command.Flags().StringVar(&repo.AzureServicePrincipalClientId, "azure-service-principal-client-id", "", "client id of the Azure Service Principal")
command.Flags().StringVar(&repo.AzureServicePrincipalClientSecret, "azure-service-principal-client-secret", "", "client secret of the Azure Service Principal")
command.Flags().StringVar(&repo.AzureServicePrincipalTenantId, "azure-service-principal-tenant-id", "", "tenant id of the Azure Service Principal")
command.Flags().StringVar(&repo.AzureActiveDirectoryEndpoint, "azure-active-directory-endpoint", "", "Active Directory endpoint when not using default Azure public cloud (e.g. https://login.microsoftonline.de)")
return command
}

Expand Down
48 changes: 28 additions & 20 deletions cmd/util/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,30 @@ import (
)

type RepoOptions struct {
Repo appsv1.Repository
Upsert bool
SshPrivateKeyPath string //nolint:revive //FIXME(var-naming)
InsecureOCIForceHTTP bool
InsecureIgnoreHostKey bool
InsecureSkipServerVerification bool
TlsClientCertPath string //nolint:revive //FIXME(var-naming)
TlsClientCertKeyPath string //nolint:revive //FIXME(var-naming)
EnableLfs bool
EnableOci bool
GithubAppId int64
GithubAppInstallationId int64
GithubAppPrivateKeyPath string
GitHubAppEnterpriseBaseURL string
Proxy string
NoProxy string
GCPServiceAccountKeyPath string
ForceHttpBasicAuth bool //nolint:revive //FIXME(var-naming)
UseAzureWorkloadIdentity bool
Depth int64
Repo appsv1.Repository
Upsert bool
SshPrivateKeyPath string //nolint:revive //FIXME(var-naming)
InsecureOCIForceHTTP bool
InsecureIgnoreHostKey bool
InsecureSkipServerVerification bool
TlsClientCertPath string //nolint:revive //FIXME(var-naming)
TlsClientCertKeyPath string //nolint:revive //FIXME(var-naming)
EnableLfs bool
EnableOci bool
GithubAppId int64
GithubAppInstallationId int64
GithubAppPrivateKeyPath string
GitHubAppEnterpriseBaseURL string
Proxy string
NoProxy string
GCPServiceAccountKeyPath string
ForceHttpBasicAuth bool //nolint:revive //FIXME(var-naming)
UseAzureWorkloadIdentity bool
Depth int64
AzureServicePrincipalTenantId string
AzureServicePrincipalClientId string
AzureServicePrincipalClientSecret string
AzureActiveDirectoryEndpoint string
}

func AddRepoFlags(command *cobra.Command, opts *RepoOptions) {
Expand Down Expand Up @@ -55,4 +59,8 @@ func AddRepoFlags(command *cobra.Command, opts *RepoOptions) {
command.Flags().BoolVar(&opts.UseAzureWorkloadIdentity, "use-azure-workload-identity", false, "whether to use azure workload identity for authentication")
command.Flags().BoolVar(&opts.InsecureOCIForceHTTP, "insecure-oci-force-http", false, "Use http when accessing an OCI repository")
command.Flags().Int64Var(&opts.Depth, "depth", 0, "Specify a custom depth for git clone operations. Unless specified, a full clone is performed using the depth of 0")
command.Flags().StringVar(&opts.AzureServicePrincipalTenantId, "azure-service-principal-tenant-id", "", "tenant id of the Azure Service Principal")
command.Flags().StringVar(&opts.AzureServicePrincipalClientId, "azure-service-principal-client-id", "", "client id of the Azure Service Principal")
command.Flags().StringVar(&opts.AzureServicePrincipalClientSecret, "azure-service-principal-client-secret", "", "client secret of the Azure Service Principal")
command.Flags().StringVar(&opts.AzureActiveDirectoryEndpoint, "azure-active-directory-endpoint", "", "Active Directory endpoint when not using default Azure public cloud (e.g. https://login.microsoftonline.de)")
}
4 changes: 4 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ const (
ChangePasswordSSOTokenMaxAge = time.Minute * 5
// GithubAppCredsExpirationDuration is the default time used to cache the GitHub app credentials
GithubAppCredsExpirationDuration = time.Minute * 60
// AzureServicePrincipalCredsExpirationDuration is the default time used to cache the Azure service principal credentials - SP tokens are valid for 60 minutes, so cache for 55 minutes to avoid issues with token expiration
AzureServicePrincipalCredsExpirationDuration = time.Minute * 55

// PasswordPatten is the default password patten
PasswordPatten = `^.{8,32}$`
Expand Down Expand Up @@ -284,6 +286,8 @@ const (
EnvEnableGRPCTimeHistogramEnv = "ARGOCD_ENABLE_GRPC_TIME_HISTOGRAM"
// EnvGithubAppCredsExpirationDuration controls the caching of Github app credentials. This value is in minutes (default: 60)
EnvGithubAppCredsExpirationDuration = "ARGOCD_GITHUB_APP_CREDS_EXPIRATION_DURATION"
// EnvAzureServicePrincipalCredsExpirationDuration controls the caching of Azure service principal credentials. This value is in minutes (default: 55)
EnvAzureServicePrincipalCredsExpirationDuration = "ARGOCD_AZURE_SERVICE_PRINCIPAL_CREDS_EXPIRATION_DURATION"
// EnvHelmIndexCacheDuration controls how the helm repository index file is cached for (default: 0)
EnvHelmIndexCacheDuration = "ARGOCD_HELM_INDEX_CACHE_DURATION"
// EnvAppConfigPath allows to override the configuration path for repo server
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 34 additions & 1 deletion docs/operator-manual/declarative-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ spec:

Repository details are stored in secrets. To configure a repo, create a secret which contains repository details.
Consider using [bitnami-labs/sealed-secrets](https://github.com/bitnami-labs/sealed-secrets) to store an encrypted secret definition as a Kubernetes manifest.
Each repository must have a `url` field and, depending on whether you connect using HTTPS, SSH, or GitHub App, `username` and `password` (for HTTPS), `sshPrivateKey` (for SSH), or `githubAppPrivateKey` (for GitHub App).
Each repository must have a `url` field and, depending on whether you connect using HTTPS, SSH, GitHub App or Azure Service Principal, `username` and `password` (for HTTPS), `sshPrivateKey` (for SSH), `githubAppPrivateKey` (for GitHub App) or `azureServicePrincipalClientSecret` (for Azure Service Principal).
Credentials can be scoped to a project using the optional `project` field. When omitted, the credential will be used as the default for all projects without a scoped credential.

> [!WARNING]
Expand Down Expand Up @@ -296,6 +296,39 @@ Example for Azure Container Registry/ Azure Devops repositories using Azure work

Refer to [Azure Container Registry/Azure Repos using Azure Workload Identity](../user-guide/private-repositories.md#azure-container-registryazure-repos-using-azure-workload-identity)

Example for Azure Service Principal:

```yaml
apiVersion: v1
kind: Secret
metadata:
name: service-principal-for-azure-public-cloud
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
type: git
url: https://dev.azure.com/my-devops-organization/my-devops-project/_git/my-devops-repo
azureServicePrincipalClientId: 12345678-1234-1234-1234-123456789012
azureServicePrincipalTenantId: 12345678-1234-1234-1234-123456789012
azureServicePrincipalClientSecret: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
---
apiVersion: v1
kind: Secret
metadata:
name: service-principal-for-azure-other-cloud
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
type: git
url: https://dev.azure.com/my-devops-organization/my-devops-project/_git/my-devops-repo
azureActiveDirectoryEndpoint: https://login.microsoftonline.de
azureServicePrincipalClientId: 12345678-1234-1234-1234-123456789012
azureServicePrincipalTenantId: 12345678-1234-1234-1234-123456789012
azureServicePrincipalClientSecret: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

### Repository Credentials

If you want to use the same credentials for multiple repositories, you can configure credential templates. Credential templates can carry the same credentials information as repositories.
Expand Down
Loading
Loading