mirror of
https://github.com/argoproj/argo-cd
synced 2026-04-21 08:57:17 +00:00
feat: Support Azure Service Principal authentication for Azure DevOps repositories (#25324)
Signed-off-by: Allan Yung <allan.yung@bbdsoftware.com> Co-authored-by: Dan Garfield <dan.garfield@octopus.com>
This commit is contained in:
parent
6bf97ec1fd
commit
9a19735918
27 changed files with 2414 additions and 1107 deletions
80
assets/swagger.json
generated
80
assets/swagger.json
generated
|
|
@ -4039,6 +4039,30 @@
|
|||
"description": "Whether https should be disabled for an OCI repo.",
|
||||
"name": "insecureOciForceHttp",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Azure Service Principal Client ID.",
|
||||
"name": "azureServicePrincipalClientId",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Azure Service Principal Client Secret.",
|
||||
"name": "azureServicePrincipalClientSecret",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Azure Service Principal Tenant ID.",
|
||||
"name": "azureServicePrincipalTenantId",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Azure Active Directory Endpoint.",
|
||||
"name": "azureActiveDirectoryEndpoint",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
|
@ -4946,6 +4970,30 @@
|
|||
"description": "Whether https should be disabled for an OCI repo.",
|
||||
"name": "insecureOciForceHttp",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Azure Service Principal Client ID.",
|
||||
"name": "azureServicePrincipalClientId",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Azure Service Principal Client Secret.",
|
||||
"name": "azureServicePrincipalClientSecret",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Azure Service Principal Tenant ID.",
|
||||
"name": "azureServicePrincipalTenantId",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Azure Active Directory Endpoint.",
|
||||
"name": "azureActiveDirectoryEndpoint",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
|
@ -9519,6 +9567,22 @@
|
|||
"type": "object",
|
||||
"title": "RepoCreds holds the definition for repository credentials",
|
||||
"properties": {
|
||||
"azureActiveDirectoryEndpoint": {
|
||||
"type": "string",
|
||||
"title": "AzureActiveDirectoryEndpoint specifies the Azure Active Directory endpoint used for Service Principal authentication. If empty will default to https://login.microsoftonline.com"
|
||||
},
|
||||
"azureServicePrincipalClientId": {
|
||||
"type": "string",
|
||||
"title": "AzureServicePrincipalClientId specifies the client ID of the Azure Service Principal used to access the repo"
|
||||
},
|
||||
"azureServicePrincipalClientSecret": {
|
||||
"type": "string",
|
||||
"title": "AzureServicePrincipalClientSecret specifies the client secret of the Azure Service Principal used to access the repo"
|
||||
},
|
||||
"azureServicePrincipalTenantId": {
|
||||
"type": "string",
|
||||
"title": "AzureServicePrincipalTenantId specifies the tenant ID of the Azure Service Principal used to access the repo"
|
||||
},
|
||||
"bearerToken": {
|
||||
"type": "string",
|
||||
"title": "BearerToken contains the bearer token used for Git BitBucket Data Center auth at the repo server"
|
||||
|
|
@ -9618,6 +9682,22 @@
|
|||
"type": "object",
|
||||
"title": "Repository is a repository holding application configurations",
|
||||
"properties": {
|
||||
"azureActiveDirectoryEndpoint": {
|
||||
"type": "string",
|
||||
"title": "AzureActiveDirectoryEndpoint specifies the Azure Active Directory endpoint used for Service Principal authentication. If empty will default to https://login.microsoftonline.com"
|
||||
},
|
||||
"azureServicePrincipalClientId": {
|
||||
"type": "string",
|
||||
"title": "AzureServicePrincipalClientId specifies the client ID of the Azure Service Principal used to access the repo"
|
||||
},
|
||||
"azureServicePrincipalClientSecret": {
|
||||
"type": "string",
|
||||
"title": "AzureServicePrincipalClientSecret specifies the client secret of the Azure Service Principal used to access the repo"
|
||||
},
|
||||
"azureServicePrincipalTenantId": {
|
||||
"type": "string",
|
||||
"title": "AzureServicePrincipalTenantId specifies the tenant ID of the Azure Service Principal used to access the repo"
|
||||
},
|
||||
"bearerToken": {
|
||||
"type": "string",
|
||||
"title": "BearerToken contains the bearer token used for Git BitBucket Data Center auth at the repo server"
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
@ -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
|
||||
repoOpts.Repo.WebhookManifestCacheWarmDisabled = repoOpts.WebhookManifestCacheWarmDisabled
|
||||
|
||||
|
|
@ -247,6 +257,10 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ type RepoOptions struct {
|
|||
UseAzureWorkloadIdentity bool
|
||||
Depth int64
|
||||
WebhookManifestCacheWarmDisabled bool
|
||||
AzureServicePrincipalTenantId string
|
||||
AzureServicePrincipalClientId string
|
||||
AzureServicePrincipalClientSecret string
|
||||
AzureActiveDirectoryEndpoint string
|
||||
}
|
||||
|
||||
func AddRepoFlags(command *cobra.Command, opts *RepoOptions) {
|
||||
|
|
@ -57,4 +61,8 @@ func AddRepoFlags(command *cobra.Command, opts *RepoOptions) {
|
|||
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().BoolVar(&opts.WebhookManifestCacheWarmDisabled, "webhook-manifest-cache-warm-disabled", false, "disable manifest cache warming during webhook processing for this repository (recommended for large monorepos with plain YAML manifests)")
|
||||
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)")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,6 +137,9 @@ 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 59 minutes to avoid issues with token expiration when taking the cleanup interval of 1 minute into account
|
||||
AzureServicePrincipalCredsExpirationDuration = time.Minute * 59
|
||||
|
||||
// PasswordPatten is the default password patten
|
||||
PasswordPatten = `^.{8,32}$`
|
||||
|
|
@ -297,6 +300,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: 59). Any value greater than 59 will be set to 59 minutes
|
||||
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
|
||||
|
|
|
|||
BIN
docs/assets/repo-add-azure-service-principal.png
Normal file
BIN
docs/assets/repo-add-azure-service-principal.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
|
|
@ -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]
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ argocd admin repo generate-spec REPOURL [flags]
|
|||
### Options
|
||||
|
||||
```
|
||||
--azure-active-directory-endpoint string Active Directory endpoint when not using default Azure public cloud (e.g. https://login.microsoftonline.de)
|
||||
--azure-service-principal-client-id string client id of the Azure Service Principal
|
||||
--azure-service-principal-client-secret string client secret of the Azure Service Principal
|
||||
--azure-service-principal-tenant-id string tenant id of the Azure Service Principal
|
||||
--bearer-token string bearer token to the Git BitBucket Data Center repository
|
||||
--depth int Specify a custom depth for git clone operations. Unless specified, a full clone is performed using the depth of 0
|
||||
--enable-lfs enable git-lfs (Large File Support) on this repository
|
||||
|
|
|
|||
10
docs/user-guide/commands/argocd_repo_add.md
generated
10
docs/user-guide/commands/argocd_repo_add.md
generated
|
|
@ -56,11 +56,21 @@ argocd repo add REPOURL [flags]
|
|||
# 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
|
||||
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--azure-active-directory-endpoint string Active Directory endpoint when not using default Azure public cloud (e.g. https://login.microsoftonline.de)
|
||||
--azure-service-principal-client-id string client id of the Azure Service Principal
|
||||
--azure-service-principal-client-secret string client secret of the Azure Service Principal
|
||||
--azure-service-principal-tenant-id string tenant id of the Azure Service Principal
|
||||
--bearer-token string bearer token to the Git BitBucket Data Center repository
|
||||
--depth int Specify a custom depth for git clone operations. Unless specified, a full clone is performed using the depth of 0
|
||||
--enable-lfs enable git-lfs (Large File Support) on this repository
|
||||
|
|
|
|||
10
docs/user-guide/commands/argocd_repocreds_add.md
generated
10
docs/user-guide/commands/argocd_repocreds_add.md
generated
|
|
@ -32,11 +32,21 @@ argocd repocreds add REPOURL [flags]
|
|||
# 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
|
||||
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--azure-active-directory-endpoint string Active Directory endpoint when not using default Azure public cloud (e.g. https://login.microsoftonline.de)
|
||||
--azure-service-principal-client-id string client id of the Azure Service Principal
|
||||
--azure-service-principal-client-secret string client secret of the Azure Service Principal
|
||||
--azure-service-principal-tenant-id string tenant id of the Azure Service Principal
|
||||
--bearer-token string bearer token to the Git repository
|
||||
--enable-oci Specifies whether helm-oci support should be enabled for this repo
|
||||
--force-http-basic-auth whether to force basic auth when connecting via HTTP
|
||||
|
|
|
|||
|
|
@ -242,6 +242,36 @@ stringData:
|
|||
useAzureWorkloadIdentity: "true"
|
||||
```
|
||||
|
||||
### Azure Devops using Service Principal
|
||||
|
||||
Azure DevOps repositories can be accessed using credentials from a Service Principal. Refer to steps 1,2 and 3 from the [Use service principals and managed identities in Azure DevOps](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity?view=azure-devops) documentation on how to create a service principal and configure access to Azure DevOps.
|
||||
|
||||
> [!NOTE]
|
||||
> Ensure your service principal has at least `Project Readers` permissions to the `Project` that contains the repository. This is the minimum requirement.
|
||||
|
||||
You can configure access to your Git repository hosted on Azure DevOps with Service Principal by either using the CLI or the UI.
|
||||
|
||||
Using the CLI:
|
||||
|
||||
```
|
||||
argocd repo add https://dev.azure.com/my-devops-organization/my-devops-project/_git/my-devops-repo --azure-service-principal-tenant-id 12345678-1234-1234-1234-123456789012 --azure-service-principal-client-id 12345678-1234-1234-1234-123456789012 --azure-service-principal-client-secret test
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> To use an Azure cloud other than the default public cloud using the CLI add `--azure-active-directory-endpoint https://login.microsoftonline.de` flag.
|
||||
|
||||
Using the UI:
|
||||
|
||||
1. Navigate to `Settings/Repositories`
|
||||
|
||||

|
||||
|
||||
2. Click `Connect Repo` button, choose connection method: `Via Azure Service Principal`, enter the URL, Tenant Id, Client Id, Client Secret, and Active Directory Endpoint if not using default Azure public cloud.
|
||||
|
||||

|
||||
|
||||
3. Click `Connect` to test the connection and have the repository added
|
||||
|
||||
## Credential templates
|
||||
|
||||
You can also set up credentials to serve as templates for connecting repositories, without having to repeat credential configuration. For example, if you setup credential templates for the URL prefix `https://github.com/argoproj`, these credentials will be used for all repositories with this URL as prefix (e.g. `https://github.com/argoproj/argocd-example-apps`) that do not have their own credentials configured.
|
||||
|
|
|
|||
397
pkg/apiclient/repository/repository.pb.go
generated
397
pkg/apiclient/repository/repository.pb.go
generated
|
|
@ -402,6 +402,14 @@ type RepoAccessQuery struct {
|
|||
BearerToken string `protobuf:"bytes,21,opt,name=bearerToken,proto3" json:"bearerToken,omitempty"`
|
||||
// Whether https should be disabled for an OCI repo
|
||||
InsecureOciForceHttp bool `protobuf:"varint,22,opt,name=insecureOciForceHttp,proto3" json:"insecureOciForceHttp,omitempty"`
|
||||
// Azure Service Principal Client ID
|
||||
AzureServicePrincipalClientId string `protobuf:"bytes,23,opt,name=azureServicePrincipalClientId,proto3" json:"azureServicePrincipalClientId,omitempty"`
|
||||
// Azure Service Principal Client Secret
|
||||
AzureServicePrincipalClientSecret string `protobuf:"bytes,24,opt,name=azureServicePrincipalClientSecret,proto3" json:"azureServicePrincipalClientSecret,omitempty"`
|
||||
// Azure Service Principal Tenant ID
|
||||
AzureServicePrincipalTenantId string `protobuf:"bytes,25,opt,name=azureServicePrincipalTenantId,proto3" json:"azureServicePrincipalTenantId,omitempty"`
|
||||
// Azure Active Directory Endpoint
|
||||
AzureActiveDirectoryEndpoint string `protobuf:"bytes,26,opt,name=azureActiveDirectoryEndpoint,proto3" json:"azureActiveDirectoryEndpoint,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
|
@ -587,6 +595,34 @@ func (m *RepoAccessQuery) GetInsecureOciForceHttp() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) GetAzureServicePrincipalClientId() string {
|
||||
if m != nil {
|
||||
return m.AzureServicePrincipalClientId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) GetAzureServicePrincipalClientSecret() string {
|
||||
if m != nil {
|
||||
return m.AzureServicePrincipalClientSecret
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) GetAzureServicePrincipalTenantId() string {
|
||||
if m != nil {
|
||||
return m.AzureServicePrincipalTenantId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) GetAzureActiveDirectoryEndpoint() string {
|
||||
if m != nil {
|
||||
return m.AzureActiveDirectoryEndpoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RepoResponse struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
|
|
@ -757,94 +793,99 @@ func init() {
|
|||
}
|
||||
|
||||
var fileDescriptor_8d38260443475705 = []byte{
|
||||
// 1392 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xdf, 0x6e, 0x1b, 0xc5,
|
||||
0x17, 0xd6, 0x26, 0x8d, 0x9b, 0x4c, 0x9a, 0xd6, 0x9d, 0x24, 0xed, 0xfe, 0xdc, 0x34, 0xcd, 0x6f,
|
||||
0x5b, 0xa2, 0x34, 0x6a, 0xd7, 0x4d, 0x0a, 0xa2, 0x2a, 0x02, 0xc9, 0x4d, 0x4a, 0x6b, 0x11, 0x91,
|
||||
0xb2, 0x6d, 0xa9, 0x84, 0x40, 0x68, 0xb2, 0x3e, 0xb1, 0xb7, 0xd9, 0xec, 0x4e, 0x67, 0xc6, 0x6e,
|
||||
0x4d, 0xd5, 0x1b, 0x84, 0x10, 0x12, 0xdc, 0x20, 0x04, 0xe2, 0x0e, 0x2e, 0x90, 0x90, 0xe0, 0x12,
|
||||
0x89, 0x67, 0xe0, 0x12, 0x89, 0x17, 0x40, 0x15, 0x0f, 0xc1, 0x25, 0x9a, 0x33, 0xeb, 0xf5, 0x3a,
|
||||
0xf1, 0x9f, 0x44, 0x4d, 0x73, 0x37, 0x73, 0xce, 0xec, 0xf9, 0xbe, 0xf3, 0xcd, 0x99, 0x33, 0x63,
|
||||
0x13, 0x47, 0x82, 0x68, 0x80, 0x28, 0x0a, 0xe0, 0xb1, 0x0c, 0x54, 0x2c, 0x9a, 0x99, 0xa1, 0xcb,
|
||||
0x45, 0xac, 0x62, 0x4a, 0xda, 0x96, 0xc2, 0x4c, 0x35, 0x8e, 0xab, 0x21, 0x14, 0x19, 0x0f, 0x8a,
|
||||
0x2c, 0x8a, 0x62, 0xc5, 0x54, 0x10, 0x47, 0xd2, 0xac, 0x2c, 0xac, 0x55, 0x03, 0x55, 0xab, 0x6f,
|
||||
0xb8, 0x7e, 0xbc, 0x5d, 0x64, 0xa2, 0x1a, 0x73, 0x11, 0x3f, 0xc4, 0xc1, 0x65, 0xbf, 0x52, 0x6c,
|
||||
0x5c, 0x2d, 0xf2, 0xad, 0xaa, 0xfe, 0x52, 0x16, 0x19, 0xe7, 0x61, 0xe0, 0xe3, 0xb7, 0xc5, 0xc6,
|
||||
0x12, 0x0b, 0x79, 0x8d, 0x2d, 0x15, 0xab, 0x10, 0x81, 0x60, 0x0a, 0x2a, 0x49, 0xb4, 0x9b, 0x03,
|
||||
0xa2, 0x21, 0xad, 0x81, 0xf4, 0x9d, 0x26, 0x99, 0xf0, 0x80, 0xc7, 0x25, 0xce, 0xe5, 0x7b, 0x75,
|
||||
0x10, 0x4d, 0x4a, 0xc9, 0x11, 0xbd, 0xc8, 0xb6, 0xe6, 0xac, 0x85, 0x31, 0x0f, 0xc7, 0xb4, 0x40,
|
||||
0x46, 0x05, 0x34, 0x02, 0x19, 0xc4, 0x91, 0x3d, 0x84, 0xf6, 0x74, 0x4e, 0x6d, 0x72, 0x94, 0x71,
|
||||
0xfe, 0x2e, 0xdb, 0x06, 0x7b, 0x18, 0x5d, 0xad, 0x29, 0x9d, 0x25, 0x84, 0x71, 0x7e, 0x47, 0xc4,
|
||||
0x0f, 0xc1, 0x57, 0xf6, 0x11, 0x74, 0x66, 0x2c, 0xce, 0x12, 0x39, 0x5a, 0xe2, 0xbc, 0x1c, 0x6d,
|
||||
0xc6, 0x1a, 0x54, 0x35, 0x39, 0xb4, 0x40, 0xf5, 0x58, 0xdb, 0x38, 0x53, 0xb5, 0x04, 0x10, 0xc7,
|
||||
0xce, 0xbf, 0x16, 0x99, 0x4c, 0xe8, 0xae, 0x82, 0x62, 0x41, 0x98, 0x90, 0xae, 0x92, 0x9c, 0x8c,
|
||||
0xeb, 0xc2, 0x37, 0x11, 0xc6, 0x97, 0xd7, 0xdd, 0xb6, 0x3a, 0x6e, 0x4b, 0x1d, 0x1c, 0x7c, 0xec,
|
||||
0x57, 0xdc, 0xc6, 0x55, 0x97, 0x6f, 0x55, 0x5d, 0xad, 0xb5, 0x9b, 0xd1, 0xda, 0x6d, 0x69, 0xed,
|
||||
0x96, 0xda, 0xc6, 0xbb, 0x18, 0xd6, 0x4b, 0xc2, 0x67, 0xb3, 0x1d, 0xea, 0x97, 0xed, 0xf0, 0xce,
|
||||
0x6c, 0xe9, 0x1c, 0x19, 0x37, 0x31, 0xca, 0x51, 0x05, 0x9e, 0xa0, 0x1c, 0x23, 0x5e, 0xd6, 0x44,
|
||||
0x67, 0xc8, 0x58, 0x03, 0x84, 0x16, 0xb5, 0x5c, 0xb1, 0x47, 0xd0, 0xdf, 0x36, 0x38, 0x6f, 0x92,
|
||||
0x7c, 0x6b, 0xa3, 0x3c, 0x90, 0x3c, 0x8e, 0x24, 0xd0, 0x8b, 0x64, 0x24, 0x50, 0xb0, 0x2d, 0x6d,
|
||||
0x6b, 0x6e, 0x78, 0x61, 0x7c, 0x79, 0xd2, 0xcd, 0x6c, 0x6f, 0x22, 0xad, 0x67, 0x56, 0x38, 0x3e,
|
||||
0x19, 0xd3, 0x9f, 0xf7, 0xde, 0x63, 0x87, 0x1c, 0xdb, 0x8c, 0x75, 0xaa, 0xb0, 0x29, 0x40, 0x1a,
|
||||
0xd9, 0x47, 0xbd, 0x0e, 0xdb, 0xa0, 0x1c, 0x9d, 0xdf, 0x72, 0xe4, 0x04, 0x92, 0xf4, 0x7d, 0x90,
|
||||
0xfd, 0xeb, 0xa9, 0x2e, 0x41, 0x44, 0x6d, 0x19, 0xd3, 0xb9, 0xf6, 0x71, 0x26, 0xe5, 0xe3, 0x58,
|
||||
0x54, 0x12, 0x84, 0x74, 0x4e, 0x2f, 0x90, 0x09, 0x29, 0x6b, 0x77, 0x44, 0xd0, 0x60, 0x0a, 0xde,
|
||||
0x81, 0x66, 0x52, 0x54, 0x9d, 0x46, 0x1d, 0x21, 0x88, 0x24, 0xf8, 0x75, 0x01, 0x28, 0xe3, 0xa8,
|
||||
0x97, 0xce, 0xe9, 0x25, 0x72, 0x52, 0x85, 0x72, 0x25, 0x0c, 0x20, 0x52, 0x2b, 0x20, 0xd4, 0x2a,
|
||||
0x53, 0xcc, 0xce, 0x61, 0x94, 0xdd, 0x0e, 0xba, 0x48, 0xf2, 0x1d, 0x46, 0x0d, 0x79, 0x14, 0x17,
|
||||
0xef, 0xb2, 0xa7, 0x25, 0x3c, 0xd6, 0x59, 0xc2, 0x98, 0x23, 0x31, 0x36, 0xcc, 0x6f, 0x86, 0x8c,
|
||||
0x41, 0xc4, 0x36, 0x42, 0x58, 0xf7, 0x03, 0x7b, 0x1c, 0xe9, 0xb5, 0x0d, 0xf4, 0x0a, 0x99, 0x34,
|
||||
0x95, 0x5b, 0xd2, 0xaa, 0xa6, 0x79, 0x1e, 0xc3, 0x00, 0xdd, 0x5c, 0xba, 0xae, 0x52, 0x73, 0x79,
|
||||
0xd5, 0x9e, 0x98, 0xb3, 0x16, 0x86, 0xbd, 0xac, 0x89, 0x5e, 0x23, 0xa7, 0xdb, 0xd3, 0x48, 0x2a,
|
||||
0x16, 0x86, 0x58, 0xda, 0xe5, 0x55, 0xfb, 0x38, 0xae, 0xee, 0xe5, 0xa6, 0x6f, 0x91, 0x42, 0xea,
|
||||
0xba, 0x19, 0x29, 0x10, 0x5c, 0x04, 0x12, 0x6e, 0x30, 0x09, 0xf7, 0x45, 0x68, 0x9f, 0x40, 0x52,
|
||||
0x7d, 0x56, 0xd0, 0x29, 0x32, 0xc2, 0x45, 0xfc, 0xa4, 0x69, 0xe7, 0x71, 0xa9, 0x99, 0xe8, 0x33,
|
||||
0xc4, 0x93, 0x12, 0x3a, 0x69, 0xce, 0x50, 0x32, 0xa5, 0xcb, 0x64, 0xaa, 0xea, 0xf3, 0xbb, 0x20,
|
||||
0x1a, 0x81, 0x0f, 0x25, 0xdf, 0x8f, 0xeb, 0x11, 0x6a, 0x4e, 0x71, 0x59, 0x57, 0x1f, 0x75, 0x09,
|
||||
0xc5, 0x1a, 0xbd, 0xad, 0x14, 0xbf, 0xc1, 0x64, 0xe0, 0x97, 0xea, 0xaa, 0x66, 0x4f, 0xa2, 0xb0,
|
||||
0x5d, 0x3c, 0xf4, 0x3a, 0xb1, 0xeb, 0x12, 0x4a, 0x9f, 0xd4, 0x05, 0x3c, 0x88, 0xc5, 0x56, 0x18,
|
||||
0xb3, 0x4a, 0xb9, 0x02, 0x91, 0x0a, 0x54, 0xd3, 0x9e, 0xc2, 0xaf, 0x7a, 0xfa, 0xb5, 0xd6, 0x1b,
|
||||
0xc0, 0x04, 0x88, 0x7b, 0xf1, 0x16, 0x44, 0xf6, 0x34, 0xd2, 0xca, 0x9a, 0x74, 0x06, 0xad, 0x5a,
|
||||
0x5b, 0xf7, 0x83, 0xb7, 0x5b, 0xf0, 0xf6, 0x29, 0x8c, 0xdc, 0xd5, 0xe7, 0x1c, 0x27, 0xc7, 0xf4,
|
||||
0xa1, 0x69, 0x9d, 0x6a, 0xe7, 0x67, 0x8b, 0x9c, 0xd4, 0x86, 0x15, 0x01, 0x4c, 0x81, 0x07, 0x8f,
|
||||
0xea, 0x20, 0x15, 0xfd, 0x30, 0x73, 0x8e, 0xc6, 0x97, 0x6f, 0xbf, 0x58, 0x83, 0xf3, 0xd2, 0x3e,
|
||||
0x91, 0x9c, 0xc8, 0x53, 0x24, 0x57, 0xe7, 0x12, 0x84, 0x4a, 0xce, 0x7d, 0x32, 0xd3, 0xd5, 0xea,
|
||||
0x0b, 0xa8, 0xc8, 0xf5, 0x28, 0x6c, 0xe2, 0x71, 0x1c, 0xf5, 0xda, 0x06, 0xe7, 0x91, 0x21, 0x7a,
|
||||
0x9f, 0x57, 0x0e, 0x8b, 0xe8, 0xf2, 0x67, 0xa7, 0x0d, 0xa6, 0x31, 0x26, 0xe5, 0x40, 0xbf, 0xb2,
|
||||
0xc8, 0x91, 0xb5, 0x40, 0x2a, 0x3a, 0x9d, 0x6d, 0x81, 0x69, 0xc3, 0x2b, 0xac, 0x1d, 0x14, 0x0b,
|
||||
0x0d, 0xe2, 0x9c, 0xfb, 0xf4, 0xaf, 0x7f, 0xbe, 0x19, 0x3a, 0x45, 0xa7, 0xf0, 0xa2, 0x6f, 0x2c,
|
||||
0xb5, 0x6f, 0xd5, 0x00, 0xe4, 0x17, 0x43, 0x16, 0xfd, 0xd2, 0x22, 0xc3, 0xb7, 0xa0, 0x27, 0x9b,
|
||||
0x03, 0xd3, 0xc4, 0x39, 0x8f, 0x4c, 0xce, 0xd2, 0x33, 0xdd, 0x98, 0x14, 0x9f, 0xea, 0xd9, 0x33,
|
||||
0xfa, 0x9d, 0x45, 0x46, 0x6f, 0x81, 0x7a, 0x20, 0x02, 0x05, 0x2f, 0x9f, 0xd2, 0x45, 0xa4, 0x74,
|
||||
0x9e, 0xfe, 0xbf, 0x45, 0xe9, 0xb1, 0xc6, 0xbd, 0xdc, 0x8d, 0xd8, 0xb7, 0x16, 0xc9, 0x6b, 0x41,
|
||||
0xbd, 0x8c, 0xef, 0x70, 0x76, 0x70, 0xa6, 0xdf, 0x0e, 0xd2, 0x1f, 0x2d, 0x32, 0xad, 0x97, 0xa1,
|
||||
0x62, 0x87, 0x4f, 0xce, 0x41, 0x72, 0x33, 0xb4, 0xd0, 0x5b, 0x41, 0xfa, 0x11, 0x19, 0x35, 0xca,
|
||||
0x6d, 0xf6, 0x24, 0x95, 0xef, 0x34, 0x6f, 0x4a, 0x67, 0x01, 0x03, 0x3b, 0x74, 0xae, 0x4f, 0xb5,
|
||||
0x14, 0x85, 0x0e, 0x59, 0x21, 0xe3, 0x3a, 0xfc, 0xfa, 0x4a, 0xf9, 0x1e, 0xab, 0xee, 0x03, 0xe1,
|
||||
0x12, 0x22, 0xcc, 0xd3, 0x0b, 0xfd, 0x10, 0x62, 0x3f, 0xb8, 0xac, 0x74, 0xd8, 0x6d, 0x93, 0x84,
|
||||
0x7e, 0xd2, 0xd0, 0xff, 0xed, 0x84, 0x48, 0x5f, 0xa4, 0x85, 0x99, 0x6e, 0xae, 0xb4, 0x5b, 0xee,
|
||||
0x29, 0x29, 0xa6, 0x21, 0xbe, 0xb6, 0xc8, 0xc4, 0x2d, 0x50, 0xed, 0xb7, 0x23, 0x3d, 0xd7, 0x25,
|
||||
0x72, 0xf6, 0x5d, 0x59, 0x70, 0x7a, 0x2f, 0x48, 0x09, 0xbc, 0x81, 0x04, 0x5e, 0x73, 0xae, 0x74,
|
||||
0x27, 0x60, 0x5e, 0x78, 0x18, 0xe7, 0xbe, 0xb7, 0x86, 0x54, 0x2a, 0x26, 0xc2, 0x75, 0x6b, 0x91,
|
||||
0x36, 0x90, 0xd2, 0x6d, 0x08, 0xb7, 0x57, 0x6a, 0x4c, 0xa8, 0x9e, 0x52, 0xcf, 0x66, 0xcd, 0xed,
|
||||
0xe5, 0x29, 0x09, 0x17, 0x49, 0x2c, 0xd0, 0xf9, 0x7e, 0x2a, 0xd4, 0x20, 0xdc, 0xf6, 0x0d, 0xcc,
|
||||
0xf7, 0x16, 0xc9, 0x99, 0xfb, 0x85, 0x9e, 0xdd, 0x89, 0xd8, 0x71, 0xef, 0x1c, 0x60, 0x67, 0x78,
|
||||
0xc5, 0xd4, 0xb5, 0xd3, 0xf5, 0xd0, 0x5d, 0xc7, 0xf6, 0xae, 0x9b, 0xe7, 0x0f, 0x16, 0xc9, 0xb7,
|
||||
0x28, 0xb4, 0xbe, 0x3d, 0x3c, 0x92, 0xce, 0x60, 0x92, 0xf4, 0x17, 0x8b, 0x4c, 0x1b, 0xfc, 0xce,
|
||||
0x0e, 0x71, 0x88, 0x34, 0x93, 0xaa, 0x77, 0xfa, 0xf4, 0x88, 0x84, 0xec, 0x4f, 0x16, 0xc9, 0x99,
|
||||
0x0b, 0x7a, 0x37, 0xbb, 0x8e, 0x8b, 0xfb, 0x00, 0xd9, 0x2d, 0x99, 0x6a, 0x2c, 0xf4, 0x39, 0x93,
|
||||
0x48, 0xe5, 0x59, 0x7b, 0xd7, 0x7f, 0xb5, 0x48, 0xbe, 0x45, 0xa7, 0xb7, 0x9c, 0x2f, 0x8b, 0xb0,
|
||||
0xbb, 0x3f, 0xc2, 0xf4, 0x77, 0x8b, 0x4c, 0x1b, 0x2e, 0x03, 0x2b, 0xe0, 0x65, 0x51, 0x7e, 0x15,
|
||||
0x29, 0xbb, 0x85, 0xf9, 0x41, 0xf7, 0x6c, 0x07, 0x71, 0x46, 0x72, 0xab, 0x10, 0x42, 0xef, 0x87,
|
||||
0x80, 0xbd, 0xd3, 0x9c, 0xb6, 0x98, 0x79, 0xf3, 0xd6, 0x58, 0xec, 0xf7, 0xd6, 0xd0, 0x3b, 0x59,
|
||||
0x23, 0x79, 0x03, 0x91, 0x51, 0x65, 0xdf, 0x60, 0xe7, 0xf7, 0x00, 0x46, 0x25, 0x99, 0x36, 0x48,
|
||||
0x3b, 0x37, 0x61, 0xdf, 0x70, 0xc9, 0xa3, 0x65, 0x71, 0x0f, 0x8f, 0x96, 0xa7, 0xe4, 0xf8, 0xfb,
|
||||
0x2c, 0x0c, 0xf4, 0xa6, 0x9a, 0x9f, 0xb9, 0xf4, 0xcc, 0xae, 0x4b, 0xa2, 0xfd, 0xf3, 0xb7, 0x0f,
|
||||
0xe6, 0x32, 0x62, 0x5e, 0x72, 0xfa, 0xde, 0x95, 0x8d, 0x04, 0x2a, 0xd9, 0xbe, 0xcf, 0x2d, 0x32,
|
||||
0xd9, 0x42, 0xc7, 0xa4, 0x5f, 0x8c, 0xc2, 0x35, 0xa4, 0xb0, 0xec, 0x2c, 0x0e, 0x4c, 0x7b, 0x07,
|
||||
0x91, 0x1b, 0x37, 0xff, 0x78, 0x3e, 0x6b, 0xfd, 0xf9, 0x7c, 0xd6, 0xfa, 0xfb, 0xf9, 0xac, 0xf5,
|
||||
0xc1, 0xeb, 0x7b, 0xfb, 0x67, 0xcb, 0xc7, 0x1f, 0xcc, 0x99, 0xff, 0xa0, 0x36, 0x72, 0xf8, 0x27,
|
||||
0xd4, 0xd5, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x0b, 0xd2, 0x3f, 0x69, 0x13, 0x00, 0x00,
|
||||
// 1471 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x5f, 0x6f, 0x13, 0xc7,
|
||||
0x16, 0xd7, 0x26, 0x24, 0x24, 0x13, 0x02, 0x66, 0x92, 0xc0, 0x62, 0x42, 0x08, 0x0b, 0x37, 0x0a,
|
||||
0x11, 0xac, 0x49, 0xb8, 0x57, 0x17, 0x71, 0x75, 0x2b, 0x39, 0x7f, 0x0a, 0x56, 0xa3, 0x86, 0x1a,
|
||||
0x28, 0x52, 0xd5, 0xaa, 0x9a, 0xac, 0x4f, 0xec, 0x25, 0x9b, 0xdd, 0x61, 0x66, 0x6c, 0x70, 0x11,
|
||||
0x2f, 0x55, 0x55, 0x55, 0x6a, 0x5f, 0xaa, 0xaa, 0x55, 0xdf, 0xda, 0x87, 0x4a, 0x95, 0xda, 0xf7,
|
||||
0x7e, 0x86, 0x3e, 0xb6, 0xea, 0x17, 0xa8, 0x50, 0x3f, 0x44, 0x1f, 0xab, 0x39, 0xb3, 0x5e, 0xaf,
|
||||
0x13, 0x7b, 0x9d, 0x88, 0x90, 0xb7, 0x9d, 0x73, 0x8e, 0xcf, 0xef, 0x77, 0x7e, 0x73, 0xf6, 0xcc,
|
||||
0x78, 0x89, 0x23, 0x41, 0x34, 0x40, 0x14, 0x04, 0xf0, 0x48, 0xfa, 0x2a, 0x12, 0xcd, 0xd4, 0xa3,
|
||||
0xcb, 0x45, 0xa4, 0x22, 0x4a, 0xda, 0x96, 0xfc, 0x74, 0x35, 0x8a, 0xaa, 0x01, 0x14, 0x18, 0xf7,
|
||||
0x0b, 0x2c, 0x0c, 0x23, 0xc5, 0x94, 0x1f, 0x85, 0xd2, 0x44, 0xe6, 0xd7, 0xab, 0xbe, 0xaa, 0xd5,
|
||||
0x37, 0x5d, 0x2f, 0xda, 0x29, 0x30, 0x51, 0x8d, 0xb8, 0x88, 0x1e, 0xe3, 0xc3, 0x75, 0xaf, 0x52,
|
||||
0x68, 0xdc, 0x2c, 0xf0, 0xed, 0xaa, 0xfe, 0xa5, 0x2c, 0x30, 0xce, 0x03, 0xdf, 0xc3, 0xdf, 0x16,
|
||||
0x1a, 0x8b, 0x2c, 0xe0, 0x35, 0xb6, 0x58, 0xa8, 0x42, 0x08, 0x82, 0x29, 0xa8, 0xc4, 0xd9, 0xd6,
|
||||
0xfa, 0x64, 0x43, 0x5a, 0x7d, 0xe9, 0x3b, 0x4d, 0x32, 0x5e, 0x06, 0x1e, 0x15, 0x39, 0x97, 0xef,
|
||||
0xd4, 0x41, 0x34, 0x29, 0x25, 0xc7, 0x74, 0x90, 0x6d, 0xcd, 0x5a, 0xf3, 0xa3, 0x65, 0x7c, 0xa6,
|
||||
0x79, 0x32, 0x22, 0xa0, 0xe1, 0x4b, 0x3f, 0x0a, 0xed, 0x01, 0xb4, 0x27, 0x6b, 0x6a, 0x93, 0xe3,
|
||||
0x8c, 0xf3, 0xb7, 0xd9, 0x0e, 0xd8, 0x83, 0xe8, 0x6a, 0x2d, 0xe9, 0x0c, 0x21, 0x8c, 0xf3, 0x7b,
|
||||
0x22, 0x7a, 0x0c, 0x9e, 0xb2, 0x8f, 0xa1, 0x33, 0x65, 0x71, 0x16, 0xc9, 0xf1, 0x22, 0xe7, 0xa5,
|
||||
0x70, 0x2b, 0xd2, 0xa0, 0xaa, 0xc9, 0xa1, 0x05, 0xaa, 0x9f, 0xb5, 0x8d, 0x33, 0x55, 0x8b, 0x01,
|
||||
0xf1, 0xd9, 0xf9, 0xdb, 0x22, 0x13, 0x31, 0xdd, 0x55, 0x50, 0xcc, 0x0f, 0x62, 0xd2, 0x55, 0x32,
|
||||
0x2c, 0xa3, 0xba, 0xf0, 0x4c, 0x86, 0xb1, 0xa5, 0x0d, 0xb7, 0xad, 0x8e, 0xdb, 0x52, 0x07, 0x1f,
|
||||
0x3e, 0xf4, 0x2a, 0x6e, 0xe3, 0xa6, 0xcb, 0xb7, 0xab, 0xae, 0xd6, 0xda, 0x4d, 0x69, 0xed, 0xb6,
|
||||
0xb4, 0x76, 0x8b, 0x6d, 0xe3, 0x7d, 0x4c, 0x5b, 0x8e, 0xd3, 0xa7, 0xab, 0x1d, 0xc8, 0xaa, 0x76,
|
||||
0x70, 0x77, 0xb5, 0x74, 0x96, 0x8c, 0x99, 0x1c, 0xa5, 0xb0, 0x02, 0xcf, 0x50, 0x8e, 0xa1, 0x72,
|
||||
0xda, 0x44, 0xa7, 0xc9, 0x68, 0x03, 0x84, 0x16, 0xb5, 0x54, 0xb1, 0x87, 0xd0, 0xdf, 0x36, 0x38,
|
||||
0xff, 0x27, 0xb9, 0xd6, 0x46, 0x95, 0x41, 0xf2, 0x28, 0x94, 0x40, 0xaf, 0x92, 0x21, 0x5f, 0xc1,
|
||||
0x8e, 0xb4, 0xad, 0xd9, 0xc1, 0xf9, 0xb1, 0xa5, 0x09, 0x37, 0xb5, 0xbd, 0xb1, 0xb4, 0x65, 0x13,
|
||||
0xe1, 0x78, 0x64, 0x54, 0xff, 0xbc, 0xf7, 0x1e, 0x3b, 0xe4, 0xc4, 0x56, 0xa4, 0x4b, 0x85, 0x2d,
|
||||
0x01, 0xd2, 0xc8, 0x3e, 0x52, 0xee, 0xb0, 0xf5, 0xab, 0xd1, 0xf9, 0x7d, 0x84, 0x9c, 0x42, 0x92,
|
||||
0x9e, 0x07, 0x32, 0xbb, 0x9f, 0xea, 0x12, 0x44, 0xd8, 0x96, 0x31, 0x59, 0x6b, 0x1f, 0x67, 0x52,
|
||||
0x3e, 0x8d, 0x44, 0x25, 0x46, 0x48, 0xd6, 0xf4, 0x0a, 0x19, 0x97, 0xb2, 0x76, 0x4f, 0xf8, 0x0d,
|
||||
0xa6, 0xe0, 0x2d, 0x68, 0xc6, 0x4d, 0xd5, 0x69, 0xd4, 0x19, 0xfc, 0x50, 0x82, 0x57, 0x17, 0x80,
|
||||
0x32, 0x8e, 0x94, 0x93, 0x35, 0xbd, 0x46, 0x4e, 0xab, 0x40, 0xae, 0x04, 0x3e, 0x84, 0x6a, 0x05,
|
||||
0x84, 0x5a, 0x65, 0x8a, 0xd9, 0xc3, 0x98, 0x65, 0xaf, 0x83, 0x2e, 0x90, 0x5c, 0x87, 0x51, 0x43,
|
||||
0x1e, 0xc7, 0xe0, 0x3d, 0xf6, 0xa4, 0x85, 0x47, 0x3b, 0x5b, 0x18, 0x6b, 0x24, 0xc6, 0x86, 0xf5,
|
||||
0x4d, 0x93, 0x51, 0x08, 0xd9, 0x66, 0x00, 0x1b, 0x9e, 0x6f, 0x8f, 0x21, 0xbd, 0xb6, 0x81, 0xde,
|
||||
0x20, 0x13, 0xa6, 0x73, 0x8b, 0x5a, 0xd5, 0xa4, 0xce, 0x13, 0x98, 0xa0, 0x9b, 0x4b, 0xf7, 0x55,
|
||||
0x62, 0x2e, 0xad, 0xda, 0xe3, 0xb3, 0xd6, 0xfc, 0x60, 0x39, 0x6d, 0xa2, 0xb7, 0xc8, 0xd9, 0xf6,
|
||||
0x32, 0x94, 0x8a, 0x05, 0x01, 0xb6, 0x76, 0x69, 0xd5, 0x3e, 0x89, 0xd1, 0xbd, 0xdc, 0xf4, 0x0d,
|
||||
0x92, 0x4f, 0x5c, 0x6b, 0xa1, 0x02, 0xc1, 0x85, 0x2f, 0x61, 0x99, 0x49, 0x78, 0x28, 0x02, 0xfb,
|
||||
0x14, 0x92, 0xca, 0x88, 0xa0, 0x93, 0x64, 0x88, 0x8b, 0xe8, 0x59, 0xd3, 0xce, 0x61, 0xa8, 0x59,
|
||||
0xe8, 0x77, 0x88, 0xc7, 0x2d, 0x74, 0xda, 0xbc, 0x43, 0xf1, 0x92, 0x2e, 0x91, 0xc9, 0xaa, 0xc7,
|
||||
0xef, 0x83, 0x68, 0xf8, 0x1e, 0x14, 0x3d, 0x2f, 0xaa, 0x87, 0xa8, 0x39, 0xc5, 0xb0, 0xae, 0x3e,
|
||||
0xea, 0x12, 0x8a, 0x3d, 0x7a, 0x57, 0x29, 0xbe, 0xcc, 0xa4, 0xef, 0x15, 0xeb, 0xaa, 0x66, 0x4f,
|
||||
0xa0, 0xb0, 0x5d, 0x3c, 0xf4, 0x36, 0xb1, 0xeb, 0x12, 0x8a, 0x1f, 0xd5, 0x05, 0x3c, 0x8a, 0xc4,
|
||||
0x76, 0x10, 0xb1, 0x4a, 0xa9, 0x02, 0xa1, 0xf2, 0x55, 0xd3, 0x9e, 0xc4, 0x5f, 0xf5, 0xf4, 0x6b,
|
||||
0xad, 0x37, 0x81, 0x09, 0x10, 0x0f, 0xa2, 0x6d, 0x08, 0xed, 0x29, 0xa4, 0x95, 0x36, 0xe9, 0x0a,
|
||||
0x5a, 0xbd, 0xb6, 0xe1, 0xf9, 0x6f, 0xb6, 0xe0, 0xed, 0x33, 0x98, 0xb9, 0xab, 0x8f, 0xae, 0x92,
|
||||
0x0b, 0x4c, 0xc3, 0xc5, 0xb5, 0xdd, 0x13, 0x7e, 0xe8, 0xf9, 0x9c, 0x05, 0xa6, 0xbf, 0x4a, 0x15,
|
||||
0xfb, 0x2c, 0xe2, 0x64, 0x07, 0xd1, 0x75, 0x72, 0x29, 0x23, 0xe0, 0x3e, 0x78, 0x02, 0x94, 0x6d,
|
||||
0x63, 0xa6, 0xfe, 0x81, 0x3d, 0x39, 0x3d, 0x80, 0x90, 0x21, 0xa7, 0x73, 0x19, 0x9c, 0x5a, 0x41,
|
||||
0x74, 0x99, 0x4c, 0x63, 0x40, 0xd1, 0x53, 0x7e, 0x03, 0x56, 0x7d, 0x01, 0x9e, 0x9e, 0x4d, 0x6b,
|
||||
0x61, 0x85, 0x47, 0x7e, 0xa8, 0xec, 0x3c, 0x26, 0xc9, 0x8c, 0x71, 0x4e, 0x92, 0x13, 0x7a, 0xa4,
|
||||
0xb4, 0x66, 0x9e, 0xf3, 0xa3, 0x45, 0x4e, 0x6b, 0xc3, 0x8a, 0x00, 0xa6, 0xa0, 0x0c, 0x4f, 0xea,
|
||||
0x20, 0x15, 0x7d, 0x3f, 0x35, 0x65, 0xc6, 0x96, 0xee, 0xbe, 0xda, 0xf8, 0x2f, 0x27, 0x53, 0x34,
|
||||
0x9e, 0x57, 0x67, 0xc8, 0x70, 0x9d, 0x4b, 0x10, 0x2a, 0x9e, 0x8a, 0xf1, 0x4a, 0xbf, 0xcb, 0x9e,
|
||||
0x80, 0x8a, 0xdc, 0x08, 0x83, 0x26, 0x0e, 0xab, 0x91, 0x72, 0xdb, 0xe0, 0x3c, 0x31, 0x44, 0x1f,
|
||||
0xf2, 0xca, 0x51, 0x11, 0x5d, 0xfa, 0xe4, 0xac, 0xc1, 0x34, 0xc6, 0x78, 0x5f, 0xe8, 0x17, 0x16,
|
||||
0x39, 0xb6, 0xee, 0x4b, 0x45, 0xa7, 0xd2, 0x07, 0x44, 0x72, 0x1c, 0xe4, 0xd7, 0x0f, 0x8b, 0x85,
|
||||
0x06, 0x71, 0x2e, 0x7e, 0xfc, 0xc7, 0x5f, 0x5f, 0x0d, 0x9c, 0xa1, 0x93, 0x78, 0x0d, 0x6a, 0x2c,
|
||||
0xb6, 0xef, 0x1c, 0x3e, 0xc8, 0xcf, 0x06, 0x2c, 0xfa, 0xb9, 0x45, 0x06, 0xef, 0x40, 0x4f, 0x36,
|
||||
0x87, 0xa6, 0x89, 0x73, 0x19, 0x99, 0x5c, 0xa0, 0xe7, 0xbb, 0x31, 0x29, 0x3c, 0xd7, 0xab, 0x17,
|
||||
0xf4, 0x1b, 0x8b, 0x8c, 0xdc, 0x01, 0xf5, 0x48, 0xf8, 0x0a, 0x5e, 0x3f, 0xa5, 0xab, 0x48, 0xe9,
|
||||
0x32, 0xbd, 0xd4, 0xa2, 0xf4, 0x54, 0xe3, 0x5e, 0xef, 0x46, 0xec, 0x6b, 0x8b, 0xe4, 0xb4, 0xa0,
|
||||
0xe5, 0x94, 0xef, 0x68, 0x76, 0x70, 0x3a, 0x6b, 0x07, 0xe9, 0xf7, 0x16, 0x99, 0xd2, 0x61, 0xa8,
|
||||
0xd8, 0xd1, 0x93, 0x73, 0x90, 0xdc, 0x34, 0xcd, 0xf7, 0x56, 0x90, 0x7e, 0x40, 0x46, 0x8c, 0x72,
|
||||
0x5b, 0x3d, 0x49, 0xe5, 0x3a, 0xcd, 0x5b, 0xd2, 0x99, 0xc7, 0xc4, 0x0e, 0x9d, 0xcd, 0xe8, 0x96,
|
||||
0x82, 0xd0, 0x29, 0x2b, 0x64, 0x4c, 0xa7, 0xdf, 0x58, 0x29, 0x3d, 0x60, 0xd5, 0x03, 0x20, 0x5c,
|
||||
0x43, 0x84, 0x39, 0x7a, 0x25, 0x0b, 0x21, 0xf2, 0xfc, 0xeb, 0x4a, 0xa7, 0xdd, 0x31, 0x45, 0xe8,
|
||||
0x0b, 0x1f, 0x3d, 0xb7, 0x1b, 0x22, 0xb9, 0xaf, 0xe7, 0xa7, 0xbb, 0xb9, 0x92, 0x69, 0xb9, 0xaf,
|
||||
0xa2, 0x98, 0x86, 0xf8, 0xd2, 0x22, 0xe3, 0x77, 0x40, 0xb5, 0x6f, 0xd6, 0xf4, 0x62, 0x97, 0xcc,
|
||||
0xe9, 0x5b, 0x77, 0xde, 0xe9, 0x1d, 0x90, 0x10, 0xf8, 0x1f, 0x12, 0xf8, 0x8f, 0x73, 0xa3, 0x3b,
|
||||
0x01, 0x73, 0xff, 0xc5, 0x3c, 0x0f, 0xcb, 0xeb, 0x48, 0xa5, 0x62, 0x32, 0xdc, 0xb6, 0x16, 0x68,
|
||||
0x03, 0x29, 0xdd, 0x85, 0x60, 0x67, 0xa5, 0xc6, 0x84, 0xea, 0x29, 0xf5, 0x4c, 0xda, 0xdc, 0x0e,
|
||||
0x4f, 0x48, 0xb8, 0x48, 0x62, 0x9e, 0xce, 0x65, 0xa9, 0x50, 0x83, 0x60, 0xc7, 0x33, 0x30, 0xdf,
|
||||
0x5a, 0x64, 0xd8, 0x9c, 0x2f, 0xf4, 0xc2, 0x6e, 0xc4, 0x8e, 0x73, 0xe7, 0x10, 0x27, 0xc3, 0xbf,
|
||||
0x4c, 0x5f, 0x3b, 0x5d, 0x5f, 0xba, 0xdb, 0x38, 0xde, 0xf5, 0xf0, 0xfc, 0xce, 0x22, 0xb9, 0x16,
|
||||
0x85, 0xd6, 0x6f, 0x8f, 0x8e, 0xa4, 0xd3, 0x9f, 0x24, 0xfd, 0xc9, 0x22, 0x53, 0x06, 0xbf, 0x73,
|
||||
0x42, 0x1c, 0x21, 0xcd, 0xb8, 0xeb, 0x9d, 0x8c, 0x19, 0x11, 0x93, 0xfd, 0xc1, 0x22, 0xc3, 0xe6,
|
||||
0x80, 0xde, 0xcb, 0xae, 0xe3, 0xe0, 0x3e, 0x44, 0x76, 0x8b, 0xa6, 0x1b, 0xf3, 0x19, 0xef, 0x24,
|
||||
0x52, 0x79, 0xd1, 0xde, 0xf5, 0x9f, 0x2d, 0x92, 0x6b, 0xd1, 0xe9, 0x2d, 0xe7, 0xeb, 0x22, 0xec,
|
||||
0x1e, 0x8c, 0x30, 0xfd, 0xc5, 0x22, 0x53, 0x86, 0x4b, 0xdf, 0x0e, 0x78, 0x5d, 0x94, 0xff, 0x8d,
|
||||
0x94, 0xdd, 0xfc, 0x5c, 0xbf, 0x73, 0xb6, 0x83, 0x38, 0x23, 0xc3, 0xab, 0x10, 0x40, 0xef, 0x8b,
|
||||
0x80, 0xbd, 0xdb, 0x9c, 0x8c, 0x98, 0x39, 0x73, 0xd7, 0x58, 0xc8, 0xba, 0x6b, 0xe8, 0x9d, 0xac,
|
||||
0x91, 0x9c, 0x81, 0x48, 0xa9, 0x72, 0x60, 0xb0, 0xcb, 0xfb, 0x00, 0xa3, 0x92, 0x4c, 0x19, 0xa4,
|
||||
0xdd, 0x9b, 0x70, 0x60, 0xb8, 0xf8, 0xd2, 0xb2, 0xb0, 0x8f, 0x4b, 0xcb, 0x73, 0x72, 0xf2, 0x5d,
|
||||
0x16, 0xf8, 0x7a, 0x53, 0xcd, 0x47, 0x00, 0x7a, 0x7e, 0xcf, 0x21, 0xd1, 0xfe, 0x38, 0x90, 0x81,
|
||||
0xb9, 0x84, 0x98, 0xd7, 0x9c, 0xcc, 0xb3, 0xb2, 0x11, 0x43, 0xc5, 0xdb, 0xf7, 0xa9, 0x45, 0x26,
|
||||
0x5a, 0xe8, 0x58, 0xf4, 0xab, 0x51, 0xb8, 0x85, 0x14, 0x96, 0x9c, 0x85, 0xbe, 0x65, 0xef, 0x22,
|
||||
0xb2, 0xbc, 0xf6, 0xeb, 0xcb, 0x19, 0xeb, 0xb7, 0x97, 0x33, 0xd6, 0x9f, 0x2f, 0x67, 0xac, 0xf7,
|
||||
0xfe, 0xbb, 0xbf, 0xef, 0x7e, 0x1e, 0xfe, 0xff, 0x4a, 0x7d, 0xa1, 0xdb, 0x1c, 0xc6, 0x4f, 0x74,
|
||||
0x37, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0xff, 0x54, 0xba, 0x9b, 0x87, 0x14, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
@ -1964,6 +2005,42 @@ func (m *RepoAccessQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if len(m.AzureActiveDirectoryEndpoint) > 0 {
|
||||
i -= len(m.AzureActiveDirectoryEndpoint)
|
||||
copy(dAtA[i:], m.AzureActiveDirectoryEndpoint)
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.AzureActiveDirectoryEndpoint)))
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0xd2
|
||||
}
|
||||
if len(m.AzureServicePrincipalTenantId) > 0 {
|
||||
i -= len(m.AzureServicePrincipalTenantId)
|
||||
copy(dAtA[i:], m.AzureServicePrincipalTenantId)
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.AzureServicePrincipalTenantId)))
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0xca
|
||||
}
|
||||
if len(m.AzureServicePrincipalClientSecret) > 0 {
|
||||
i -= len(m.AzureServicePrincipalClientSecret)
|
||||
copy(dAtA[i:], m.AzureServicePrincipalClientSecret)
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.AzureServicePrincipalClientSecret)))
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0xc2
|
||||
}
|
||||
if len(m.AzureServicePrincipalClientId) > 0 {
|
||||
i -= len(m.AzureServicePrincipalClientId)
|
||||
copy(dAtA[i:], m.AzureServicePrincipalClientId)
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.AzureServicePrincipalClientId)))
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0xba
|
||||
}
|
||||
if m.InsecureOciForceHttp {
|
||||
i--
|
||||
if m.InsecureOciForceHttp {
|
||||
|
|
@ -2477,6 +2554,22 @@ func (m *RepoAccessQuery) Size() (n int) {
|
|||
if m.InsecureOciForceHttp {
|
||||
n += 3
|
||||
}
|
||||
l = len(m.AzureServicePrincipalClientId)
|
||||
if l > 0 {
|
||||
n += 2 + l + sovRepository(uint64(l))
|
||||
}
|
||||
l = len(m.AzureServicePrincipalClientSecret)
|
||||
if l > 0 {
|
||||
n += 2 + l + sovRepository(uint64(l))
|
||||
}
|
||||
l = len(m.AzureServicePrincipalTenantId)
|
||||
if l > 0 {
|
||||
n += 2 + l + sovRepository(uint64(l))
|
||||
}
|
||||
l = len(m.AzureActiveDirectoryEndpoint)
|
||||
if l > 0 {
|
||||
n += 2 + l + sovRepository(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
|
|
@ -3857,6 +3950,134 @@ func (m *RepoAccessQuery) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
}
|
||||
m.InsecureOciForceHttp = bool(v != 0)
|
||||
case 23:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AzureServicePrincipalClientId", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.AzureServicePrincipalClientId = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 24:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AzureServicePrincipalClientSecret", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.AzureServicePrincipalClientSecret = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 25:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AzureServicePrincipalTenantId", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.AzureServicePrincipalTenantId = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 26:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AzureActiveDirectoryEndpoint", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.AzureActiveDirectoryEndpoint = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipRepository(dAtA[iNdEx:])
|
||||
|
|
|
|||
1917
pkg/apis/application/v1alpha1/generated.pb.go
generated
1917
pkg/apis/application/v1alpha1/generated.pb.go
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1876,6 +1876,18 @@ message RepoCreds {
|
|||
|
||||
// InsecureOCIForceHttp specifies whether the connection to the repository uses TLS at _all_. If true, no TLS. This flag is applicable for OCI repos only.
|
||||
optional bool insecureOCIForceHttp = 26;
|
||||
|
||||
// AzureServicePrincipalClientId specifies the client ID of the Azure Service Principal used to access the repo
|
||||
optional string azureServicePrincipalClientId = 29;
|
||||
|
||||
// AzureServicePrincipalClientSecret specifies the client secret of the Azure Service Principal used to access the repo
|
||||
optional string azureServicePrincipalClientSecret = 30;
|
||||
|
||||
// AzureServicePrincipalTenantId specifies the tenant ID of the Azure Service Principal used to access the repo
|
||||
optional string azureServicePrincipalTenantId = 31;
|
||||
|
||||
// AzureActiveDirectoryEndpoint specifies the Azure Active Directory endpoint used for Service Principal authentication. If empty will default to https://login.microsoftonline.com
|
||||
optional string azureActiveDirectoryEndpoint = 32;
|
||||
}
|
||||
|
||||
// RepositoryList is a collection of Repositories.
|
||||
|
|
@ -1973,6 +1985,18 @@ message Repository {
|
|||
// When set, webhook handlers will only trigger reconciliation for affected applications and skip Redis cache
|
||||
// operations for unaffected ones. Recommended for large monorepos with plain YAML manifests.
|
||||
optional bool webhookManifestCacheWarmDisabled = 28;
|
||||
|
||||
// AzureServicePrincipalClientId specifies the client ID of the Azure Service Principal used to access the repo
|
||||
optional string azureServicePrincipalClientId = 29;
|
||||
|
||||
// AzureServicePrincipalClientSecret specifies the client secret of the Azure Service Principal used to access the repo
|
||||
optional string azureServicePrincipalClientSecret = 30;
|
||||
|
||||
// AzureServicePrincipalTenantId specifies the tenant ID of the Azure Service Principal used to access the repo
|
||||
optional string azureServicePrincipalTenantId = 31;
|
||||
|
||||
// AzureActiveDirectoryEndpoint specifies the Azure Active Directory endpoint used for Service Principal authentication. If empty will default to https://login.microsoftonline.com
|
||||
optional string azureActiveDirectoryEndpoint = 32;
|
||||
}
|
||||
|
||||
// A RepositoryCertificate is either SSH known hosts entry or TLS certificate
|
||||
|
|
|
|||
|
|
@ -57,6 +57,14 @@ type RepoCreds struct {
|
|||
BearerToken string `json:"bearerToken,omitempty" protobuf:"bytes,25,opt,name=bearerToken"`
|
||||
// InsecureOCIForceHttp specifies whether the connection to the repository uses TLS at _all_. If true, no TLS. This flag is applicable for OCI repos only.
|
||||
InsecureOCIForceHttp bool `json:"insecureOCIForceHttp,omitempty" protobuf:"bytes,26,opt,name=insecureOCIForceHttp"` //nolint:revive //FIXME(var-naming)
|
||||
// AzureServicePrincipalClientId specifies the client ID of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalClientId string `json:"azureServicePrincipalClientId,omitempty" protobuf:"bytes,29,opt,name=azureServicePrincipalClientId"`
|
||||
// AzureServicePrincipalClientSecret specifies the client secret of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalClientSecret string `json:"azureServicePrincipalClientSecret,omitempty" protobuf:"bytes,30,opt,name=azureServicePrincipalClientSecret"`
|
||||
// AzureServicePrincipalTenantId specifies the tenant ID of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalTenantId string `json:"azureServicePrincipalTenantId,omitempty" protobuf:"bytes,31,opt,name=azureServicePrincipalTenantId"`
|
||||
// AzureActiveDirectoryEndpoint specifies the Azure Active Directory endpoint used for Service Principal authentication. If empty will default to https://login.microsoftonline.com
|
||||
AzureActiveDirectoryEndpoint string `json:"azureActiveDirectoryEndpoint,omitempty" protobuf:"bytes,32,opt,name=azureActiveDirectoryEndpoint"`
|
||||
}
|
||||
|
||||
// Repository is a repository holding application configurations
|
||||
|
|
@ -120,6 +128,14 @@ type Repository struct {
|
|||
// When set, webhook handlers will only trigger reconciliation for affected applications and skip Redis cache
|
||||
// operations for unaffected ones. Recommended for large monorepos with plain YAML manifests.
|
||||
WebhookManifestCacheWarmDisabled bool `json:"webhookManifestCacheWarmDisabled,omitempty" protobuf:"varint,28,opt,name=webhookManifestCacheWarmDisabled"`
|
||||
// AzureServicePrincipalClientId specifies the client ID of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalClientId string `json:"azureServicePrincipalClientId,omitempty" protobuf:"bytes,29,opt,name=azureServicePrincipalClientId"`
|
||||
// AzureServicePrincipalClientSecret specifies the client secret of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalClientSecret string `json:"azureServicePrincipalClientSecret,omitempty" protobuf:"bytes,30,opt,name=azureServicePrincipalClientSecret"`
|
||||
// AzureServicePrincipalTenantId specifies the tenant ID of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalTenantId string `json:"azureServicePrincipalTenantId,omitempty" protobuf:"bytes,31,opt,name=azureServicePrincipalTenantId"`
|
||||
// AzureActiveDirectoryEndpoint specifies the Azure Active Directory endpoint used for Service Principal authentication. If empty will default to https://login.microsoftonline.com
|
||||
AzureActiveDirectoryEndpoint string `json:"azureActiveDirectoryEndpoint,omitempty" protobuf:"bytes,32,opt,name=azureActiveDirectoryEndpoint"`
|
||||
}
|
||||
|
||||
// IsInsecure returns true if the repository has been configured to skip server verification or set to HTTP only
|
||||
|
|
@ -134,7 +150,7 @@ func (repo *Repository) IsLFSEnabled() bool {
|
|||
|
||||
// HasCredentials returns true when the repository has been configured with any credentials
|
||||
func (repo *Repository) HasCredentials() bool {
|
||||
return repo.Username != "" || repo.Password != "" || repo.BearerToken != "" || repo.SSHPrivateKey != "" || repo.TLSClientCertData != "" || repo.GithubAppPrivateKey != "" || repo.UseAzureWorkloadIdentity
|
||||
return repo.Username != "" || repo.Password != "" || repo.BearerToken != "" || repo.SSHPrivateKey != "" || repo.TLSClientCertData != "" || repo.GithubAppPrivateKey != "" || repo.UseAzureWorkloadIdentity || repo.AzureServicePrincipalClientSecret != ""
|
||||
}
|
||||
|
||||
// CopyCredentialsFromRepo copies all credential information from source repository to receiving repository
|
||||
|
|
@ -173,6 +189,18 @@ func (repo *Repository) CopyCredentialsFromRepo(source *Repository) {
|
|||
if repo.GCPServiceAccountKey == "" {
|
||||
repo.GCPServiceAccountKey = source.GCPServiceAccountKey
|
||||
}
|
||||
if repo.AzureServicePrincipalClientId == "" {
|
||||
repo.AzureServicePrincipalClientId = source.AzureServicePrincipalClientId
|
||||
}
|
||||
if repo.AzureServicePrincipalClientSecret == "" {
|
||||
repo.AzureServicePrincipalClientSecret = source.AzureServicePrincipalClientSecret
|
||||
}
|
||||
if repo.AzureServicePrincipalTenantId == "" {
|
||||
repo.AzureServicePrincipalTenantId = source.AzureServicePrincipalTenantId
|
||||
}
|
||||
if repo.AzureActiveDirectoryEndpoint == "" {
|
||||
repo.AzureActiveDirectoryEndpoint = source.AzureActiveDirectoryEndpoint
|
||||
}
|
||||
repo.InsecureOCIForceHttp = source.InsecureOCIForceHttp
|
||||
repo.ForceHttpBasicAuth = source.ForceHttpBasicAuth
|
||||
repo.UseAzureWorkloadIdentity = source.UseAzureWorkloadIdentity
|
||||
|
|
@ -215,6 +243,18 @@ func (repo *Repository) CopyCredentialsFrom(source *RepoCreds) {
|
|||
if repo.GCPServiceAccountKey == "" {
|
||||
repo.GCPServiceAccountKey = source.GCPServiceAccountKey
|
||||
}
|
||||
if repo.AzureServicePrincipalClientId == "" {
|
||||
repo.AzureServicePrincipalClientId = source.AzureServicePrincipalClientId
|
||||
}
|
||||
if repo.AzureServicePrincipalClientSecret == "" {
|
||||
repo.AzureServicePrincipalClientSecret = source.AzureServicePrincipalClientSecret
|
||||
}
|
||||
if repo.AzureServicePrincipalTenantId == "" {
|
||||
repo.AzureServicePrincipalTenantId = source.AzureServicePrincipalTenantId
|
||||
}
|
||||
if repo.AzureActiveDirectoryEndpoint == "" {
|
||||
repo.AzureActiveDirectoryEndpoint = source.AzureActiveDirectoryEndpoint
|
||||
}
|
||||
if repo.Proxy == "" {
|
||||
repo.Proxy = source.Proxy
|
||||
}
|
||||
|
|
@ -252,6 +292,14 @@ func (repo *Repository) GetGitCreds(store git.CredsStore) git.Creds {
|
|||
if repo.UseAzureWorkloadIdentity {
|
||||
return git.NewAzureWorkloadIdentityCreds(store, workloadidentity.NewWorkloadIdentityTokenProvider())
|
||||
}
|
||||
if repo.AzureServicePrincipalClientId != "" && repo.AzureServicePrincipalClientSecret != "" && repo.AzureServicePrincipalTenantId != "" {
|
||||
creds := git.NewAzureServicePrincipalCreds(repo.AzureServicePrincipalTenantId, repo.AzureServicePrincipalClientId, repo.AzureServicePrincipalClientSecret, store).
|
||||
WithActiveDirectoryEndpoint(repo.AzureActiveDirectoryEndpoint).
|
||||
WithClientCert(repo.TLSClientCertData, repo.TLSClientCertKey).
|
||||
WithProxy(repo.Proxy).
|
||||
WithNoProxy(repo.NoProxy)
|
||||
return creds
|
||||
}
|
||||
return git.NopCreds{}
|
||||
}
|
||||
|
||||
|
|
@ -366,6 +414,9 @@ func (repo *Repository) Sanitized() *Repository {
|
|||
GithubAppInstallationId: repo.GithubAppInstallationId,
|
||||
GitHubAppEnterpriseBaseURL: repo.GitHubAppEnterpriseBaseURL,
|
||||
UseAzureWorkloadIdentity: repo.UseAzureWorkloadIdentity,
|
||||
AzureActiveDirectoryEndpoint: repo.AzureActiveDirectoryEndpoint,
|
||||
AzureServicePrincipalClientId: repo.AzureServicePrincipalClientId,
|
||||
AzureServicePrincipalTenantId: repo.AzureServicePrincipalTenantId,
|
||||
Depth: repo.Depth,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,15 @@ func TestGetGitCreds(t *testing.T) {
|
|||
},
|
||||
expected: git.NewGoogleCloudCreds("gcp-key", nil),
|
||||
},
|
||||
{
|
||||
name: "Azure Service Principal credentials",
|
||||
repo: &Repository{
|
||||
AzureServicePrincipalClientId: "client-id",
|
||||
AzureServicePrincipalClientSecret: "client-secret",
|
||||
AzureServicePrincipalTenantId: "tenant-id",
|
||||
},
|
||||
expected: git.NewAzureServicePrincipalCreds("tenant-id", "client-id", "client-secret", nil),
|
||||
},
|
||||
{
|
||||
name: "No credentials",
|
||||
repo: &Repository{},
|
||||
|
|
@ -153,6 +162,9 @@ func TestSanitizedRepository(t *testing.T) {
|
|||
GithubAppInstallationId: 67890,
|
||||
GitHubAppEnterpriseBaseURL: "https://ghe.example.com/api/v3",
|
||||
UseAzureWorkloadIdentity: true,
|
||||
AzureServicePrincipalClientId: "client-id",
|
||||
AzureServicePrincipalClientSecret: "client-secret",
|
||||
AzureServicePrincipalTenantId: "tenant-id",
|
||||
Depth: 1,
|
||||
}
|
||||
|
||||
|
|
@ -174,6 +186,8 @@ func TestSanitizedRepository(t *testing.T) {
|
|||
assert.Equal(t, repo.GithubAppInstallationId, sanitized.GithubAppInstallationId)
|
||||
assert.Equal(t, repo.GitHubAppEnterpriseBaseURL, sanitized.GitHubAppEnterpriseBaseURL)
|
||||
assert.Equal(t, repo.UseAzureWorkloadIdentity, sanitized.UseAzureWorkloadIdentity)
|
||||
assert.Equal(t, repo.AzureServicePrincipalClientId, sanitized.AzureServicePrincipalClientId)
|
||||
assert.Equal(t, repo.AzureServicePrincipalTenantId, sanitized.AzureServicePrincipalTenantId)
|
||||
assert.Equal(t, repo.Depth, sanitized.Depth)
|
||||
|
||||
// Sensitive fields must be stripped
|
||||
|
|
@ -185,6 +199,7 @@ func TestSanitizedRepository(t *testing.T) {
|
|||
assert.Empty(t, sanitized.TLSClientCertKey)
|
||||
assert.Empty(t, sanitized.GCPServiceAccountKey)
|
||||
assert.Empty(t, sanitized.GithubAppPrivateKey)
|
||||
assert.Empty(t, sanitized.AzureServicePrincipalClientSecret)
|
||||
}
|
||||
|
||||
func TestSanitizedRepositoryPreservesDepthZero(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -705,6 +705,10 @@ func (s *Server) ValidateAccess(ctx context.Context, q *repositorypkg.RepoAccess
|
|||
GCPServiceAccountKey: q.GcpServiceAccountKey,
|
||||
InsecureOCIForceHttp: q.InsecureOciForceHttp,
|
||||
UseAzureWorkloadIdentity: q.UseAzureWorkloadIdentity,
|
||||
AzureServicePrincipalClientId: q.AzureServicePrincipalClientId,
|
||||
AzureServicePrincipalClientSecret: q.AzureServicePrincipalClientSecret,
|
||||
AzureServicePrincipalTenantId: q.AzureServicePrincipalTenantId,
|
||||
AzureActiveDirectoryEndpoint: q.AzureActiveDirectoryEndpoint,
|
||||
}
|
||||
|
||||
// If repo does not have credentials, check if there are credentials stored
|
||||
|
|
@ -755,6 +759,10 @@ func (s *Server) ValidateWriteAccess(ctx context.Context, q *repositorypkg.RepoA
|
|||
Proxy: q.Proxy,
|
||||
GCPServiceAccountKey: q.GcpServiceAccountKey,
|
||||
UseAzureWorkloadIdentity: q.UseAzureWorkloadIdentity,
|
||||
AzureServicePrincipalClientId: q.AzureServicePrincipalClientId,
|
||||
AzureServicePrincipalClientSecret: q.AzureServicePrincipalClientSecret,
|
||||
AzureServicePrincipalTenantId: q.AzureServicePrincipalTenantId,
|
||||
AzureActiveDirectoryEndpoint: q.AzureActiveDirectoryEndpoint,
|
||||
}
|
||||
|
||||
err := s.testRepo(ctx, repo)
|
||||
|
|
|
|||
|
|
@ -95,6 +95,14 @@ message RepoAccessQuery {
|
|||
string bearerToken = 21;
|
||||
// Whether https should be disabled for an OCI repo
|
||||
bool insecureOciForceHttp = 22;
|
||||
// Azure Service Principal Client ID
|
||||
string azureServicePrincipalClientId = 23;
|
||||
// Azure Service Principal Client Secret
|
||||
string azureServicePrincipalClientSecret = 24;
|
||||
// Azure Service Principal Tenant ID
|
||||
string azureServicePrincipalTenantId = 25;
|
||||
// Azure Active Directory Endpoint
|
||||
string azureActiveDirectoryEndpoint = 26;
|
||||
}
|
||||
|
||||
message RepoResponse {}
|
||||
|
|
|
|||
|
|
@ -284,6 +284,19 @@ func TestRepositoryServer(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Test_validateWriteAccess", func(t *testing.T) {
|
||||
repoServerClient := &mocks.RepoServerServiceClient{}
|
||||
repoServerClient.EXPECT().TestRepository(mock.Anything, mock.Anything).Return(&apiclient.TestRepositoryResponse{}, nil)
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: repoServerClient}
|
||||
|
||||
s := NewServer(&repoServerClientset, argoDB, enforcer, nil, appLister, projInformer, testNamespace, settingsMgr, true)
|
||||
url := "https://test"
|
||||
_, err := s.ValidateWriteAccess(t.Context(), &repository.RepoAccessQuery{
|
||||
Repo: url,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Test_Get", func(t *testing.T) {
|
||||
repoServerClient := &mocks.RepoServerServiceClient{}
|
||||
repoServerClient.EXPECT().TestRepository(mock.Anything, mock.Anything).Return(&apiclient.TestRepositoryResponse{}, nil)
|
||||
|
|
|
|||
|
|
@ -82,6 +82,21 @@ interface NewGoogleCloudSourceRepoParams {
|
|||
write: boolean;
|
||||
}
|
||||
|
||||
interface NewAzureServicePrincipalRepoParams {
|
||||
type: string;
|
||||
name: string;
|
||||
url: string;
|
||||
azureServicePrincipalClientId: string;
|
||||
azureServicePrincipalClientSecret: string;
|
||||
azureServicePrincipalTenantId: string;
|
||||
azureActiveDirectoryEndpoint: string;
|
||||
proxy: string;
|
||||
noProxy: string;
|
||||
project?: string;
|
||||
// write should be true if saving as a write credential.
|
||||
write: boolean;
|
||||
}
|
||||
|
||||
interface NewSSHRepoCredsParams {
|
||||
url: string;
|
||||
sshPrivateKey: string;
|
||||
|
|
@ -128,11 +143,25 @@ interface NewGoogleCloudSourceRepoCredsParams {
|
|||
write: boolean;
|
||||
}
|
||||
|
||||
interface NewAzureServicePrincipalRepoCredsParams {
|
||||
url: string;
|
||||
azureServicePrincipalClientId: string;
|
||||
azureServicePrincipalClientSecret: string;
|
||||
azureServicePrincipalTenantId: string;
|
||||
azureActiveDirectoryEndpoint: string;
|
||||
proxy: string;
|
||||
noProxy: string;
|
||||
project?: string;
|
||||
// write should be true if saving as a write credential.
|
||||
write: boolean;
|
||||
}
|
||||
|
||||
export enum ConnectionMethod {
|
||||
SSH = 'via SSH',
|
||||
HTTPS = 'via HTTP/HTTPS',
|
||||
GITHUBAPP = 'via GitHub App',
|
||||
GOOGLECLOUD = 'via Google Cloud'
|
||||
GOOGLECLOUD = 'via Google Cloud',
|
||||
AZURESERVICEPRINCIPAL = 'via Azure Service Principal'
|
||||
}
|
||||
|
||||
export const ReposList = ({match, location}: RouteComponentProps) => {
|
||||
|
|
@ -172,8 +201,15 @@ export const ReposList = ({match, location}: RouteComponentProps) => {
|
|||
{method.toUpperCase()} <i className='fa fa-caret-down' />
|
||||
</p>
|
||||
)}
|
||||
items={[ConnectionMethod.SSH, ConnectionMethod.HTTPS, ConnectionMethod.GITHUBAPP, ConnectionMethod.GOOGLECLOUD].map(
|
||||
(connectMethod: ConnectionMethod.SSH | ConnectionMethod.HTTPS | ConnectionMethod.GITHUBAPP | ConnectionMethod.GOOGLECLOUD) => ({
|
||||
items={[ConnectionMethod.SSH, ConnectionMethod.HTTPS, ConnectionMethod.GITHUBAPP, ConnectionMethod.GOOGLECLOUD, ConnectionMethod.AZURESERVICEPRINCIPAL].map(
|
||||
(
|
||||
connectMethod:
|
||||
| ConnectionMethod.SSH
|
||||
| ConnectionMethod.HTTPS
|
||||
| ConnectionMethod.GITHUBAPP
|
||||
| ConnectionMethod.GOOGLECLOUD
|
||||
| ConnectionMethod.AZURESERVICEPRINCIPAL
|
||||
) => ({
|
||||
title: connectMethod.toUpperCase(),
|
||||
action: () => {
|
||||
onSelection(connectMethod);
|
||||
|
|
@ -191,7 +227,7 @@ export const ReposList = ({match, location}: RouteComponentProps) => {
|
|||
};
|
||||
|
||||
const onChooseDefaultValues = (): FormValues => {
|
||||
return {type: 'git', ghType: 'GitHub', write: false};
|
||||
return {type: 'git', ghType: 'GitHub', azureType: 'Azure Public Cloud', write: false};
|
||||
};
|
||||
|
||||
const onValidateErrors = (params: FormValues): FormErrors => {
|
||||
|
|
@ -233,6 +269,16 @@ export const ReposList = ({match, location}: RouteComponentProps) => {
|
|||
gcpServiceAccountKey: !googleCloudValues.gcpServiceAccountKey && 'GCP service account key is required',
|
||||
depth: googleCloudValues.depth != undefined && googleCloudValues.depth < 0 && 'Depth must be a non-negative number'
|
||||
};
|
||||
case ConnectionMethod.AZURESERVICEPRINCIPAL:
|
||||
const azureServicePrincipalValues = params as NewAzureServicePrincipalRepoParams;
|
||||
return {
|
||||
url:
|
||||
(!azureServicePrincipalValues.url && 'Repository URL is required') ||
|
||||
(credsTemplate && !isHTTPOrHTTPSUrl(azureServicePrincipalValues.url) && 'Not a valid HTTP/HTTPS URL'),
|
||||
azureServicePrincipalClientId: !azureServicePrincipalValues.azureServicePrincipalClientId && 'Azure Service Principal Client ID is required',
|
||||
azureServicePrincipalClientSecret: !azureServicePrincipalValues.azureServicePrincipalClientSecret && 'Azure Service Principal Client Secret is required',
|
||||
azureServicePrincipalTenantId: !azureServicePrincipalValues.azureServicePrincipalTenantId && 'Azure Service Principal Tenant ID is required'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -283,6 +329,8 @@ export const ReposList = ({match, location}: RouteComponentProps) => {
|
|||
return connectGitHubAppRepo(params as NewGitHubAppRepoParams);
|
||||
case ConnectionMethod.GOOGLECLOUD:
|
||||
return connectGoogleCloudSourceRepo(params as NewGoogleCloudSourceRepoParams);
|
||||
case ConnectionMethod.AZURESERVICEPRINCIPAL:
|
||||
return connectAzureServicePrincipalRepo(params as NewAzureServicePrincipalRepoParams);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -313,9 +361,9 @@ export const ReposList = ({match, location}: RouteComponentProps) => {
|
|||
return url.replace('https://', '').replace('oci://', '');
|
||||
};
|
||||
|
||||
// only connections of git type which is not via GitHub App are updatable
|
||||
// only connections of git type which are not via GitHub App or Azure Service Principal are updatable
|
||||
const isRepoUpdatable = (repo: models.Repository) => {
|
||||
return isHTTPOrHTTPSUrl(repo.repo) && repo.type === 'git' && !repo.githubAppID;
|
||||
return isHTTPOrHTTPSUrl(repo.repo) && repo.type === 'git' && !repo.githubAppID && !repo.azureServicePrincipalClientId;
|
||||
};
|
||||
|
||||
// Forces a reload of configured repositories, circumventing the cache
|
||||
|
|
@ -466,7 +514,7 @@ export const ReposList = ({match, location}: RouteComponentProps) => {
|
|||
}
|
||||
};
|
||||
|
||||
// Connect a new repository or create a repository credentials for GitHub App repositories
|
||||
// Connect a new repository or create a repository credentials for Google Cloud Source repositories
|
||||
const connectGoogleCloudSourceRepo = async (params: NewGoogleCloudSourceRepoParams) => {
|
||||
if (credsTemplate.current) {
|
||||
createGoogleCloudSourceCreds({
|
||||
|
|
@ -495,6 +543,40 @@ export const ReposList = ({match, location}: RouteComponentProps) => {
|
|||
}
|
||||
};
|
||||
|
||||
// Connect a new repository or create a repository credentials for Azure Service Principal repositories
|
||||
const connectAzureServicePrincipalRepo = async (params: NewAzureServicePrincipalRepoParams) => {
|
||||
if (credsTemplate.current) {
|
||||
createAzureServicePrincipalCreds({
|
||||
url: params.url,
|
||||
azureServicePrincipalClientId: params.azureServicePrincipalClientId,
|
||||
azureServicePrincipalClientSecret: params.azureServicePrincipalClientSecret,
|
||||
azureServicePrincipalTenantId: params.azureServicePrincipalTenantId,
|
||||
azureActiveDirectoryEndpoint: params.azureActiveDirectoryEndpoint,
|
||||
proxy: params.proxy,
|
||||
noProxy: params.noProxy,
|
||||
write: params.write
|
||||
});
|
||||
} else {
|
||||
setConnecting(true);
|
||||
try {
|
||||
if (params.write) {
|
||||
await services.repos.createAzureServicePrincipalWrite(params);
|
||||
} else {
|
||||
await services.repos.createAzureServicePrincipal(params);
|
||||
}
|
||||
repoLoader.current.reload();
|
||||
setConnectRepo(false);
|
||||
} catch (e) {
|
||||
ctx.notifications.show({
|
||||
content: <ErrorNotification title='Unable to connect Azure Service Principal repository' e={e} />,
|
||||
type: NotificationType.Error
|
||||
});
|
||||
} finally {
|
||||
setConnecting(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const createHTTPSCreds = async (params: NewHTTPSRepoCredsParams) => {
|
||||
try {
|
||||
if (params.write) {
|
||||
|
|
@ -563,6 +645,23 @@ export const ReposList = ({match, location}: RouteComponentProps) => {
|
|||
}
|
||||
};
|
||||
|
||||
const createAzureServicePrincipalCreds = async (params: NewAzureServicePrincipalRepoCredsParams) => {
|
||||
try {
|
||||
if (params.write) {
|
||||
await services.repocreds.createAzureServicePrincipalWrite(params);
|
||||
} else {
|
||||
await services.repocreds.createAzureServicePrincipal(params);
|
||||
}
|
||||
credsLoader.current.reload();
|
||||
setConnectRepo(false);
|
||||
} catch (e) {
|
||||
ctx.notifications.show({
|
||||
content: <ErrorNotification title='Unable to create Azure Service Principal credentials' e={e} />,
|
||||
type: NotificationType.Error
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Remove a repository from the configuration
|
||||
const disconnectRepo = async (repo: string, project: string, write: boolean) => {
|
||||
const confirmed = await ctx.popup.confirm('Disconnect repository', `Are you sure you want to disconnect '${repo}'?`);
|
||||
|
|
@ -1322,6 +1421,59 @@ export const ReposList = ({match, location}: RouteComponentProps) => {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
{method === ConnectionMethod.AZURESERVICEPRINCIPAL && (
|
||||
<div className='white-box'>
|
||||
<p>CONNECT REPO USING AZURE SERVICE PRINCIPAL</p>
|
||||
<div className='argo-form-row'>
|
||||
<FormField
|
||||
formApi={formApi}
|
||||
label='Type'
|
||||
field='azureType'
|
||||
component={FormSelect}
|
||||
componentProps={{options: ['Azure Public Cloud', 'Azure Other Cloud']}}
|
||||
/>
|
||||
</div>
|
||||
{formApi.getFormState().values.azureType === 'Azure Other Cloud' && (
|
||||
<div className='argo-form-row'>
|
||||
<FormField
|
||||
formApi={formApi}
|
||||
label='Azure Active Directory Endpoint (e.g. https://login.microsoftonline.de)'
|
||||
field='azureActiveDirectoryEndpoint'
|
||||
component={Text}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={formApi} label='Project' field='project' component={AutocompleteField} componentProps={{items: projects}} />
|
||||
</div>
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={formApi} label='Repository URL' field='url' component={Text} />
|
||||
</div>
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={formApi} label='AzureTenant ID' field='azureServicePrincipalTenantId' component={Text} />
|
||||
</div>
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={formApi} label='Azure Client ID' field='azureServicePrincipalClientId' component={Text} />
|
||||
</div>
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={formApi} label='Azure Client Secret' field='azureServicePrincipalClientSecret' component={Text} />
|
||||
</div>
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={formApi} label='Skip server verification' field='insecure' component={CheckboxField} />
|
||||
<HelpIcon title='This setting is ignored when creating as credential template.' />
|
||||
</div>
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={formApi} label='Enable LFS support (Git only)' field='enableLfs' component={CheckboxField} />
|
||||
<HelpIcon title='This setting is ignored when creating as credential template.' />
|
||||
</div>
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={formApi} label='Proxy (optional)' field='proxy' component={Text} />
|
||||
</div>
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={formApi} label='NoProxy (optional)' field='noProxy' component={Text} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
)}
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -677,6 +677,10 @@ export interface Repository {
|
|||
enableOCI: boolean;
|
||||
useAzureWorkloadIdentity: boolean;
|
||||
depth?: number;
|
||||
azureServicePrincipalClientId?: string;
|
||||
azureServicePrincipalClientSecret?: string;
|
||||
azureServicePrincipalTenantId?: string;
|
||||
azureActiveDirectoryEndpoint?: string;
|
||||
}
|
||||
|
||||
export interface RepositoryList extends ItemsList<Repository> {}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,19 @@ export interface GoogleCloudSourceQuery {
|
|||
depth?: number;
|
||||
}
|
||||
|
||||
export interface AzureServicePrincipalQuery {
|
||||
type: string;
|
||||
name: string;
|
||||
url: string;
|
||||
azureActiveDirectoryEndpoint: string;
|
||||
azureServicePrincipalClientId: string;
|
||||
azureServicePrincipalClientSecret: string;
|
||||
azureServicePrincipalTenantId: string;
|
||||
proxy: string;
|
||||
noProxy: string;
|
||||
project?: string;
|
||||
}
|
||||
|
||||
export class RepositoriesService {
|
||||
public list(): Promise<models.Repository[]> {
|
||||
return requests
|
||||
|
|
@ -311,6 +324,42 @@ export class RepositoriesService {
|
|||
.then(res => res.body as models.Repository);
|
||||
}
|
||||
|
||||
public createAzureServicePrincipal(q: AzureServicePrincipalQuery): Promise<models.Repository> {
|
||||
return requests
|
||||
.post('/repositories')
|
||||
.send({
|
||||
type: q.type,
|
||||
name: q.name,
|
||||
repo: q.url,
|
||||
azureServicePrincipalClientId: q.azureServicePrincipalClientId,
|
||||
azureServicePrincipalClientSecret: q.azureServicePrincipalClientSecret,
|
||||
azureServicePrincipalTenantId: q.azureServicePrincipalTenantId,
|
||||
azureActiveDirectoryEndpoint: q.azureActiveDirectoryEndpoint,
|
||||
proxy: q.proxy,
|
||||
noProxy: q.noProxy,
|
||||
project: q.project
|
||||
})
|
||||
.then(res => res.body as models.Repository);
|
||||
}
|
||||
|
||||
public createAzureServicePrincipalWrite(q: AzureServicePrincipalQuery): Promise<models.Repository> {
|
||||
return requests
|
||||
.post('/write-repositories')
|
||||
.send({
|
||||
type: q.type,
|
||||
name: q.name,
|
||||
repo: q.url,
|
||||
azureServicePrincipalClientId: q.azureServicePrincipalClientId,
|
||||
azureServicePrincipalClientSecret: q.azureServicePrincipalClientSecret,
|
||||
azureServicePrincipalTenantId: q.azureServicePrincipalTenantId,
|
||||
azureActiveDirectoryEndpoint: q.azureActiveDirectoryEndpoint,
|
||||
proxy: q.proxy,
|
||||
noProxy: q.noProxy,
|
||||
project: q.project
|
||||
})
|
||||
.then(res => res.body as models.Repository);
|
||||
}
|
||||
|
||||
public delete(url: string, project: string): Promise<models.Repository> {
|
||||
return requests
|
||||
.delete(`/repositories/${encodeURIComponent(url)}?appProject=${project}`)
|
||||
|
|
|
|||
|
|
@ -37,6 +37,16 @@ export interface GoogleCloudSourceCreds {
|
|||
gcpServiceAccountKey: string;
|
||||
}
|
||||
|
||||
export interface AzureServicePrincipalCreds {
|
||||
url: string;
|
||||
azureActiveDirectoryEndpoint: string;
|
||||
azureServicePrincipalClientId: string;
|
||||
azureServicePrincipalClientSecret: string;
|
||||
azureServicePrincipalTenantId: string;
|
||||
proxy: string;
|
||||
noProxy: string;
|
||||
}
|
||||
|
||||
export class RepoCredsService {
|
||||
public list(): Promise<models.RepoCreds[]> {
|
||||
return requests
|
||||
|
|
@ -108,6 +118,20 @@ export class RepoCredsService {
|
|||
.then(res => res.body as models.RepoCreds);
|
||||
}
|
||||
|
||||
public createAzureServicePrincipal(creds: AzureServicePrincipalCreds): Promise<models.RepoCreds> {
|
||||
return requests
|
||||
.post('/repocreds')
|
||||
.send(creds)
|
||||
.then(res => res.body as models.RepoCreds);
|
||||
}
|
||||
|
||||
public createAzureServicePrincipalWrite(creds: AzureServicePrincipalCreds): Promise<models.RepoCreds> {
|
||||
return requests
|
||||
.post('/write-repocreds')
|
||||
.send(creds)
|
||||
.then(res => res.body as models.RepoCreds);
|
||||
}
|
||||
|
||||
public delete(url: string): Promise<models.RepoCreds> {
|
||||
return requests
|
||||
.delete(`/repocreds/${encodeURIComponent(url)}`)
|
||||
|
|
|
|||
|
|
@ -345,6 +345,10 @@ func secretToRepository(secret *corev1.Secret) (*appsv1.Repository, error) {
|
|||
NoProxy: string(secretCopy.Data["noProxy"]),
|
||||
Project: string(secretCopy.Data["project"]),
|
||||
GCPServiceAccountKey: string(secretCopy.Data["gcpServiceAccountKey"]),
|
||||
AzureServicePrincipalClientId: string(secretCopy.Data["azureServicePrincipalClientId"]),
|
||||
AzureServicePrincipalClientSecret: string(secretCopy.Data["azureServicePrincipalClientSecret"]),
|
||||
AzureServicePrincipalTenantId: string(secretCopy.Data["azureServicePrincipalTenantId"]),
|
||||
AzureActiveDirectoryEndpoint: string(secretCopy.Data["azureActiveDirectoryEndpoint"]),
|
||||
}
|
||||
|
||||
insecureIgnoreHostKey, err := boolOrFalse(secretCopy, "insecureIgnoreHostKey")
|
||||
|
|
@ -451,6 +455,10 @@ func (s *secretsRepositoryBackend) repositoryToSecret(repository *appsv1.Reposit
|
|||
updateSecretBool(secretCopy, "useAzureWorkloadIdentity", repository.UseAzureWorkloadIdentity)
|
||||
updateSecretInt(secretCopy, "depth", repository.Depth)
|
||||
updateSecretBool(secretCopy, "webhookManifestCacheWarmDisabled", repository.WebhookManifestCacheWarmDisabled)
|
||||
updateSecretString(secretCopy, "azureServicePrincipalClientId", repository.AzureServicePrincipalClientId)
|
||||
updateSecretString(secretCopy, "azureServicePrincipalClientSecret", repository.AzureServicePrincipalClientSecret)
|
||||
updateSecretString(secretCopy, "azureServicePrincipalTenantId", repository.AzureServicePrincipalTenantId)
|
||||
updateSecretString(secretCopy, "azureActiveDirectoryEndpoint", repository.AzureActiveDirectoryEndpoint)
|
||||
addSecretMetadata(secretCopy, s.getSecretType())
|
||||
|
||||
return secretCopy
|
||||
|
|
@ -473,6 +481,10 @@ func (s *secretsRepositoryBackend) secretToRepoCred(secret *corev1.Secret) (*app
|
|||
GCPServiceAccountKey: string(secretCopy.Data["gcpServiceAccountKey"]),
|
||||
Proxy: string(secretCopy.Data["proxy"]),
|
||||
NoProxy: string(secretCopy.Data["noProxy"]),
|
||||
AzureServicePrincipalClientId: string(secretCopy.Data["azureServicePrincipalClientID"]),
|
||||
AzureServicePrincipalClientSecret: string(secretCopy.Data["azureServicePrincipalClientSecret"]),
|
||||
AzureServicePrincipalTenantId: string(secretCopy.Data["azureServicePrincipalTenantID"]),
|
||||
AzureActiveDirectoryEndpoint: string(secretCopy.Data["azureActiveDirectoryEndpoint"]),
|
||||
}
|
||||
|
||||
enableOCI, err := boolOrFalse(secretCopy, "enableOCI")
|
||||
|
|
@ -540,6 +552,10 @@ func (s *secretsRepositoryBackend) repoCredsToSecret(repoCreds *appsv1.RepoCreds
|
|||
updateSecretString(secretCopy, "noProxy", repoCreds.NoProxy)
|
||||
updateSecretBool(secretCopy, "forceHttpBasicAuth", repoCreds.ForceHttpBasicAuth)
|
||||
updateSecretBool(secretCopy, "useAzureWorkloadIdentity", repoCreds.UseAzureWorkloadIdentity)
|
||||
updateSecretString(secretCopy, "azureServicePrincipalClientID", repoCreds.AzureServicePrincipalClientId)
|
||||
updateSecretString(secretCopy, "azureServicePrincipalClientSecret", repoCreds.AzureServicePrincipalClientSecret)
|
||||
updateSecretString(secretCopy, "azureServicePrincipalTenantID", repoCreds.AzureServicePrincipalTenantId)
|
||||
updateSecretString(secretCopy, "azureActiveDirectoryEndpoint", repoCreds.AzureActiveDirectoryEndpoint)
|
||||
addSecretMetadata(secretCopy, s.getRepoCredSecretType())
|
||||
|
||||
return secretCopy
|
||||
|
|
|
|||
|
|
@ -412,6 +412,13 @@ func newAuth(repoURL string, creds Creds) (transport.AuthMethod, error) {
|
|||
return nil, fmt.Errorf("failed to get access token from creds: %w", err)
|
||||
}
|
||||
|
||||
auth := githttp.TokenAuth{Token: token}
|
||||
return &auth, nil
|
||||
case AzureServicePrincipalCreds:
|
||||
token, err := creds.getAccessToken()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get access token from creds: %w", err)
|
||||
}
|
||||
auth := githttp.TokenAuth{Token: token}
|
||||
return &auth, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
giturls "github.com/chainguard-dev/git-urls"
|
||||
"github.com/google/go-github/v69/github"
|
||||
|
||||
|
|
@ -50,6 +54,8 @@ var (
|
|||
// installationIdCache caches installation IDs for organizations to avoid redundant API calls.
|
||||
githubInstallationIdCache *gocache.Cache
|
||||
githubInstallationIdCacheMutex sync.RWMutex // For bulk API call coordination
|
||||
// In memory cache for storing Azure Service Principal tokens
|
||||
azureServicePrincipalTokenCache *gocache.Cache
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -64,16 +70,30 @@ const (
|
|||
func init() {
|
||||
githubAppCredsExp := common.GithubAppCredsExpirationDuration
|
||||
if exp := os.Getenv(common.EnvGithubAppCredsExpirationDuration); exp != "" {
|
||||
if qps, err := strconv.Atoi(exp); err != nil {
|
||||
if qps, err := strconv.Atoi(exp); err == nil {
|
||||
githubAppCredsExp = time.Duration(qps) * time.Minute
|
||||
}
|
||||
}
|
||||
azureServicePrincipalCredsExp := common.AzureServicePrincipalCredsExpirationDuration
|
||||
if exp := os.Getenv(common.EnvAzureServicePrincipalCredsExpirationDuration); exp != "" {
|
||||
if qps, err := strconv.Atoi(exp); err == nil {
|
||||
// Azure service principal tokens are valid for 60 minutes
|
||||
// the cache has a cleanup interval of 1 minute
|
||||
// cap the expiration duration to 59 minutes to avoid issues with token expiration
|
||||
if qps > 59 {
|
||||
log.Warnf("Value in %s is %d, which is greater than maximum 59 minutes allowed. Setting to 59 minutes", common.EnvAzureServicePrincipalCredsExpirationDuration, qps)
|
||||
qps = 59
|
||||
}
|
||||
azureServicePrincipalCredsExp = time.Duration(qps) * time.Minute
|
||||
}
|
||||
}
|
||||
|
||||
githubAppTokenCache = gocache.New(githubAppCredsExp, 1*time.Minute)
|
||||
// oauth2.TokenSource handles fetching new Tokens once they are expired. The oauth2.TokenSource itself does not expire.
|
||||
googleCloudTokenSource = gocache.New(gocache.NoExpiration, 0)
|
||||
azureTokenCache = gocache.New(gocache.NoExpiration, 0)
|
||||
githubInstallationIdCache = gocache.New(60*time.Minute, 60*time.Minute)
|
||||
azureServicePrincipalTokenCache = gocache.New(azureServicePrincipalCredsExp, 1*time.Minute)
|
||||
}
|
||||
|
||||
type NoopCredsStore struct{}
|
||||
|
|
@ -974,3 +994,133 @@ func (creds AzureWorkloadIdentityCreds) GetAzureDevOpsAccessToken() (string, err
|
|||
accessToken, err := creds.getAccessToken(azureDevopsEntraResourceId) // wellknown resourceid of Azure DevOps
|
||||
return accessToken, err
|
||||
}
|
||||
|
||||
var _ Creds = AzureServicePrincipalCreds{}
|
||||
|
||||
// AzureServicePrincipalCreds to authenticate to Azure DevOps using a Service Principal
|
||||
type AzureServicePrincipalCreds struct {
|
||||
tenantID string
|
||||
clientID string
|
||||
clientSecret string
|
||||
activeDirectoryEndpoint string
|
||||
clientCertData string
|
||||
clientCertKey string
|
||||
proxy string
|
||||
noProxy string
|
||||
store CredsStore
|
||||
}
|
||||
|
||||
// NewAzureServicePrincipalCreds creates new Azure Service Principal credentials
|
||||
func NewAzureServicePrincipalCreds(tenantID string, clientID string, clientSecret string, store CredsStore) AzureServicePrincipalCreds {
|
||||
return AzureServicePrincipalCreds{tenantID: tenantID, clientID: clientID, clientSecret: clientSecret, store: store}
|
||||
}
|
||||
|
||||
// WithActiveDirectoryEndpoint sets a custom Active Directory endpoint. When not set, the default Azure public cloud is used.
|
||||
func (a AzureServicePrincipalCreds) WithActiveDirectoryEndpoint(activeDirectoryEndpoint string) AzureServicePrincipalCreds {
|
||||
if activeDirectoryEndpoint != "" {
|
||||
a.activeDirectoryEndpoint = activeDirectoryEndpoint
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// WithClientCert sets the client certificate data and key
|
||||
func (a AzureServicePrincipalCreds) WithClientCert(data string, key string) AzureServicePrincipalCreds {
|
||||
if data != "" && key != "" {
|
||||
a.clientCertData = data
|
||||
a.clientCertKey = key
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// WithProxy sets the HTTP/HTTPS proxy used to access the repo
|
||||
func (a AzureServicePrincipalCreds) WithProxy(proxy string) AzureServicePrincipalCreds {
|
||||
if proxy != "" {
|
||||
a.proxy = proxy
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// WithNoProxy sets a comma separated list of IPs/hostnames that should not use the proxy
|
||||
func (a AzureServicePrincipalCreds) WithNoProxy(noProxy string) AzureServicePrincipalCreds {
|
||||
if noProxy != "" {
|
||||
a.noProxy = noProxy
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// GetUserInfo doesn't return any user info as they are not present for Azure Service Principals.
|
||||
func (a AzureServicePrincipalCreds) GetUserInfo(_ context.Context) (string, string, error) {
|
||||
return workloadidentity.EmptyGuid, "", nil
|
||||
}
|
||||
|
||||
func (a AzureServicePrincipalCreds) Environ() (io.Closer, []string, error) {
|
||||
token, err := a.getAccessToken()
|
||||
if err != nil {
|
||||
return NopCloser{}, nil, err
|
||||
}
|
||||
nonce := a.store.Add("", token)
|
||||
env := a.store.Environ(nonce)
|
||||
env = append(env, fmt.Sprintf("%s=Authorization: Bearer %s", bearerAuthHeaderEnv, token))
|
||||
|
||||
return utilio.NewCloser(func() error {
|
||||
a.store.Remove(nonce)
|
||||
return nil
|
||||
}), env, nil
|
||||
}
|
||||
|
||||
func (a AzureServicePrincipalCreds) getAccessToken() (string, error) {
|
||||
// Override the default active directory endpoint if present
|
||||
activeDirectoryEndpoint := "https://login.microsoftonline.com"
|
||||
disableInstanceDiscovery := false
|
||||
if a.activeDirectoryEndpoint != "" {
|
||||
activeDirectoryEndpoint = a.activeDirectoryEndpoint
|
||||
disableInstanceDiscovery = true
|
||||
}
|
||||
|
||||
// Generate cache key for creds
|
||||
key, err := argoutils.GenerateCacheKey("%s %s %s %s", a.tenantID, a.clientID, a.clientSecret, activeDirectoryEndpoint)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get get SHA256 hash for Azure Service Principal credentials: %w", err)
|
||||
}
|
||||
|
||||
t, found := azureServicePrincipalTokenCache.Get(key)
|
||||
if found {
|
||||
return t.(string), nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
opts := azcore.ClientOptions{}
|
||||
opts.Cloud = cloud.Configuration{
|
||||
ActiveDirectoryAuthorityHost: activeDirectoryEndpoint,
|
||||
}
|
||||
// Configure HTTP client with proxy if proxy is set
|
||||
if a.proxy != "" {
|
||||
opts.Transport = GetRepoHTTPClient(activeDirectoryEndpoint, false, a, a.proxy, a.noProxy)
|
||||
}
|
||||
cred, err := azidentity.NewClientSecretCredential(a.tenantID, a.clientID, a.clientSecret, &azidentity.ClientSecretCredentialOptions{ClientOptions: opts, DisableInstanceDiscovery: disableInstanceDiscovery})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create Azure client secret credential: %w", err)
|
||||
}
|
||||
token, err := cred.GetToken(ctx, policy.TokenRequestOptions{
|
||||
Scopes: []string{azureDevopsEntraResourceId},
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get Azure access token: %w", err)
|
||||
}
|
||||
azureServicePrincipalTokenCache.Set(key, token.Token, 0)
|
||||
return token.Token, nil
|
||||
}
|
||||
|
||||
func (a AzureServicePrincipalCreds) HasClientCert() bool {
|
||||
return a.clientCertData != "" && a.clientCertKey != ""
|
||||
}
|
||||
|
||||
func (a AzureServicePrincipalCreds) GetClientCertData() string {
|
||||
return a.clientCertData
|
||||
}
|
||||
|
||||
func (a AzureServicePrincipalCreds) GetClientCertKey() string {
|
||||
return a.clientCertKey
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,6 +326,14 @@ type Repository struct {
|
|||
ForceHttpBasicAuth bool `json:"forceHttpBasicAuth,omitempty"` //nolint:revive //FIXME(var-naming)
|
||||
// UseAzureWorkloadIdentity specifies whether to use Azure Workload Identity for authentication
|
||||
UseAzureWorkloadIdentity bool `json:"useAzureWorkloadIdentity,omitempty"`
|
||||
// AzureActiveDirectoryEndpoint specifies the Azure Active Directory endpoint used for Service Principal authentication. If empty will default to https://login.microsoftonline.com
|
||||
AzureActiveDirectoryEndpoint string `json:"azureActiveDirectoryEndpoint,omitempty"`
|
||||
// AzureServicePrincipalClientId specifies the client ID of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalClientId string `json:"azureServicePrincipalClientId,omitempty"`
|
||||
// AzureServicePrincipalClientSecret specifies the client secret of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalClientSecret string `json:"azureServicePrincipalClientSecret,omitempty"`
|
||||
// AzureServicePrincipalTenantId specifies the tenant ID of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalTenantId string `json:"azureServicePrincipalTenantId,omitempty"`
|
||||
}
|
||||
|
||||
// Credential template for accessing repositories
|
||||
|
|
@ -360,6 +368,14 @@ type RepositoryCredentials struct {
|
|||
ForceHttpBasicAuth bool `json:"forceHttpBasicAuth,omitempty"` //nolint:revive //FIXME(var-naming)
|
||||
// UseAzureWorkloadIdentity specifies whether to use Azure Workload Identity for authentication
|
||||
UseAzureWorkloadIdentity bool `json:"useAzureWorkloadIdentity,omitempty"`
|
||||
// AzureActiveDirectoryEndpoint specifies the Azure Active Directory endpoint used for Service Principal authentication. If empty will default to https://login.microsoftonline.com
|
||||
AzureActiveDirectoryEndpoint string `json:"azureActiveDirectoryEndpoint,omitempty"`
|
||||
// AzureServicePrincipalClientId specifies the client ID of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalClientId string `json:"azureServicePrincipalClientId,omitempty"`
|
||||
// AzureServicePrincipalClientSecret specifies the client secret of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalClientSecret string `json:"azureServicePrincipalClientSecret,omitempty"`
|
||||
// AzureServicePrincipalTenantId specifies the tenant ID of the Azure Service Principal used to access the repo
|
||||
AzureServicePrincipalTenantId string `json:"azureServicePrincipalTenantId,omitempty"`
|
||||
}
|
||||
|
||||
// DeepLink structure
|
||||
|
|
|
|||
Loading…
Reference in a new issue