mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-02-20 01:28:45 +01:00
feat: add bearer token auth (#21462)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io> Co-authored-by: Pasha Kostohrys <pasha.kostohrys@gmail.com>
This commit is contained in:
20
assets/swagger.json
generated
20
assets/swagger.json
generated
@@ -3777,6 +3777,12 @@
|
||||
"description": "Whether to use azure workload identity for authentication.",
|
||||
"name": "useAzureWorkloadIdentity",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "BearerToken contains the bearer token used for Git auth at the repo server.",
|
||||
"name": "bearerToken",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -4609,6 +4615,12 @@
|
||||
"description": "Whether to use azure workload identity for authentication.",
|
||||
"name": "useAzureWorkloadIdentity",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "BearerToken contains the bearer token used for Git auth at the repo server.",
|
||||
"name": "bearerToken",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -8912,6 +8924,10 @@
|
||||
"type": "object",
|
||||
"title": "RepoCreds holds the definition for repository credentials",
|
||||
"properties": {
|
||||
"bearerToken": {
|
||||
"type": "string",
|
||||
"title": "BearerToken contains the bearer token used for Git BitBucket Data Center auth at the repo server"
|
||||
},
|
||||
"enableOCI": {
|
||||
"type": "boolean",
|
||||
"title": "EnableOCI specifies whether helm-oci support should be enabled for this repo"
|
||||
@@ -9003,6 +9019,10 @@
|
||||
"type": "object",
|
||||
"title": "Repository is a repository holding application configurations",
|
||||
"properties": {
|
||||
"bearerToken": {
|
||||
"type": "string",
|
||||
"title": "BearerToken contains the bearer token used for Git BitBucket Data Center auth at the repo server"
|
||||
},
|
||||
"connectionState": {
|
||||
"$ref": "#/definitions/v1alpha1ConnectionState"
|
||||
},
|
||||
|
||||
@@ -54,6 +54,9 @@ func NewGenRepoSpecCommand() *cobra.Command {
|
||||
# Add a private Git repository via HTTPS using username/password and TLS client certificates:
|
||||
argocd admin repo generate-spec https://git.example.com/repos/repo --username git --password secret --tls-client-cert-path ~/mycert.crt --tls-client-cert-key-path ~/mycert.key
|
||||
|
||||
# Add a private Git BitBucket Data Center repository via HTTPS using bearer token:
|
||||
argocd admin repo generate-spec https://bitbucket.example.com/scm/proj/repo --bearer-token secret-token
|
||||
|
||||
# Add a private Git repository via HTTPS using username/password without verifying the server's TLS certificate
|
||||
argocd admin repo generate-spec https://git.example.com/repos/repo --username git --password secret --insecure-skip-server-verification
|
||||
|
||||
@@ -138,6 +141,13 @@ func NewGenRepoSpecCommand() *cobra.Command {
|
||||
repoOpts.Repo.Password = cli.PromptPassword(repoOpts.Repo.Password)
|
||||
}
|
||||
|
||||
err := cmdutil.ValidateBearerTokenAndPasswordCombo(repoOpts.Repo.BearerToken, repoOpts.Repo.Password)
|
||||
errors.CheckError(err)
|
||||
err = cmdutil.ValidateBearerTokenForHTTPSRepoOnly(repoOpts.Repo.BearerToken, git.IsHTTPSURL(repoOpts.Repo.Repo))
|
||||
errors.CheckError(err)
|
||||
err = cmdutil.ValidateBearerTokenForGitOnly(repoOpts.Repo.BearerToken, repoOpts.Repo.Type)
|
||||
errors.CheckError(err)
|
||||
|
||||
argoCDCM := &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "ConfigMap",
|
||||
@@ -155,7 +165,7 @@ func NewGenRepoSpecCommand() *cobra.Command {
|
||||
settingsMgr := settings.NewSettingsManager(ctx, kubeClientset, ArgoCDNamespace)
|
||||
argoDB := db.NewDB(ArgoCDNamespace, settingsMgr, kubeClientset)
|
||||
|
||||
_, err := argoDB.CreateRepository(ctx, &repoOpts.Repo)
|
||||
_, err = argoDB.CreateRepository(ctx, &repoOpts.Repo)
|
||||
errors.CheckError(err)
|
||||
|
||||
secret, err := kubeClientset.CoreV1().Secrets(ArgoCDNamespace).Get(ctx, db.RepoURLToSecretName(repoSecretPrefix, repoOpts.Repo.Repo, repoOpts.Repo.Project), metav1.GetOptions{})
|
||||
|
||||
@@ -197,6 +197,13 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
repoOpts.Repo.Password = cli.PromptPassword(repoOpts.Repo.Password)
|
||||
}
|
||||
|
||||
err := cmdutil.ValidateBearerTokenAndPasswordCombo(repoOpts.Repo.BearerToken, repoOpts.Repo.Password)
|
||||
errors.CheckError(err)
|
||||
err = cmdutil.ValidateBearerTokenForGitOnly(repoOpts.Repo.BearerToken, repoOpts.Repo.Type)
|
||||
errors.CheckError(err)
|
||||
err = cmdutil.ValidateBearerTokenForHTTPSRepoOnly(repoOpts.Repo.BearerToken, git.IsHTTPSURL(repoOpts.Repo.Repo))
|
||||
errors.CheckError(err)
|
||||
|
||||
// We let the server check access to the repository before adding it. If
|
||||
// it is a private repo, but we cannot access with with the credentials
|
||||
// that were supplied, we bail out.
|
||||
@@ -210,6 +217,7 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
Name: repoOpts.Repo.Name,
|
||||
Username: repoOpts.Repo.Username,
|
||||
Password: repoOpts.Repo.Password,
|
||||
BearerToken: repoOpts.Repo.BearerToken,
|
||||
SshPrivateKey: repoOpts.Repo.SSHPrivateKey,
|
||||
TlsClientCertData: repoOpts.Repo.TLSClientCertData,
|
||||
TlsClientCertKey: repoOpts.Repo.TLSClientCertKey,
|
||||
@@ -225,7 +233,7 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
ForceHttpBasicAuth: repoOpts.Repo.ForceHttpBasicAuth,
|
||||
UseAzureWorkloadIdentity: repoOpts.Repo.UseAzureWorkloadIdentity,
|
||||
}
|
||||
_, err := repoIf.ValidateAccess(ctx, &repoAccessReq)
|
||||
_, err = repoIf.ValidateAccess(ctx, &repoAccessReq)
|
||||
errors.CheckError(err)
|
||||
|
||||
repoCreateReq := repositorypkg.RepoCreateRequest{
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/argoproj/argo-cd/v3/cmd/argocd/commands/headless"
|
||||
"github.com/argoproj/argo-cd/v3/cmd/argocd/commands/utils"
|
||||
cmdutil "github.com/argoproj/argo-cd/v3/cmd/util"
|
||||
"github.com/argoproj/argo-cd/v3/common"
|
||||
argocdclient "github.com/argoproj/argo-cd/v3/pkg/apiclient"
|
||||
repocredspkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/repocreds"
|
||||
@@ -65,6 +66,9 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma
|
||||
repocredsAddExamples := ` # Add credentials with user/pass authentication to use for all repositories under https://git.example.com/repos
|
||||
argocd repocreds add https://git.example.com/repos/ --username git --password secret
|
||||
|
||||
# Add credentials with bearer token authentication to use for all BitBucket Data Center repositories under https://bitbucket.example.com/scm
|
||||
argocd repocreds add https://bitbucket.example.com/scm/ --bearer-token secret-token
|
||||
|
||||
# Add credentials with SSH private key authentication to use for all repositories under ssh://git@git.example.com/repos
|
||||
argocd repocreds add ssh://git@git.example.com/repos/ --ssh-private-key-path ~/.ssh/id_rsa
|
||||
|
||||
@@ -165,6 +169,13 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma
|
||||
repo.Password = cli.PromptPassword(repo.Password)
|
||||
}
|
||||
|
||||
err := cmdutil.ValidateBearerTokenAndPasswordCombo(repo.BearerToken, repo.Password)
|
||||
errors.CheckError(err)
|
||||
err = cmdutil.ValidateBearerTokenForGitOnly(repo.BearerToken, repo.Type)
|
||||
errors.CheckError(err)
|
||||
err = cmdutil.ValidateBearerTokenForHTTPSRepoOnly(repo.BearerToken, git.IsHTTPSURL(repo.URL))
|
||||
errors.CheckError(err)
|
||||
|
||||
repoCreateReq := repocredspkg.RepoCredsCreateRequest{
|
||||
Creds: &repo,
|
||||
Upsert: upsert,
|
||||
@@ -177,6 +188,7 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma
|
||||
}
|
||||
command.Flags().StringVar(&repo.Username, "username", "", "username to the repository")
|
||||
command.Flags().StringVar(&repo.Password, "password", "", "password to the repository")
|
||||
command.Flags().StringVar(&repo.BearerToken, "bearer-token", "", "bearer token to the Git repository")
|
||||
command.Flags().StringVar(&sshPrivateKeyPath, "ssh-private-key-path", "", "path to the private ssh key (e.g. ~/.ssh/id_rsa)")
|
||||
command.Flags().StringVar(&tlsClientCertPath, "tls-client-cert-path", "", "path to the TLS client cert (must be PEM format)")
|
||||
command.Flags().StringVar(&tlsClientCertKeyPath, "tls-client-cert-key-path", "", "path to the TLS client cert's key path (must be PEM format)")
|
||||
|
||||
@@ -1,6 +1,39 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
stderrors "errors"
|
||||
)
|
||||
|
||||
var (
|
||||
LogFormat string
|
||||
LogLevel string
|
||||
)
|
||||
|
||||
func ValidateBearerTokenForHTTPSRepoOnly(bearerToken string, isHTTPS bool) error {
|
||||
// Bearer token is only valid for HTTPS repositories
|
||||
if bearerToken != "" {
|
||||
if !isHTTPS {
|
||||
err := stderrors.New("--bearer-token is only supported for HTTPS repositories")
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateBearerTokenForGitOnly(bearerToken string, repoType string) error {
|
||||
// Bearer token is only valid for Git repositories
|
||||
if bearerToken != "" && repoType != "git" {
|
||||
err := stderrors.New("--bearer-token is only supported for Git repositories")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateBearerTokenAndPasswordCombo(bearerToken string, password string) error {
|
||||
// Either the password or the bearer token must be set, but not both
|
||||
if bearerToken != "" && password != "" {
|
||||
err := stderrors.New("only --bearer-token or --password is allowed, not both")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
155
cmd/util/common_test.go
Normal file
155
cmd/util/common_test.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestValidateBearerTokenAndPasswordCombo(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
bearerToken string
|
||||
password string
|
||||
expectError bool
|
||||
errorMsg string
|
||||
}{
|
||||
{
|
||||
name: "Both token and password set",
|
||||
bearerToken: "some-token",
|
||||
password: "some-password",
|
||||
expectError: true,
|
||||
errorMsg: "only --bearer-token or --password is allowed, not both",
|
||||
},
|
||||
{
|
||||
name: "Only token set",
|
||||
bearerToken: "some-token",
|
||||
password: "",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "Only password set",
|
||||
bearerToken: "",
|
||||
password: "some-password",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "Neither token nor password set",
|
||||
bearerToken: "",
|
||||
password: "",
|
||||
expectError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := ValidateBearerTokenAndPasswordCombo(tt.bearerToken, tt.password)
|
||||
if tt.expectError {
|
||||
require.ErrorContains(t, err, tt.errorMsg)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateBearerTokenForGitOnly(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
bearerToken string
|
||||
repoType string
|
||||
expectError bool
|
||||
errorMsg string
|
||||
}{
|
||||
{
|
||||
name: "Bearer token with helm repo",
|
||||
bearerToken: "some-token",
|
||||
repoType: "helm",
|
||||
expectError: true,
|
||||
errorMsg: "--bearer-token is only supported for Git repositories",
|
||||
},
|
||||
{
|
||||
name: "Bearer token with git repo",
|
||||
bearerToken: "some-token",
|
||||
repoType: "git",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "No bearer token with helm repo",
|
||||
bearerToken: "",
|
||||
repoType: "helm",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "No bearer token with git repo",
|
||||
bearerToken: "",
|
||||
repoType: "git",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "Bearer token with empty repo",
|
||||
bearerToken: "some-token",
|
||||
repoType: "",
|
||||
expectError: true,
|
||||
errorMsg: "--bearer-token is only supported for Git repositories",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := ValidateBearerTokenForGitOnly(tt.bearerToken, tt.repoType)
|
||||
if tt.expectError {
|
||||
require.ErrorContains(t, err, tt.errorMsg)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateBearerTokenForHTTPSRepoOnly(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
bearerToken string
|
||||
isHTTPS bool
|
||||
expectError bool
|
||||
errorMsg string
|
||||
}{
|
||||
{
|
||||
name: "Bearer token with HTTPS repo",
|
||||
bearerToken: "some-token",
|
||||
isHTTPS: true,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "Bearer token with non-HTTPS repo",
|
||||
bearerToken: "some-token",
|
||||
isHTTPS: false,
|
||||
expectError: true,
|
||||
errorMsg: "--bearer-token is only supported for HTTPS repositories",
|
||||
},
|
||||
{
|
||||
name: "No bearer token with HTTPS repo",
|
||||
bearerToken: "",
|
||||
isHTTPS: true,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "No bearer token with non-HTTPS repo",
|
||||
bearerToken: "",
|
||||
isHTTPS: false,
|
||||
expectError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := ValidateBearerTokenForHTTPSRepoOnly(tt.bearerToken, tt.isHTTPS)
|
||||
if tt.expectError {
|
||||
require.ErrorContains(t, err, tt.errorMsg)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ func AddRepoFlags(command *cobra.Command, opts *RepoOptions) {
|
||||
command.Flags().StringVar(&opts.Repo.Project, "project", "", "project of the repository")
|
||||
command.Flags().StringVar(&opts.Repo.Username, "username", "", "username to the repository")
|
||||
command.Flags().StringVar(&opts.Repo.Password, "password", "", "password to the repository")
|
||||
command.Flags().StringVar(&opts.Repo.BearerToken, "bearer-token", "", "bearer token to the Git BitBucket Data Center repository")
|
||||
command.Flags().StringVar(&opts.SshPrivateKeyPath, "ssh-private-key-path", "", "path to the private ssh key (e.g. ~/.ssh/id_rsa)")
|
||||
command.Flags().StringVar(&opts.TlsClientCertPath, "tls-client-cert-path", "", "path to the TLS client cert (must be PEM format)")
|
||||
command.Flags().StringVar(&opts.TlsClientCertKeyPath, "tls-client-cert-key-path", "", "path to the TLS client cert's key path (must be PEM format)")
|
||||
|
||||
@@ -21,6 +21,9 @@ argocd admin repo generate-spec REPOURL [flags]
|
||||
# Add a private Git repository via HTTPS using username/password and TLS client certificates:
|
||||
argocd admin repo generate-spec https://git.example.com/repos/repo --username git --password secret --tls-client-cert-path ~/mycert.crt --tls-client-cert-key-path ~/mycert.key
|
||||
|
||||
# Add a private Git BitBucket Data Center repository via HTTPS using bearer token:
|
||||
argocd admin repo generate-spec https://bitbucket.example.com/scm/proj/repo --bearer-token secret-token
|
||||
|
||||
# Add a private Git repository via HTTPS using username/password without verifying the server's TLS certificate
|
||||
argocd admin repo generate-spec https://git.example.com/repos/repo --username git --password secret --insecure-skip-server-verification
|
||||
|
||||
@@ -38,6 +41,7 @@ argocd admin repo generate-spec REPOURL [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
--bearer-token string bearer token to the Git BitBucket Data Center repository
|
||||
--enable-lfs enable git-lfs (Large File Support) on this repository
|
||||
--enable-oci enable helm-oci (Helm OCI-Based Repository)
|
||||
--force-http-basic-auth whether to force use of basic auth when connecting repository via HTTP
|
||||
|
||||
1
docs/user-guide/commands/argocd_repo_add.md
generated
1
docs/user-guide/commands/argocd_repo_add.md
generated
@@ -52,6 +52,7 @@ argocd repo add REPOURL [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
--bearer-token string bearer token to the Git BitBucket Data Center repository
|
||||
--enable-lfs enable git-lfs (Large File Support) on this repository
|
||||
--enable-oci enable helm-oci (Helm OCI-Based Repository)
|
||||
--force-http-basic-auth whether to force use of basic auth when connecting repository via HTTP
|
||||
|
||||
4
docs/user-guide/commands/argocd_repocreds_add.md
generated
4
docs/user-guide/commands/argocd_repocreds_add.md
generated
@@ -14,6 +14,9 @@ argocd repocreds add REPOURL [flags]
|
||||
# Add credentials with user/pass authentication to use for all repositories under https://git.example.com/repos
|
||||
argocd repocreds add https://git.example.com/repos/ --username git --password secret
|
||||
|
||||
# Add credentials with bearer token authentication to use for all BitBucket Data Center repositories under https://bitbucket.example.com/scm
|
||||
argocd repocreds add https://bitbucket.example.com/scm/ --bearer-token secret-token
|
||||
|
||||
# Add credentials with SSH private key authentication to use for all repositories under ssh://git@git.example.com/repos
|
||||
argocd repocreds add ssh://git@git.example.com/repos/ --ssh-private-key-path ~/.ssh/id_rsa
|
||||
|
||||
@@ -34,6 +37,7 @@ argocd repocreds add REPOURL [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
--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
|
||||
--gcp-service-account-key-path string service account key for the Google Cloud Platform
|
||||
|
||||
233
pkg/apiclient/repository/repository.pb.go
generated
233
pkg/apiclient/repository/repository.pb.go
generated
@@ -397,10 +397,12 @@ type RepoAccessQuery struct {
|
||||
// Whether to force HTTP basic auth
|
||||
ForceHttpBasicAuth bool `protobuf:"varint,19,opt,name=forceHttpBasicAuth,proto3" json:"forceHttpBasicAuth,omitempty"`
|
||||
// Whether to use azure workload identity for authentication
|
||||
UseAzureWorkloadIdentity bool `protobuf:"varint,20,opt,name=useAzureWorkloadIdentity,proto3" json:"useAzureWorkloadIdentity,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
UseAzureWorkloadIdentity bool `protobuf:"varint,20,opt,name=useAzureWorkloadIdentity,proto3" json:"useAzureWorkloadIdentity,omitempty"`
|
||||
// BearerToken contains the bearer token used for Git auth at the repo server
|
||||
BearerToken string `protobuf:"bytes,21,opt,name=bearerToken,proto3" json:"bearerToken,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) Reset() { *m = RepoAccessQuery{} }
|
||||
@@ -569,6 +571,13 @@ func (m *RepoAccessQuery) GetUseAzureWorkloadIdentity() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *RepoAccessQuery) GetBearerToken() string {
|
||||
if m != nil {
|
||||
return m.BearerToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RepoResponse struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
@@ -739,91 +748,92 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_8d38260443475705 = []byte{
|
||||
// 1335 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0x5d, 0x6f, 0x1b, 0x45,
|
||||
0x17, 0xc7, 0xb5, 0x49, 0xe3, 0x26, 0x27, 0x4d, 0xeb, 0x4e, 0x92, 0x3e, 0xfb, 0xb8, 0x69, 0x1a,
|
||||
0xb6, 0xa5, 0x4a, 0xa3, 0x76, 0xdd, 0xb8, 0x20, 0xaa, 0x22, 0x90, 0xdc, 0xa4, 0x6a, 0x23, 0x22,
|
||||
0x5a, 0xb6, 0x2a, 0x95, 0x10, 0x08, 0x4d, 0xd7, 0x27, 0xf6, 0xb6, 0x9b, 0xdd, 0xe9, 0xcc, 0xd8,
|
||||
0xad, 0xa9, 0x7a, 0xc3, 0x05, 0x42, 0x82, 0x1b, 0x84, 0x40, 0x5c, 0x01, 0x17, 0x48, 0x48, 0x70,
|
||||
0xcf, 0x67, 0xe0, 0x12, 0x89, 0x6b, 0x24, 0x54, 0xf1, 0x21, 0xb8, 0x44, 0x33, 0xb3, 0xde, 0x5d,
|
||||
0x3b, 0x7e, 0x49, 0xd5, 0x24, 0x77, 0x33, 0xe7, 0xcc, 0x9e, 0xf3, 0x9b, 0xff, 0x9c, 0x79, 0xb1,
|
||||
0xc1, 0x11, 0xc8, 0x5b, 0xc8, 0xcb, 0x1c, 0x59, 0x2c, 0x02, 0x19, 0xf3, 0x76, 0xae, 0xe9, 0x32,
|
||||
0x1e, 0xcb, 0x98, 0x40, 0x66, 0x29, 0x2d, 0xd4, 0xe3, 0xb8, 0x1e, 0x62, 0x99, 0xb2, 0xa0, 0x4c,
|
||||
0xa3, 0x28, 0x96, 0x54, 0x06, 0x71, 0x24, 0xcc, 0xc8, 0xd2, 0x66, 0x3d, 0x90, 0x8d, 0xe6, 0x7d,
|
||||
0xd7, 0x8f, 0xb7, 0xcb, 0x94, 0xd7, 0x63, 0xc6, 0xe3, 0x07, 0xba, 0x71, 0xd1, 0xaf, 0x95, 0x5b,
|
||||
0x97, 0xcb, 0xec, 0x61, 0x5d, 0x7d, 0x29, 0xca, 0x94, 0xb1, 0x30, 0xf0, 0xf5, 0xb7, 0xe5, 0xd6,
|
||||
0x2a, 0x0d, 0x59, 0x83, 0xae, 0x96, 0xeb, 0x18, 0x21, 0xa7, 0x12, 0x6b, 0x49, 0xb4, 0xeb, 0x23,
|
||||
0xa2, 0x69, 0xac, 0x91, 0xf8, 0x4e, 0x1b, 0x66, 0x3c, 0x64, 0x71, 0x95, 0x31, 0xf1, 0x5e, 0x13,
|
||||
0x79, 0x9b, 0x10, 0x38, 0xa4, 0x06, 0xd9, 0xd6, 0x92, 0xb5, 0x3c, 0xe5, 0xe9, 0x36, 0x29, 0xc1,
|
||||
0x24, 0xc7, 0x56, 0x20, 0x82, 0x38, 0xb2, 0xc7, 0xb4, 0x3d, 0xed, 0x13, 0x1b, 0x0e, 0x53, 0xc6,
|
||||
0xde, 0xa5, 0xdb, 0x68, 0x8f, 0x6b, 0x57, 0xa7, 0x4b, 0x16, 0x01, 0x28, 0x63, 0xb7, 0x79, 0xfc,
|
||||
0x00, 0x7d, 0x69, 0x1f, 0xd2, 0xce, 0x9c, 0xc5, 0x59, 0x85, 0xc3, 0x55, 0xc6, 0x36, 0xa2, 0xad,
|
||||
0x58, 0x25, 0x95, 0x6d, 0x86, 0x9d, 0xa4, 0xaa, 0xad, 0x6c, 0x8c, 0xca, 0x46, 0x92, 0x50, 0xb7,
|
||||
0x9d, 0x7f, 0x2d, 0x98, 0x4d, 0x70, 0xd7, 0x51, 0xd2, 0x20, 0x4c, 0xa0, 0xeb, 0x50, 0x10, 0x71,
|
||||
0x93, 0xfb, 0x26, 0xc2, 0x74, 0xe5, 0x96, 0x9b, 0xa9, 0xe3, 0x76, 0xd4, 0xd1, 0x8d, 0x8f, 0xfd,
|
||||
0x9a, 0xdb, 0xba, 0xec, 0xb2, 0x87, 0x75, 0x57, 0x69, 0xed, 0xe6, 0xb4, 0x76, 0x3b, 0x5a, 0xbb,
|
||||
0xd5, 0xcc, 0x78, 0x47, 0x87, 0xf5, 0x92, 0xf0, 0xf9, 0xd9, 0x8e, 0x0d, 0x9b, 0xed, 0x78, 0xef,
|
||||
0x6c, 0xc9, 0x12, 0x4c, 0x9b, 0x18, 0x1b, 0x51, 0x0d, 0x9f, 0x68, 0x39, 0x26, 0xbc, 0xbc, 0x89,
|
||||
0x2c, 0xc0, 0x54, 0x0b, 0xb9, 0x12, 0x75, 0xa3, 0x66, 0x4f, 0x68, 0x7f, 0x66, 0x70, 0xde, 0x82,
|
||||
0x62, 0x67, 0xa1, 0x3c, 0x14, 0x2c, 0x8e, 0x04, 0x92, 0xf3, 0x30, 0x11, 0x48, 0xdc, 0x16, 0xb6,
|
||||
0xb5, 0x34, 0xbe, 0x3c, 0x5d, 0x99, 0x75, 0x73, 0xcb, 0x9b, 0x48, 0xeb, 0x99, 0x11, 0x8e, 0x0f,
|
||||
0x53, 0xea, 0xf3, 0xc1, 0x6b, 0xec, 0xc0, 0x91, 0xad, 0x58, 0x4d, 0x15, 0xb7, 0x38, 0x0a, 0x23,
|
||||
0xfb, 0xa4, 0xd7, 0x65, 0x1b, 0x35, 0x47, 0xe7, 0xaf, 0x09, 0x38, 0xa6, 0x21, 0x7d, 0x1f, 0xc5,
|
||||
0xf0, 0x7a, 0x6a, 0x0a, 0xe4, 0x51, 0x26, 0x63, 0xda, 0x57, 0x3e, 0x46, 0x85, 0x78, 0x1c, 0xf3,
|
||||
0x5a, 0x92, 0x21, 0xed, 0x93, 0xb3, 0x30, 0x23, 0x44, 0xe3, 0x36, 0x0f, 0x5a, 0x54, 0xe2, 0x3b,
|
||||
0xd8, 0x4e, 0x8a, 0xaa, 0xdb, 0xa8, 0x22, 0x04, 0x91, 0x40, 0xbf, 0xc9, 0x51, 0xcb, 0x38, 0xe9,
|
||||
0xa5, 0x7d, 0x72, 0x01, 0x8e, 0xcb, 0x50, 0xac, 0x85, 0x01, 0x46, 0x72, 0x0d, 0xb9, 0x5c, 0xa7,
|
||||
0x92, 0xda, 0x05, 0x1d, 0x65, 0xa7, 0x83, 0xac, 0x40, 0xb1, 0xcb, 0xa8, 0x52, 0x1e, 0xd6, 0x83,
|
||||
0x77, 0xd8, 0xd3, 0x12, 0x9e, 0xea, 0x2e, 0x61, 0x3d, 0x47, 0x30, 0x36, 0x3d, 0xbf, 0x05, 0x98,
|
||||
0xc2, 0x88, 0xde, 0x0f, 0xf1, 0x96, 0x1f, 0xd8, 0xd3, 0x1a, 0x2f, 0x33, 0x90, 0x4b, 0x30, 0x6b,
|
||||
0x2a, 0xb7, 0xaa, 0x54, 0x4d, 0xe7, 0x79, 0x44, 0x07, 0xe8, 0xe7, 0x52, 0x75, 0x95, 0x9a, 0x37,
|
||||
0xd6, 0xed, 0x99, 0x25, 0x6b, 0x79, 0xdc, 0xcb, 0x9b, 0xc8, 0x15, 0xf8, 0x5f, 0xd6, 0x8d, 0x84,
|
||||
0xa4, 0x61, 0xa8, 0x4b, 0x7b, 0x63, 0xdd, 0x3e, 0xaa, 0x47, 0x0f, 0x72, 0x93, 0xb7, 0xa1, 0x94,
|
||||
0xba, 0xae, 0x47, 0x12, 0x39, 0xe3, 0x81, 0xc0, 0x6b, 0x54, 0xe0, 0x5d, 0x1e, 0xda, 0xc7, 0x34,
|
||||
0xd4, 0x90, 0x11, 0x64, 0x0e, 0x26, 0x18, 0x8f, 0x9f, 0xb4, 0xed, 0xa2, 0x1e, 0x6a, 0x3a, 0x6a,
|
||||
0x0f, 0xb1, 0xa4, 0x84, 0x8e, 0x9b, 0x3d, 0x94, 0x74, 0x49, 0x05, 0xe6, 0xea, 0x3e, 0xbb, 0x83,
|
||||
0xbc, 0x15, 0xf8, 0x58, 0xf5, 0xfd, 0xb8, 0x19, 0x69, 0xcd, 0x89, 0x1e, 0xd6, 0xd7, 0x47, 0x5c,
|
||||
0x20, 0xba, 0x46, 0x6f, 0x4a, 0xc9, 0xae, 0x51, 0x11, 0xf8, 0xd5, 0xa6, 0x6c, 0xd8, 0xb3, 0x5a,
|
||||
0xd8, 0x3e, 0x1e, 0x72, 0x15, 0xec, 0xa6, 0xc0, 0xea, 0x27, 0x4d, 0x8e, 0xf7, 0x62, 0xfe, 0x30,
|
||||
0x8c, 0x69, 0x6d, 0xa3, 0x86, 0x91, 0x0c, 0x64, 0xdb, 0x9e, 0xd3, 0x5f, 0x0d, 0xf4, 0x3b, 0x47,
|
||||
0xe1, 0x88, 0x2a, 0xef, 0xce, 0xfe, 0x73, 0x7e, 0xb6, 0xe0, 0xb8, 0x32, 0xac, 0x71, 0xa4, 0x12,
|
||||
0x3d, 0x7c, 0xd4, 0x44, 0x21, 0xc9, 0x87, 0xb9, 0x8a, 0x9f, 0xae, 0xdc, 0x7c, 0xb9, 0xa3, 0xc8,
|
||||
0x4b, 0x77, 0x74, 0xb2, 0x77, 0x4e, 0x40, 0xa1, 0xc9, 0x04, 0x72, 0x99, 0xec, 0xd0, 0xa4, 0xa7,
|
||||
0xea, 0xca, 0xe7, 0x58, 0x13, 0xb7, 0xa2, 0xb0, 0xad, 0x37, 0xce, 0xa4, 0x97, 0x19, 0x9c, 0x47,
|
||||
0x06, 0xf4, 0x2e, 0xab, 0x1d, 0x14, 0x68, 0xe5, 0xfb, 0x13, 0x26, 0xa7, 0x31, 0x26, 0x0b, 0x47,
|
||||
0xbe, 0xb4, 0xe0, 0xd0, 0x66, 0x20, 0x24, 0x99, 0xcf, 0x1f, 0x56, 0xe9, 0xd1, 0x54, 0xda, 0xdc,
|
||||
0x2b, 0x0a, 0x95, 0xc4, 0x39, 0xfd, 0xe9, 0x9f, 0xff, 0x7c, 0x3d, 0x76, 0x82, 0xcc, 0xe9, 0x2b,
|
||||
0xb9, 0xb5, 0x9a, 0xdd, 0x7f, 0x01, 0x8a, 0xcf, 0xc7, 0x2c, 0xf2, 0x85, 0x05, 0xe3, 0x37, 0x70,
|
||||
0x20, 0xcd, 0x9e, 0x69, 0xe2, 0x9c, 0xd1, 0x24, 0xa7, 0xc8, 0xc9, 0x7e, 0x24, 0xe5, 0xa7, 0xaa,
|
||||
0xf7, 0x8c, 0x7c, 0x6b, 0xc1, 0xe4, 0x0d, 0x94, 0xf7, 0x78, 0x20, 0x71, 0xff, 0x91, 0xce, 0x6b,
|
||||
0xa4, 0x33, 0xe4, 0x95, 0x0e, 0xd2, 0x63, 0x95, 0xf7, 0x62, 0x3f, 0xb0, 0x6f, 0x2c, 0x28, 0x2a,
|
||||
0x41, 0xbd, 0x9c, 0xef, 0x60, 0x56, 0x70, 0x61, 0xd8, 0x0a, 0x92, 0x1f, 0x2d, 0x98, 0x57, 0xc3,
|
||||
0xb4, 0x62, 0x07, 0x0f, 0xe7, 0x68, 0xb8, 0x05, 0x52, 0x1a, 0xac, 0x20, 0xf9, 0x08, 0x26, 0x8d,
|
||||
0x72, 0x5b, 0x03, 0xa1, 0x8a, 0xdd, 0xe6, 0x2d, 0xe1, 0x2c, 0xeb, 0xc0, 0x0e, 0x59, 0x1a, 0x52,
|
||||
0x2d, 0x65, 0xae, 0x42, 0x6e, 0x9b, 0xf0, 0xea, 0x59, 0x40, 0xfe, 0xdf, 0x1b, 0x3e, 0x7d, 0xd5,
|
||||
0x95, 0x16, 0xfa, 0xb9, 0xd2, 0x73, 0x6c, 0x57, 0xe9, 0xa8, 0x4a, 0xf1, 0x95, 0x05, 0x33, 0x37,
|
||||
0x50, 0x66, 0xef, 0x2f, 0x72, 0xba, 0x4f, 0xe4, 0xfc, 0xdb, 0xac, 0xe4, 0x0c, 0x1e, 0x90, 0x02,
|
||||
0xbc, 0xa9, 0x01, 0x5e, 0x77, 0x2e, 0xf5, 0x07, 0x30, 0xaf, 0x24, 0x1d, 0xe7, 0xae, 0xb7, 0xa9,
|
||||
0x51, 0x6a, 0x26, 0xc2, 0x55, 0x6b, 0x85, 0xb4, 0x34, 0xd2, 0x4d, 0x0c, 0xb7, 0xd7, 0x1a, 0x94,
|
||||
0xcb, 0x81, 0x32, 0x2f, 0xe6, 0xcd, 0xd9, 0xf0, 0x14, 0xc2, 0xd5, 0x10, 0xcb, 0xe4, 0xdc, 0x30,
|
||||
0x15, 0x1a, 0x18, 0x6e, 0xfb, 0x26, 0xcd, 0x77, 0x16, 0x14, 0xcc, 0xc9, 0x4f, 0x4e, 0xf5, 0x66,
|
||||
0xec, 0xba, 0x11, 0xf6, 0x70, 0xcf, 0xbe, 0x6a, 0x2a, 0xce, 0xe9, 0xbb, 0x1d, 0xae, 0xea, 0x83,
|
||||
0x57, 0x1d, 0x6b, 0x3f, 0x58, 0x50, 0xec, 0x20, 0x74, 0xbe, 0x3d, 0x38, 0x48, 0x67, 0x34, 0x24,
|
||||
0xf9, 0xc5, 0x82, 0x79, 0x93, 0xbf, 0x7b, 0xef, 0x1e, 0x20, 0x66, 0x52, 0xf5, 0xce, 0x90, 0xdd,
|
||||
0x9b, 0xc0, 0xfe, 0x64, 0x41, 0xc1, 0x5c, 0x9d, 0x3b, 0xe9, 0xba, 0xae, 0xd4, 0x3d, 0xa4, 0x5b,
|
||||
0x35, 0xd5, 0x58, 0x1a, 0xb2, 0x27, 0x35, 0xca, 0xb3, 0x6c, 0xd5, 0x7f, 0xb5, 0xa0, 0xd8, 0xc1,
|
||||
0x19, 0x2c, 0xe7, 0x7e, 0x01, 0xbb, 0x2f, 0x06, 0x4c, 0x7e, 0xb3, 0x60, 0xde, 0xb0, 0x8c, 0xac,
|
||||
0x80, 0xfd, 0x42, 0x7e, 0x4d, 0x23, 0xbb, 0xa5, 0x73, 0xa3, 0x6e, 0xc0, 0x2e, 0x70, 0x0a, 0x85,
|
||||
0x75, 0x0c, 0x71, 0xf0, 0x15, 0x6d, 0xf7, 0x9a, 0xd3, 0x23, 0xe6, 0x9c, 0x79, 0x05, 0xac, 0x0c,
|
||||
0x7b, 0x05, 0xa8, 0x95, 0x6c, 0x40, 0xd1, 0xa4, 0xc8, 0xa9, 0xf2, 0xc2, 0xc9, 0xce, 0xec, 0x22,
|
||||
0x19, 0x11, 0x30, 0x6f, 0x32, 0xf5, 0x2e, 0xc2, 0x0b, 0xa7, 0x4b, 0x9e, 0x13, 0x2b, 0xbb, 0x78,
|
||||
0x4e, 0x3c, 0x85, 0xa3, 0xef, 0xd3, 0x30, 0x50, 0x8b, 0x6a, 0x7e, 0x2a, 0x92, 0x93, 0x3b, 0x2e,
|
||||
0x89, 0xec, 0x27, 0xe4, 0x90, 0x9c, 0x15, 0x9d, 0xf3, 0x82, 0x73, 0x76, 0xd8, 0x91, 0xdd, 0x4a,
|
||||
0x52, 0x25, 0xcb, 0xf7, 0x99, 0x05, 0xb3, 0x9d, 0xec, 0x7a, 0xd2, 0x2f, 0x87, 0x70, 0x45, 0x23,
|
||||
0x54, 0x9c, 0x95, 0x91, 0xd3, 0xee, 0x01, 0xb9, 0x76, 0xfd, 0xf7, 0xe7, 0x8b, 0xd6, 0x1f, 0xcf,
|
||||
0x17, 0xad, 0xbf, 0x9f, 0x2f, 0x5a, 0x1f, 0xbc, 0xb1, 0xbb, 0x7f, 0x87, 0x7c, 0xfd, 0xa3, 0x33,
|
||||
0xf7, 0x3f, 0xce, 0xfd, 0x82, 0xfe, 0x23, 0xe7, 0xf2, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x1e,
|
||||
0x28, 0xd2, 0x55, 0xad, 0x12, 0x00, 0x00,
|
||||
// 1349 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0xcf, 0x6f, 0x1c, 0x35,
|
||||
0x14, 0xc7, 0x35, 0x49, 0xb3, 0x4d, 0x5e, 0x9a, 0x76, 0xeb, 0x24, 0x65, 0xd8, 0xa6, 0x69, 0x98,
|
||||
0x96, 0x2a, 0x8d, 0xda, 0xd9, 0x66, 0x0b, 0xa2, 0x2a, 0x02, 0x69, 0x9b, 0x54, 0x6d, 0x44, 0x44,
|
||||
0xcb, 0x94, 0x52, 0x09, 0x81, 0x90, 0x33, 0xfb, 0xb2, 0x3b, 0xcd, 0x64, 0xc6, 0xb5, 0xbd, 0xdb,
|
||||
0x2e, 0x55, 0x2f, 0x1c, 0x10, 0x12, 0x5c, 0x10, 0x02, 0x71, 0x02, 0x0e, 0x48, 0x48, 0x70, 0xe7,
|
||||
0x6f, 0xe0, 0x88, 0xc4, 0x3f, 0x80, 0x2a, 0xfe, 0x08, 0x6e, 0x20, 0xdb, 0xb3, 0x33, 0xb3, 0xc9,
|
||||
0xfe, 0x48, 0xd5, 0x34, 0x37, 0xfb, 0xd9, 0xf3, 0xde, 0xc7, 0x5f, 0xbf, 0x67, 0x7b, 0x17, 0x1c,
|
||||
0x81, 0xbc, 0x85, 0xbc, 0xcc, 0x91, 0xc5, 0x22, 0x90, 0x31, 0x6f, 0xe7, 0x9a, 0x2e, 0xe3, 0xb1,
|
||||
0x8c, 0x09, 0x64, 0x96, 0xd2, 0x5c, 0x3d, 0x8e, 0xeb, 0x21, 0x96, 0x29, 0x0b, 0xca, 0x34, 0x8a,
|
||||
0x62, 0x49, 0x65, 0x10, 0x47, 0xc2, 0xcc, 0x2c, 0xad, 0xd7, 0x03, 0xd9, 0x68, 0x6e, 0xb8, 0x7e,
|
||||
0xbc, 0x5d, 0xa6, 0xbc, 0x1e, 0x33, 0x1e, 0xdf, 0xd7, 0x8d, 0x8b, 0x7e, 0xad, 0xdc, 0xba, 0x5c,
|
||||
0x66, 0x5b, 0x75, 0xf5, 0xa5, 0x28, 0x53, 0xc6, 0xc2, 0xc0, 0xd7, 0xdf, 0x96, 0x5b, 0xcb, 0x34,
|
||||
0x64, 0x0d, 0xba, 0x5c, 0xae, 0x63, 0x84, 0x9c, 0x4a, 0xac, 0x25, 0xde, 0xae, 0x0f, 0xf1, 0xa6,
|
||||
0xb1, 0x86, 0xe2, 0x3b, 0x6d, 0x98, 0xf2, 0x90, 0xc5, 0x55, 0xc6, 0xc4, 0x7b, 0x4d, 0xe4, 0x6d,
|
||||
0x42, 0xe0, 0x90, 0x9a, 0x64, 0x5b, 0x0b, 0xd6, 0xe2, 0x84, 0xa7, 0xdb, 0xa4, 0x04, 0xe3, 0x1c,
|
||||
0x5b, 0x81, 0x08, 0xe2, 0xc8, 0x1e, 0xd1, 0xf6, 0xb4, 0x4f, 0x6c, 0x38, 0x4c, 0x19, 0x7b, 0x97,
|
||||
0x6e, 0xa3, 0x3d, 0xaa, 0x87, 0x3a, 0x5d, 0x32, 0x0f, 0x40, 0x19, 0xbb, 0xcd, 0xe3, 0xfb, 0xe8,
|
||||
0x4b, 0xfb, 0x90, 0x1e, 0xcc, 0x59, 0x9c, 0x65, 0x38, 0x5c, 0x65, 0x6c, 0x2d, 0xda, 0x8c, 0x55,
|
||||
0x50, 0xd9, 0x66, 0xd8, 0x09, 0xaa, 0xda, 0xca, 0xc6, 0xa8, 0x6c, 0x24, 0x01, 0x75, 0xdb, 0xf9,
|
||||
0xd7, 0x82, 0xe9, 0x04, 0x77, 0x15, 0x25, 0x0d, 0xc2, 0x04, 0xba, 0x0e, 0x05, 0x11, 0x37, 0xb9,
|
||||
0x6f, 0x3c, 0x4c, 0x56, 0x6e, 0xb9, 0x99, 0x3a, 0x6e, 0x47, 0x1d, 0xdd, 0xf8, 0xc4, 0xaf, 0xb9,
|
||||
0xad, 0xcb, 0x2e, 0xdb, 0xaa, 0xbb, 0x4a, 0x6b, 0x37, 0xa7, 0xb5, 0xdb, 0xd1, 0xda, 0xad, 0x66,
|
||||
0xc6, 0x3b, 0xda, 0xad, 0x97, 0xb8, 0xcf, 0xaf, 0x76, 0x64, 0xd0, 0x6a, 0x47, 0x77, 0xae, 0x96,
|
||||
0x2c, 0xc0, 0xa4, 0xf1, 0xb1, 0x16, 0xd5, 0xf0, 0x91, 0x96, 0x63, 0xcc, 0xcb, 0x9b, 0xc8, 0x1c,
|
||||
0x4c, 0xb4, 0x90, 0x2b, 0x51, 0xd7, 0x6a, 0xf6, 0x98, 0x1e, 0xcf, 0x0c, 0xce, 0x5b, 0x50, 0xec,
|
||||
0x6c, 0x94, 0x87, 0x82, 0xc5, 0x91, 0x40, 0x72, 0x1e, 0xc6, 0x02, 0x89, 0xdb, 0xc2, 0xb6, 0x16,
|
||||
0x46, 0x17, 0x27, 0x2b, 0xd3, 0x6e, 0x6e, 0x7b, 0x13, 0x69, 0x3d, 0x33, 0xc3, 0xf1, 0x61, 0x42,
|
||||
0x7d, 0xde, 0x7f, 0x8f, 0x1d, 0x38, 0xb2, 0x19, 0xab, 0xa5, 0xe2, 0x26, 0x47, 0x61, 0x64, 0x1f,
|
||||
0xf7, 0xba, 0x6c, 0xc3, 0xd6, 0xe8, 0xfc, 0x37, 0x06, 0xc7, 0x34, 0xa4, 0xef, 0xa3, 0x18, 0x9c,
|
||||
0x4f, 0x4d, 0x81, 0x3c, 0xca, 0x64, 0x4c, 0xfb, 0x6a, 0x8c, 0x51, 0x21, 0x1e, 0xc6, 0xbc, 0x96,
|
||||
0x44, 0x48, 0xfb, 0xe4, 0x2c, 0x4c, 0x09, 0xd1, 0xb8, 0xcd, 0x83, 0x16, 0x95, 0xf8, 0x0e, 0xb6,
|
||||
0x93, 0xa4, 0xea, 0x36, 0x2a, 0x0f, 0x41, 0x24, 0xd0, 0x6f, 0x72, 0xd4, 0x32, 0x8e, 0x7b, 0x69,
|
||||
0x9f, 0x5c, 0x80, 0xe3, 0x32, 0x14, 0x2b, 0x61, 0x80, 0x91, 0x5c, 0x41, 0x2e, 0x57, 0xa9, 0xa4,
|
||||
0x76, 0x41, 0x7b, 0xd9, 0x3d, 0x40, 0x96, 0xa0, 0xd8, 0x65, 0x54, 0x21, 0x0f, 0xeb, 0xc9, 0xbb,
|
||||
0xec, 0x69, 0x0a, 0x4f, 0x74, 0xa7, 0xb0, 0x5e, 0x23, 0x18, 0x9b, 0x5e, 0xdf, 0x1c, 0x4c, 0x60,
|
||||
0x44, 0x37, 0x42, 0xbc, 0xe5, 0x07, 0xf6, 0xa4, 0xc6, 0xcb, 0x0c, 0xe4, 0x12, 0x4c, 0x9b, 0xcc,
|
||||
0xad, 0x2a, 0x55, 0xd3, 0x75, 0x1e, 0xd1, 0x0e, 0x7a, 0x0d, 0xa9, 0xbc, 0x4a, 0xcd, 0x6b, 0xab,
|
||||
0xf6, 0xd4, 0x82, 0xb5, 0x38, 0xea, 0xe5, 0x4d, 0xe4, 0x0a, 0xbc, 0x94, 0x75, 0x23, 0x21, 0x69,
|
||||
0x18, 0xea, 0xd4, 0x5e, 0x5b, 0xb5, 0x8f, 0xea, 0xd9, 0xfd, 0x86, 0xc9, 0xdb, 0x50, 0x4a, 0x87,
|
||||
0xae, 0x47, 0x12, 0x39, 0xe3, 0x81, 0xc0, 0x6b, 0x54, 0xe0, 0x5d, 0x1e, 0xda, 0xc7, 0x34, 0xd4,
|
||||
0x80, 0x19, 0x64, 0x06, 0xc6, 0x18, 0x8f, 0x1f, 0xb5, 0xed, 0xa2, 0x9e, 0x6a, 0x3a, 0xaa, 0x86,
|
||||
0x58, 0x92, 0x42, 0xc7, 0x4d, 0x0d, 0x25, 0x5d, 0x52, 0x81, 0x99, 0xba, 0xcf, 0xee, 0x20, 0x6f,
|
||||
0x05, 0x3e, 0x56, 0x7d, 0x3f, 0x6e, 0x46, 0x5a, 0x73, 0xa2, 0xa7, 0xf5, 0x1c, 0x23, 0x2e, 0x10,
|
||||
0x9d, 0xa3, 0x37, 0xa5, 0x64, 0xd7, 0xa8, 0x08, 0xfc, 0x6a, 0x53, 0x36, 0xec, 0x69, 0x2d, 0x6c,
|
||||
0x8f, 0x11, 0x72, 0x15, 0xec, 0xa6, 0xc0, 0xea, 0xa7, 0x4d, 0x8e, 0xf7, 0x62, 0xbe, 0x15, 0xc6,
|
||||
0xb4, 0xb6, 0x56, 0xc3, 0x48, 0x06, 0xb2, 0x6d, 0xcf, 0xe8, 0xaf, 0xfa, 0x8e, 0x2b, 0xad, 0x37,
|
||||
0x90, 0x72, 0xe4, 0xef, 0xc7, 0x5b, 0x18, 0xd9, 0xb3, 0x1a, 0x2b, 0x6f, 0x72, 0x8e, 0xc2, 0x11,
|
||||
0x55, 0x00, 0x9d, 0x0a, 0x75, 0x7e, 0xb1, 0xe0, 0xb8, 0x32, 0xac, 0x70, 0xa4, 0x12, 0x3d, 0x7c,
|
||||
0xd0, 0x44, 0x21, 0xc9, 0x47, 0xb9, 0x9a, 0x98, 0xac, 0xdc, 0x7c, 0xbe, 0xc3, 0xca, 0x4b, 0x6b,
|
||||
0x3e, 0xa9, 0xae, 0x13, 0x50, 0x68, 0x32, 0x81, 0x5c, 0x26, 0x35, 0x9c, 0xf4, 0x54, 0xe6, 0xf9,
|
||||
0x1c, 0x6b, 0xe2, 0x56, 0x14, 0xb6, 0x75, 0x69, 0x8d, 0x7b, 0x99, 0xc1, 0x79, 0x60, 0x40, 0xef,
|
||||
0xb2, 0xda, 0x41, 0x81, 0x56, 0x7e, 0x38, 0x61, 0x62, 0x1a, 0x63, 0xb2, 0xb5, 0xe4, 0x2b, 0x0b,
|
||||
0x0e, 0xad, 0x07, 0x42, 0x92, 0xd9, 0xfc, 0x71, 0x96, 0x1e, 0x5e, 0xa5, 0xf5, 0xfd, 0xa2, 0x50,
|
||||
0x41, 0x9c, 0xd3, 0x9f, 0xfd, 0xf5, 0xcf, 0x37, 0x23, 0x27, 0xc8, 0x8c, 0xbe, 0xb4, 0x5b, 0xcb,
|
||||
0xd9, 0x0d, 0x19, 0xa0, 0xf8, 0x62, 0xc4, 0x22, 0x5f, 0x5a, 0x30, 0x7a, 0x03, 0xfb, 0xd2, 0xec,
|
||||
0x9b, 0x26, 0xce, 0x19, 0x4d, 0x72, 0x8a, 0x9c, 0xec, 0x45, 0x52, 0x7e, 0xac, 0x7a, 0x4f, 0xc8,
|
||||
0x77, 0x16, 0x8c, 0xdf, 0x40, 0x79, 0x8f, 0x07, 0x12, 0x5f, 0x3c, 0xd2, 0x79, 0x8d, 0x74, 0x86,
|
||||
0xbc, 0xd2, 0x41, 0x7a, 0xa8, 0xe2, 0x5e, 0xec, 0x05, 0xf6, 0xad, 0x05, 0x45, 0x25, 0xa8, 0x97,
|
||||
0x1b, 0x3b, 0x98, 0x1d, 0x9c, 0x1b, 0xb4, 0x83, 0xe4, 0x27, 0x0b, 0x66, 0xd5, 0x34, 0xad, 0xd8,
|
||||
0xc1, 0xc3, 0x39, 0x1a, 0x6e, 0x8e, 0x94, 0xfa, 0x2b, 0x48, 0x3e, 0x86, 0x71, 0xa3, 0xdc, 0x66,
|
||||
0x5f, 0xa8, 0x62, 0xb7, 0x79, 0x53, 0x38, 0x8b, 0xda, 0xb1, 0x43, 0x16, 0x06, 0x64, 0x4b, 0x99,
|
||||
0x2b, 0x97, 0xdb, 0xc6, 0xbd, 0x7a, 0x38, 0x90, 0x97, 0x77, 0xba, 0x4f, 0xdf, 0x7d, 0xa5, 0xb9,
|
||||
0x5e, 0x43, 0xe9, 0x39, 0xb6, 0xa7, 0x70, 0x54, 0x85, 0xf8, 0xda, 0x82, 0xa9, 0x1b, 0x28, 0xb3,
|
||||
0x17, 0x1a, 0x39, 0xdd, 0xc3, 0x73, 0xfe, 0xf5, 0x56, 0x72, 0xfa, 0x4f, 0x48, 0x01, 0xde, 0xd4,
|
||||
0x00, 0xaf, 0x3b, 0x97, 0x7a, 0x03, 0x98, 0x77, 0x94, 0xf6, 0x73, 0xd7, 0x5b, 0xd7, 0x28, 0x35,
|
||||
0xe3, 0xe1, 0xaa, 0xb5, 0x44, 0x5a, 0x1a, 0xe9, 0x26, 0x86, 0xdb, 0x2b, 0x0d, 0xca, 0x65, 0x5f,
|
||||
0x99, 0xe7, 0xf3, 0xe6, 0x6c, 0x7a, 0x0a, 0xe1, 0x6a, 0x88, 0x45, 0x72, 0x6e, 0x90, 0x0a, 0x0d,
|
||||
0x0c, 0xb7, 0x7d, 0x13, 0xe6, 0x7b, 0x0b, 0x0a, 0xe6, 0xe4, 0x27, 0xa7, 0x76, 0x46, 0xec, 0xba,
|
||||
0x11, 0xf6, 0xb1, 0x66, 0x5f, 0x35, 0x19, 0xe7, 0xf4, 0x2c, 0x87, 0xab, 0xfa, 0xe0, 0x55, 0xc7,
|
||||
0xda, 0x8f, 0x16, 0x14, 0x3b, 0x08, 0x9d, 0x6f, 0x0f, 0x0e, 0xd2, 0x19, 0x0e, 0x49, 0x7e, 0xb5,
|
||||
0x60, 0xd6, 0xc4, 0xef, 0xae, 0xdd, 0x03, 0xc4, 0x4c, 0xb2, 0xde, 0x19, 0x50, 0xbd, 0x09, 0xec,
|
||||
0xcf, 0x16, 0x14, 0xcc, 0xd5, 0xb9, 0x9b, 0xae, 0xeb, 0x4a, 0xdd, 0x47, 0xba, 0x65, 0x93, 0x8d,
|
||||
0xa5, 0x01, 0x35, 0xa9, 0x51, 0x9e, 0x64, 0xbb, 0xfe, 0x9b, 0x05, 0xc5, 0x0e, 0x4e, 0x7f, 0x39,
|
||||
0x5f, 0x14, 0xb0, 0xfb, 0x6c, 0xc0, 0xe4, 0x77, 0x0b, 0x66, 0x0d, 0xcb, 0xd0, 0x0c, 0x78, 0x51,
|
||||
0xc8, 0xaf, 0x69, 0x64, 0xb7, 0x74, 0x6e, 0xd8, 0x0d, 0xd8, 0x05, 0x4e, 0xa1, 0xb0, 0x8a, 0x21,
|
||||
0xf6, 0xbf, 0xa2, 0xed, 0x9d, 0xe6, 0xf4, 0x88, 0x39, 0x67, 0x5e, 0x01, 0x4b, 0x83, 0x5e, 0x01,
|
||||
0x6a, 0x27, 0x1b, 0x50, 0x34, 0x21, 0x72, 0xaa, 0x3c, 0x73, 0xb0, 0x33, 0x7b, 0x08, 0x46, 0x04,
|
||||
0xcc, 0x9a, 0x48, 0x3b, 0x37, 0xe1, 0x99, 0xc3, 0x25, 0xcf, 0x89, 0xa5, 0x3d, 0x3c, 0x27, 0x1e,
|
||||
0xc3, 0xd1, 0x0f, 0x68, 0x18, 0xa8, 0x4d, 0x35, 0x3f, 0x26, 0xc9, 0xc9, 0x5d, 0x97, 0x44, 0xf6,
|
||||
0x23, 0x73, 0x40, 0xcc, 0x8a, 0x8e, 0x79, 0xc1, 0x39, 0x3b, 0xe8, 0xc8, 0x6e, 0x25, 0xa1, 0x92,
|
||||
0xed, 0xfb, 0xdc, 0x82, 0xe9, 0x4e, 0x74, 0xbd, 0xe8, 0xe7, 0x43, 0xb8, 0xa2, 0x11, 0x2a, 0xce,
|
||||
0xd2, 0xd0, 0x65, 0xef, 0x00, 0xb9, 0x76, 0xfd, 0x8f, 0xa7, 0xf3, 0xd6, 0x9f, 0x4f, 0xe7, 0xad,
|
||||
0xbf, 0x9f, 0xce, 0x5b, 0x1f, 0xbe, 0xb1, 0xb7, 0xff, 0x8f, 0x7c, 0xfd, 0xb3, 0x34, 0xf7, 0x4f,
|
||||
0xcf, 0x46, 0x41, 0xff, 0xd5, 0x73, 0xf9, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x97, 0xe0,
|
||||
0xc3, 0xcf, 0x12, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@@ -1907,6 +1917,15 @@ func (m *RepoAccessQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if len(m.BearerToken) > 0 {
|
||||
i -= len(m.BearerToken)
|
||||
copy(dAtA[i:], m.BearerToken)
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.BearerToken)))
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0xaa
|
||||
}
|
||||
if m.UseAzureWorkloadIdentity {
|
||||
i--
|
||||
if m.UseAzureWorkloadIdentity {
|
||||
@@ -2392,6 +2411,10 @@ func (m *RepoAccessQuery) Size() (n int) {
|
||||
if m.UseAzureWorkloadIdentity {
|
||||
n += 3
|
||||
}
|
||||
l = len(m.BearerToken)
|
||||
if l > 0 {
|
||||
n += 2 + l + sovRepository(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
@@ -3720,6 +3743,38 @@ func (m *RepoAccessQuery) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
}
|
||||
m.UseAzureWorkloadIdentity = bool(v != 0)
|
||||
case 21:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field BearerToken", 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.BearerToken = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipRepository(dAtA[iNdEx:])
|
||||
|
||||
1580
pkg/apis/application/v1alpha1/generated.pb.go
generated
1580
pkg/apis/application/v1alpha1/generated.pb.go
generated
File diff suppressed because it is too large
Load Diff
@@ -1712,6 +1712,9 @@ message RepoCreds {
|
||||
|
||||
// UseAzureWorkloadIdentity specifies whether to use Azure Workload Identity for authentication
|
||||
optional bool useAzureWorkloadIdentity = 24;
|
||||
|
||||
// BearerToken contains the bearer token used for Git BitBucket Data Center auth at the repo server
|
||||
optional string bearerToken = 25;
|
||||
}
|
||||
|
||||
// RepositoryList is a collection of Repositories.
|
||||
@@ -1795,6 +1798,9 @@ message Repository {
|
||||
|
||||
// UseAzureWorkloadIdentity specifies whether to use Azure Workload Identity for authentication
|
||||
optional bool useAzureWorkloadIdentity = 24;
|
||||
|
||||
// BearerToken contains the bearer token used for Git BitBucket Data Center auth at the repo server
|
||||
optional string bearerToken = 25;
|
||||
}
|
||||
|
||||
// A RepositoryCertificate is either SSH known hosts entry or TLS certificate
|
||||
|
||||
@@ -51,6 +51,8 @@ type RepoCreds struct {
|
||||
NoProxy string `json:"noProxy,omitempty" protobuf:"bytes,23,opt,name=noProxy"`
|
||||
// UseAzureWorkloadIdentity specifies whether to use Azure Workload Identity for authentication
|
||||
UseAzureWorkloadIdentity bool `json:"useAzureWorkloadIdentity,omitempty" protobuf:"bytes,24,opt,name=useAzureWorkloadIdentity"`
|
||||
// BearerToken contains the bearer token used for Git BitBucket Data Center auth at the repo server
|
||||
BearerToken string `json:"bearerToken,omitempty" protobuf:"bytes,25,opt,name=bearerToken"`
|
||||
}
|
||||
|
||||
// Repository is a repository holding application configurations
|
||||
@@ -104,6 +106,8 @@ type Repository struct {
|
||||
NoProxy string `json:"noProxy,omitempty" protobuf:"bytes,23,opt,name=noProxy"`
|
||||
// UseAzureWorkloadIdentity specifies whether to use Azure Workload Identity for authentication
|
||||
UseAzureWorkloadIdentity bool `json:"useAzureWorkloadIdentity,omitempty" protobuf:"bytes,24,opt,name=useAzureWorkloadIdentity"`
|
||||
// BearerToken contains the bearer token used for Git BitBucket Data Center auth at the repo server
|
||||
BearerToken string `json:"bearerToken,omitempty" protobuf:"bytes,25,opt,name=bearerToken"`
|
||||
}
|
||||
|
||||
// IsInsecure returns true if the repository has been configured to skip server verification
|
||||
@@ -118,7 +122,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.SSHPrivateKey != "" || repo.TLSClientCertData != "" || repo.GithubAppPrivateKey != "" || repo.UseAzureWorkloadIdentity
|
||||
return repo.Username != "" || repo.Password != "" || repo.BearerToken != "" || repo.SSHPrivateKey != "" || repo.TLSClientCertData != "" || repo.GithubAppPrivateKey != "" || repo.UseAzureWorkloadIdentity
|
||||
}
|
||||
|
||||
// CopyCredentialsFromRepo copies all credential information from source repository to receiving repository
|
||||
@@ -130,6 +134,9 @@ func (repo *Repository) CopyCredentialsFromRepo(source *Repository) {
|
||||
if repo.Password == "" {
|
||||
repo.Password = source.Password
|
||||
}
|
||||
if repo.BearerToken == "" {
|
||||
repo.BearerToken = source.BearerToken
|
||||
}
|
||||
if repo.SSHPrivateKey == "" {
|
||||
repo.SSHPrivateKey = source.SSHPrivateKey
|
||||
}
|
||||
@@ -168,6 +175,9 @@ func (repo *Repository) CopyCredentialsFrom(source *RepoCreds) {
|
||||
if repo.Password == "" {
|
||||
repo.Password = source.Password
|
||||
}
|
||||
if repo.BearerToken == "" {
|
||||
repo.BearerToken = source.BearerToken
|
||||
}
|
||||
if repo.SSHPrivateKey == "" {
|
||||
repo.SSHPrivateKey = source.SSHPrivateKey
|
||||
}
|
||||
@@ -208,8 +218,8 @@ func (repo *Repository) GetGitCreds(store git.CredsStore) git.Creds {
|
||||
if repo == nil {
|
||||
return git.NopCreds{}
|
||||
}
|
||||
if repo.Password != "" {
|
||||
return git.NewHTTPSCreds(repo.Username, repo.Password, repo.TLSClientCertData, repo.TLSClientCertKey, repo.IsInsecure(), repo.Proxy, repo.NoProxy, store, repo.ForceHttpBasicAuth)
|
||||
if repo.Password != "" || repo.BearerToken != "" {
|
||||
return git.NewHTTPSCreds(repo.Username, repo.Password, repo.BearerToken, repo.TLSClientCertData, repo.TLSClientCertKey, repo.IsInsecure(), repo.Proxy, repo.NoProxy, store, repo.ForceHttpBasicAuth)
|
||||
}
|
||||
if repo.SSHPrivateKey != "" {
|
||||
return git.NewSSHCreds(repo.SSHPrivateKey, getCAPath(repo.Repo), repo.IsInsecure(), store, repo.Proxy, repo.NoProxy)
|
||||
|
||||
@@ -3,6 +3,7 @@ package v1alpha1
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/argoproj/argo-cd/v3/util/git"
|
||||
@@ -35,3 +36,67 @@ func TestGetHelmCredsShouldReturnHelmCredsIfAzureWorkloadIdentityNotSpecified(t
|
||||
_, ok := creds.(helm.HelmCreds)
|
||||
require.Truef(t, ok, "expected HelmCreds but got %T", creds)
|
||||
}
|
||||
|
||||
func TestGetGitCreds(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
repo *Repository
|
||||
expected git.Creds
|
||||
}{
|
||||
{
|
||||
name: "nil repository",
|
||||
repo: nil,
|
||||
expected: git.NopCreds{},
|
||||
},
|
||||
{
|
||||
name: "HTTPS credentials",
|
||||
repo: &Repository{
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
expected: git.NewHTTPSCreds("user", "pass", "", "", "", false, "", "", nil, false),
|
||||
},
|
||||
{
|
||||
name: "Bearer token credentials",
|
||||
repo: &Repository{
|
||||
BearerToken: "token",
|
||||
},
|
||||
expected: git.NewHTTPSCreds("", "", "token", "", "", false, "", "", nil, false),
|
||||
},
|
||||
{
|
||||
name: "SSH credentials",
|
||||
repo: &Repository{
|
||||
SSHPrivateKey: "ssh-key",
|
||||
},
|
||||
expected: git.NewSSHCreds("ssh-key", "", false, nil, "", ""),
|
||||
},
|
||||
{
|
||||
name: "GitHub App credentials",
|
||||
repo: &Repository{
|
||||
GithubAppPrivateKey: "github-key",
|
||||
GithubAppId: 123,
|
||||
GithubAppInstallationId: 456,
|
||||
},
|
||||
expected: git.NewGitHubAppCreds(123, 456, "github-key", "", "", "", "", false, "", "", nil),
|
||||
},
|
||||
{
|
||||
name: "Google Cloud credentials",
|
||||
repo: &Repository{
|
||||
GCPServiceAccountKey: "gcp-key",
|
||||
},
|
||||
expected: git.NewGoogleCloudCreds("gcp-key", nil),
|
||||
},
|
||||
{
|
||||
name: "No credentials",
|
||||
repo: &Repository{},
|
||||
expected: git.NopCreds{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
creds := tt.repo.GetGitCreds(nil)
|
||||
assert.Equal(t, tt.expected, creds)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1139,6 +1139,11 @@ func TestRepository_HasCredentials(t *testing.T) {
|
||||
repo: Repository{Password: "foo"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "TestHasBearerToken",
|
||||
repo: Repository{BearerToken: "foo"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "TestHasSSHPrivateKey",
|
||||
repo: Repository{SSHPrivateKey: "foo"},
|
||||
@@ -1249,6 +1254,7 @@ func TestRepository_CopyCredentialsFromRepo(t *testing.T) {
|
||||
}{
|
||||
{"Username", &Repository{Username: "foo"}, &Repository{}, Repository{Username: "foo"}},
|
||||
{"Password", &Repository{Password: "foo"}, &Repository{}, Repository{Password: "foo"}},
|
||||
{"BearerToken", &Repository{BearerToken: "foo"}, &Repository{}, Repository{BearerToken: "foo"}},
|
||||
{"SSHPrivateKey", &Repository{SSHPrivateKey: "foo"}, &Repository{}, Repository{SSHPrivateKey: "foo"}},
|
||||
{"InsecureHostKey", &Repository{InsecureIgnoreHostKey: true}, &Repository{}, Repository{InsecureIgnoreHostKey: true}},
|
||||
{"Insecure", &Repository{Insecure: true}, &Repository{}, Repository{Insecure: true}},
|
||||
@@ -1259,6 +1265,7 @@ func TestRepository_CopyCredentialsFromRepo(t *testing.T) {
|
||||
|
||||
{"SourceUsername", &Repository{}, &Repository{Username: "foo"}, Repository{Username: "foo"}},
|
||||
{"SourcePassword", &Repository{}, &Repository{Password: "foo"}, Repository{Password: "foo"}},
|
||||
{"SourcePassword", &Repository{}, &Repository{BearerToken: "foo"}, Repository{BearerToken: "foo"}},
|
||||
{"SourceSSHPrivateKey", &Repository{}, &Repository{SSHPrivateKey: "foo"}, Repository{SSHPrivateKey: "foo"}},
|
||||
{"SourceInsecureHostKey", &Repository{}, &Repository{InsecureIgnoreHostKey: true}, Repository{InsecureIgnoreHostKey: false}},
|
||||
{"SourceInsecure", &Repository{}, &Repository{Insecure: true}, Repository{Insecure: false}},
|
||||
@@ -1284,6 +1291,7 @@ func TestRepository_CopyCredentialsFrom(t *testing.T) {
|
||||
}{
|
||||
{"Username", &Repository{Username: "foo"}, &RepoCreds{}, Repository{Username: "foo"}},
|
||||
{"Password", &Repository{Password: "foo"}, &RepoCreds{}, Repository{Password: "foo"}},
|
||||
{"BearerToken", &Repository{BearerToken: "foo"}, &RepoCreds{}, Repository{BearerToken: "foo"}},
|
||||
{"SSHPrivateKey", &Repository{SSHPrivateKey: "foo"}, &RepoCreds{}, Repository{SSHPrivateKey: "foo"}},
|
||||
{"InsecureHostKey", &Repository{InsecureIgnoreHostKey: true}, &RepoCreds{}, Repository{InsecureIgnoreHostKey: true}},
|
||||
{"Insecure", &Repository{Insecure: true}, &RepoCreds{}, Repository{Insecure: true}},
|
||||
@@ -1294,6 +1302,7 @@ func TestRepository_CopyCredentialsFrom(t *testing.T) {
|
||||
|
||||
{"SourceUsername", &Repository{}, &RepoCreds{Username: "foo"}, Repository{Username: "foo"}},
|
||||
{"SourcePassword", &Repository{}, &RepoCreds{Password: "foo"}, Repository{Password: "foo"}},
|
||||
{"SourceBearerToken", &Repository{}, &RepoCreds{BearerToken: "foo"}, Repository{BearerToken: "foo"}},
|
||||
{"SourceSSHPrivateKey", &Repository{}, &RepoCreds{SSHPrivateKey: "foo"}, Repository{SSHPrivateKey: "foo"}},
|
||||
{"SourceTLSClientCertData", &Repository{}, &RepoCreds{TLSClientCertData: "foo"}, Repository{TLSClientCertData: "foo"}},
|
||||
{"SourceTLSClientCertKey", &Repository{}, &RepoCreds{TLSClientCertKey: "foo"}, Repository{TLSClientCertKey: "foo"}},
|
||||
|
||||
@@ -671,6 +671,7 @@ func (s *Server) ValidateAccess(ctx context.Context, q *repositorypkg.RepoAccess
|
||||
Name: q.Name,
|
||||
Username: q.Username,
|
||||
Password: q.Password,
|
||||
BearerToken: q.BearerToken,
|
||||
SSHPrivateKey: q.SshPrivateKey,
|
||||
Insecure: q.Insecure,
|
||||
TLSClientCertData: q.TlsClientCertData,
|
||||
@@ -719,6 +720,7 @@ func (s *Server) ValidateWriteAccess(ctx context.Context, q *repositorypkg.RepoA
|
||||
Name: q.Name,
|
||||
Username: q.Username,
|
||||
Password: q.Password,
|
||||
BearerToken: q.BearerToken,
|
||||
SSHPrivateKey: q.SshPrivateKey,
|
||||
Insecure: q.Insecure,
|
||||
TLSClientCertData: q.TlsClientCertData,
|
||||
|
||||
@@ -91,6 +91,8 @@ message RepoAccessQuery {
|
||||
bool forceHttpBasicAuth = 19;
|
||||
// Whether to use azure workload identity for authentication
|
||||
bool useAzureWorkloadIdentity = 20;
|
||||
// BearerToken contains the bearer token used for Git auth at the repo server
|
||||
string bearerToken = 21;
|
||||
}
|
||||
|
||||
message RepoResponse {}
|
||||
|
||||
@@ -122,6 +122,7 @@ const (
|
||||
RepoURLTypeHelmOCI = "helm-oci"
|
||||
GitUsername = "admin"
|
||||
GitPassword = "password"
|
||||
GitBearerToken = "test"
|
||||
GithubAppID = "2978632978"
|
||||
GithubAppInstallationID = "7893789433789"
|
||||
GpgGoodKeyID = "D56C4FCA57A46444"
|
||||
|
||||
@@ -175,3 +175,32 @@ func TestAddHelmRepoInsecureSkipVerify(t *testing.T) {
|
||||
assert.True(t, exists)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFailOnPrivateRepoCreationWithPasswordAndBearerToken(t *testing.T) {
|
||||
app.Given(t).And(func() {
|
||||
repoURL := fixture.RepoURL(fixture.RepoURLTypeFile)
|
||||
_, err := fixture.RunCli("repo", "add", repoURL, "--password", fixture.GitPassword, "--bearer-token", fixture.GitBearerToken)
|
||||
require.ErrorContains(t, err, "only --bearer-token or --password is allowed, not both")
|
||||
})
|
||||
}
|
||||
|
||||
func TestFailOnCreatePrivateNonHTTPSRepoWithBearerToken(t *testing.T) {
|
||||
app.Given(t).And(func() {
|
||||
repoURL := fixture.RepoURL(fixture.RepoURLTypeFile)
|
||||
_, err := fixture.RunCli("repo", "add", repoURL, "--bearer-token", fixture.GitBearerToken)
|
||||
require.ErrorContains(t, err, "--bearer-token is only supported for HTTPS repositories")
|
||||
})
|
||||
}
|
||||
|
||||
func TestFailOnCreatePrivateNonGitRepoWithBearerToken(t *testing.T) {
|
||||
app.Given(t).And(func() {
|
||||
repoURL := fixture.RepoURL(fixture.RepoURLTypeHelm)
|
||||
_, err := fixture.RunCli("repo", "add", repoURL, "--bearer-token", fixture.GitBearerToken,
|
||||
"--insecure-skip-server-verification",
|
||||
"--tls-client-cert-path", repos.CertPath,
|
||||
"--tls-client-cert-key-path", repos.CertKeyPath,
|
||||
"--name", "testrepo",
|
||||
"--type", "helm")
|
||||
require.ErrorContains(t, err, "--bearer-token is only supported for Git repositories")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -37,6 +37,14 @@ export const RepoDetails = (props: {repo: models.Repository; save?: (params: New
|
||||
}
|
||||
];
|
||||
|
||||
if (repository.type === 'git') {
|
||||
items.push({
|
||||
title: 'Bearer token (optional, for BitBucket Data Center only)',
|
||||
view: repository.bearerToken ? '******' : '',
|
||||
edit: (formApi: FormApi) => <FormField formApi={formApi} field='bearerToken' component={Text} componentProps={{type: 'password'}} />
|
||||
});
|
||||
}
|
||||
|
||||
if (useAuthSettingsCtx?.hydratorEnabled) {
|
||||
// Insert this item at index 1.
|
||||
const item = {
|
||||
@@ -77,6 +85,7 @@ export const RepoDetails = (props: {repo: models.Repository; save?: (params: New
|
||||
url: repo.repo,
|
||||
username: repo.username || '',
|
||||
password: repo.password || '',
|
||||
bearerToken: repo.bearerToken || '',
|
||||
tlsClientCertData: repo.tlsClientCertData || '',
|
||||
tlsClientCertKey: repo.tlsClientCertKey || '',
|
||||
insecure: repo.insecure || false,
|
||||
@@ -94,13 +103,15 @@ export const RepoDetails = (props: {repo: models.Repository; save?: (params: New
|
||||
values={repo}
|
||||
validate={input => ({
|
||||
username: !input.username && input.password && 'Username is required if password is given.',
|
||||
password: !input.password && input.username && 'Password is required if username is given.'
|
||||
password: !input.password && input.username && 'Password is required if username is given.',
|
||||
bearerToken: input.password && input.bearerToken && 'Either the password or the bearer token must be set, but not both.'
|
||||
})}
|
||||
save={async input => {
|
||||
const params: NewHTTPSRepoParams = {...newRepo, write};
|
||||
params.name = input.name || '';
|
||||
params.username = input.username || '';
|
||||
params.password = input.password || '';
|
||||
params.bearerToken = input.bearerToken || '';
|
||||
save(params);
|
||||
}}
|
||||
title='CONNECTED REPOSITORY'
|
||||
|
||||
@@ -33,6 +33,7 @@ export interface NewHTTPSRepoParams {
|
||||
url: string;
|
||||
username: string;
|
||||
password: string;
|
||||
bearerToken: string;
|
||||
tlsClientCertData: string;
|
||||
tlsClientCertKey: string;
|
||||
insecure: boolean;
|
||||
@@ -89,6 +90,7 @@ interface NewHTTPSRepoCredsParams {
|
||||
url: string;
|
||||
username: string;
|
||||
password: string;
|
||||
bearerToken: string;
|
||||
tlsClientCertData: string;
|
||||
tlsClientCertKey: string;
|
||||
proxy: string;
|
||||
@@ -214,6 +216,9 @@ export class ReposList extends React.Component<
|
||||
name: httpsValues.type === 'helm' && !httpsValues.name && 'Name is required',
|
||||
username: !httpsValues.username && httpsValues.password && 'Username is required if password is given.',
|
||||
password: !httpsValues.password && httpsValues.username && 'Password is required if username is given.',
|
||||
bearerToken:
|
||||
(httpsValues.password && httpsValues.bearerToken && 'Either the password or the bearer token must be set, but not both.') ||
|
||||
(httpsValues.type != 'git' && 'Bearer token is only supported for Git BitBucket Data Center repositories'),
|
||||
tlsClientCertKey: !httpsValues.tlsClientCertKey && httpsValues.tlsClientCertData && 'TLS client cert key is required if TLS client cert is given.'
|
||||
};
|
||||
case ConnectionMethod.GITHUBAPP:
|
||||
@@ -681,6 +686,17 @@ export class ReposList extends React.Component<
|
||||
componentProps={{type: 'password'}}
|
||||
/>
|
||||
</div>
|
||||
{formApi.getFormState().values.type === 'git' && (
|
||||
<div className='argo-form-row'>
|
||||
<FormField
|
||||
formApi={formApi}
|
||||
label='Bearer token (optional, for BitBucket Data Center only)'
|
||||
field='bearerToken'
|
||||
component={Text}
|
||||
componentProps={{type: 'password'}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={formApi} label='TLS client certificate (optional)' field='tlsClientCertData' component={TextArea} />
|
||||
</div>
|
||||
@@ -920,6 +936,7 @@ export class ReposList extends React.Component<
|
||||
url: params.url,
|
||||
username: params.username,
|
||||
password: params.password,
|
||||
bearerToken: params.bearerToken,
|
||||
tlsClientCertData: params.tlsClientCertData,
|
||||
tlsClientCertKey: params.tlsClientCertKey,
|
||||
proxy: params.proxy,
|
||||
|
||||
@@ -598,6 +598,7 @@ export interface Repository {
|
||||
project?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
bearerToken?: string;
|
||||
tlsClientCertData?: string;
|
||||
tlsClientCertKey?: string;
|
||||
proxy?: string;
|
||||
@@ -615,6 +616,7 @@ export interface RepositoryList extends ItemsList<Repository> {}
|
||||
export interface RepoCreds {
|
||||
url: string;
|
||||
username?: string;
|
||||
bearerToken?: string;
|
||||
}
|
||||
|
||||
export interface RepoCredsList extends ItemsList<RepoCreds> {}
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface HTTPSQuery {
|
||||
url: string;
|
||||
username: string;
|
||||
password: string;
|
||||
bearerToken: string;
|
||||
tlsClientCertData: string;
|
||||
tlsClientCertKey: string;
|
||||
insecure: boolean;
|
||||
@@ -96,6 +97,7 @@ export class RepositoriesService {
|
||||
repo: q.url,
|
||||
username: q.username,
|
||||
password: q.password,
|
||||
bearerToken: q.bearerToken,
|
||||
tlsClientCertData: q.tlsClientCertData,
|
||||
tlsClientCertKey: q.tlsClientCertKey,
|
||||
insecure: q.insecure,
|
||||
@@ -119,6 +121,7 @@ export class RepositoriesService {
|
||||
repo: q.url,
|
||||
username: q.username,
|
||||
password: q.password,
|
||||
bearerToken: q.bearerToken,
|
||||
tlsClientCertData: q.tlsClientCertData,
|
||||
tlsClientCertKey: q.tlsClientCertKey,
|
||||
insecure: q.insecure,
|
||||
@@ -142,6 +145,7 @@ export class RepositoriesService {
|
||||
repo: q.url,
|
||||
username: q.username,
|
||||
password: q.password,
|
||||
bearerToken: q.bearerToken,
|
||||
tlsClientCertData: q.tlsClientCertData,
|
||||
tlsClientCertKey: q.tlsClientCertKey,
|
||||
insecure: q.insecure,
|
||||
@@ -165,6 +169,7 @@ export class RepositoriesService {
|
||||
repo: q.url,
|
||||
username: q.username,
|
||||
password: q.password,
|
||||
bearerToken: q.bearerToken,
|
||||
tlsClientCertData: q.tlsClientCertData,
|
||||
tlsClientCertKey: q.tlsClientCertKey,
|
||||
insecure: q.insecure,
|
||||
|
||||
@@ -5,6 +5,7 @@ export interface HTTPSCreds {
|
||||
url: string;
|
||||
username: string;
|
||||
password: string;
|
||||
bearerToken: string;
|
||||
tlsClientCertData: string;
|
||||
tlsClientCertKey: string;
|
||||
proxy: string;
|
||||
|
||||
@@ -306,6 +306,7 @@ func secretToRepository(secret *corev1.Secret) (*appsv1.Repository, error) {
|
||||
Repo: string(secret.Data["url"]),
|
||||
Username: string(secret.Data["username"]),
|
||||
Password: string(secret.Data["password"]),
|
||||
BearerToken: string(secret.Data["bearerToken"]),
|
||||
SSHPrivateKey: string(secret.Data["sshPrivateKey"]),
|
||||
TLSClientCertData: string(secret.Data["tlsClientCertData"]),
|
||||
TLSClientCertKey: string(secret.Data["tlsClientCertKey"]),
|
||||
@@ -379,6 +380,7 @@ func (s *secretsRepositoryBackend) repositoryToSecret(repository *appsv1.Reposit
|
||||
updateSecretString(secret, "url", repository.Repo)
|
||||
updateSecretString(secret, "username", repository.Username)
|
||||
updateSecretString(secret, "password", repository.Password)
|
||||
updateSecretString(secret, "bearerToken", repository.BearerToken)
|
||||
updateSecretString(secret, "sshPrivateKey", repository.SSHPrivateKey)
|
||||
updateSecretBool(secret, "enableOCI", repository.EnableOCI)
|
||||
updateSecretString(secret, "tlsClientCertData", repository.TLSClientCertData)
|
||||
@@ -404,6 +406,7 @@ func (s *secretsRepositoryBackend) secretToRepoCred(secret *corev1.Secret) (*app
|
||||
URL: string(secret.Data["url"]),
|
||||
Username: string(secret.Data["username"]),
|
||||
Password: string(secret.Data["password"]),
|
||||
BearerToken: string(secret.Data["bearerToken"]),
|
||||
SSHPrivateKey: string(secret.Data["sshPrivateKey"]),
|
||||
TLSClientCertData: string(secret.Data["tlsClientCertData"]),
|
||||
TLSClientCertKey: string(secret.Data["tlsClientCertKey"]),
|
||||
@@ -456,6 +459,7 @@ func repoCredsToSecret(repoCreds *appsv1.RepoCreds, secret *corev1.Secret) {
|
||||
updateSecretString(secret, "url", repoCreds.URL)
|
||||
updateSecretString(secret, "username", repoCreds.Username)
|
||||
updateSecretString(secret, "password", repoCreds.Password)
|
||||
updateSecretString(secret, "bearerToken", repoCreds.BearerToken)
|
||||
updateSecretString(secret, "sshPrivateKey", repoCreds.SSHPrivateKey)
|
||||
updateSecretBool(secret, "enableOCI", repoCreds.EnableOCI)
|
||||
updateSecretString(secret, "tlsClientCertData", repoCreds.TLSClientCertData)
|
||||
|
||||
@@ -295,6 +295,9 @@ func newAuth(repoURL string, creds Creds) (transport.AuthMethod, error) {
|
||||
}
|
||||
return auth, nil
|
||||
case HTTPSCreds:
|
||||
if creds.bearerToken != "" {
|
||||
return &githttp.TokenAuth{Token: creds.bearerToken}, nil
|
||||
}
|
||||
auth := githttp.BasicAuth{Username: creds.username, Password: creds.password}
|
||||
if auth.Username == "" {
|
||||
auth.Username = "x-access-token"
|
||||
@@ -967,6 +970,8 @@ func (m *nativeGitClient) runCredentialedCmd(args ...string) error {
|
||||
for _, e := range environ {
|
||||
if strings.HasPrefix(e, forceBasicAuthHeaderEnv+"=") {
|
||||
args = append([]string{"--config-env", "http.extraHeader=" + forceBasicAuthHeaderEnv}, args...)
|
||||
} else if strings.HasPrefix(e, bearerAuthHeaderEnv+"=") {
|
||||
args = append([]string{"--config-env", "http.extraHeader=" + bearerAuthHeaderEnv}, args...)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
@@ -9,6 +12,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
githttp "github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -851,3 +855,142 @@ func Test_newAuth_AzureWorkloadIdentity(t *testing.T) {
|
||||
_, ok := auth.(*githttp.TokenAuth)
|
||||
require.Truef(t, ok, "expected TokenAuth but got %T", auth)
|
||||
}
|
||||
|
||||
func TestNewAuth(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
repoURL string
|
||||
creds Creds
|
||||
expected transport.AuthMethod
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "HTTPSCreds with bearer token",
|
||||
repoURL: "https://github.com/org/repo.git",
|
||||
creds: HTTPSCreds{
|
||||
bearerToken: "test-token",
|
||||
},
|
||||
expected: &githttp.TokenAuth{Token: "test-token"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "HTTPSCreds with basic auth",
|
||||
repoURL: "https://github.com/org/repo.git",
|
||||
creds: HTTPSCreds{
|
||||
username: "test-user",
|
||||
password: "test-password",
|
||||
},
|
||||
expected: &githttp.BasicAuth{Username: "test-user", Password: "test-password"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "HTTPSCreds with basic auth no username",
|
||||
repoURL: "https://github.com/org/repo.git",
|
||||
creds: HTTPSCreds{
|
||||
password: "test-password",
|
||||
},
|
||||
expected: &githttp.BasicAuth{Username: "x-access-token", Password: "test-password"},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
auth, err := newAuth(tt.repoURL, tt.creds)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("newAuth() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
assert.Equal(t, tt.expected, auth)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_nativeGitClient_runCredentialedCmd(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
creds Creds
|
||||
environ []string
|
||||
expectedArgs []string
|
||||
expectedEnv []string
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
name: "basic auth header set",
|
||||
creds: &mockCreds{
|
||||
environ: []string{forceBasicAuthHeaderEnv + "=Basic dGVzdDp0ZXN0"},
|
||||
},
|
||||
expectedArgs: []string{"--config-env", "http.extraHeader=" + forceBasicAuthHeaderEnv, "status"},
|
||||
expectedEnv: []string{forceBasicAuthHeaderEnv + "=Basic dGVzdDp0ZXN0"},
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "bearer auth header set",
|
||||
creds: &mockCreds{
|
||||
environ: []string{bearerAuthHeaderEnv + "=Bearer test-token"},
|
||||
},
|
||||
expectedArgs: []string{"--config-env", "http.extraHeader=" + bearerAuthHeaderEnv, "status"},
|
||||
expectedEnv: []string{bearerAuthHeaderEnv + "=Bearer test-token"},
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "no auth header set",
|
||||
creds: &mockCreds{
|
||||
environ: []string{},
|
||||
},
|
||||
expectedArgs: []string{"status"},
|
||||
expectedEnv: []string{},
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "error getting environment",
|
||||
creds: &mockCreds{
|
||||
environErr: true,
|
||||
},
|
||||
expectedArgs: []string{},
|
||||
expectedEnv: []string{},
|
||||
expectedErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
client := &nativeGitClient{
|
||||
creds: tt.creds,
|
||||
}
|
||||
|
||||
err := client.runCredentialedCmd("status")
|
||||
if (err != nil) != tt.expectedErr {
|
||||
t.Errorf("runCredentialedCmd() error = %v, expectedErr %v", err, tt.expectedErr)
|
||||
return
|
||||
}
|
||||
|
||||
if tt.expectedErr {
|
||||
return
|
||||
}
|
||||
|
||||
cmd := exec.Command("git", tt.expectedArgs...)
|
||||
cmd.Env = append(os.Environ(), tt.expectedEnv...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Errorf("runCredentialedCmd() command error = %v, output = %s", err, output)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type mockCreds struct {
|
||||
environ []string
|
||||
environErr bool
|
||||
}
|
||||
|
||||
func (m *mockCreds) Environ() (io.Closer, []string, error) {
|
||||
if m.environErr {
|
||||
return nil, nil, errors.New("error getting environment")
|
||||
}
|
||||
return io.NopCloser(nil), m.environ, nil
|
||||
}
|
||||
|
||||
func (m *mockCreds) GetUserInfo(_ context.Context) (string, string, error) {
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ const (
|
||||
// githubAccessTokenUsername is a username that is used to with the github access token
|
||||
githubAccessTokenUsername = "x-access-token"
|
||||
forceBasicAuthHeaderEnv = "ARGOCD_GIT_AUTH_HEADER"
|
||||
bearerAuthHeaderEnv = "ARGOCD_GIT_BEARER_AUTH_HEADER"
|
||||
// This is the resource id of the OAuth application of Azure Devops.
|
||||
azureDevopsEntraResourceId = "499b84ac-1321-427f-aa17-267ca6975798/.default"
|
||||
)
|
||||
@@ -133,6 +134,8 @@ type HTTPSCreds struct {
|
||||
username string
|
||||
// Password for authentication
|
||||
password string
|
||||
// Bearer token for authentication
|
||||
bearerToken string
|
||||
// Whether to ignore invalid server certificates
|
||||
insecure bool
|
||||
// Client certificate to use
|
||||
@@ -149,10 +152,11 @@ type HTTPSCreds struct {
|
||||
forceBasicAuth bool
|
||||
}
|
||||
|
||||
func NewHTTPSCreds(username string, password string, clientCertData string, clientCertKey string, insecure bool, proxy string, noProxy string, store CredsStore, forceBasicAuth bool) GenericHTTPSCreds {
|
||||
func NewHTTPSCreds(username string, password string, bearerToken string, clientCertData string, clientCertKey string, insecure bool, proxy string, noProxy string, store CredsStore, forceBasicAuth bool) GenericHTTPSCreds {
|
||||
return HTTPSCreds{
|
||||
username,
|
||||
password,
|
||||
bearerToken,
|
||||
insecure,
|
||||
clientCertData,
|
||||
clientCertKey,
|
||||
@@ -176,6 +180,11 @@ func (creds HTTPSCreds) BasicAuthHeader() string {
|
||||
return h
|
||||
}
|
||||
|
||||
func (creds HTTPSCreds) BearerAuthHeader() string {
|
||||
h := "Authorization: Bearer " + creds.bearerToken
|
||||
return h
|
||||
}
|
||||
|
||||
// Get additional required environment variables for executing git client to
|
||||
// access specific repository via HTTPS.
|
||||
func (creds HTTPSCreds) Environ() (io.Closer, []string, error) {
|
||||
@@ -237,6 +246,9 @@ func (creds HTTPSCreds) Environ() (io.Closer, []string, error) {
|
||||
// skipped. This is insecure, but some environments may need it.
|
||||
if creds.password != "" && creds.forceBasicAuth {
|
||||
env = append(env, fmt.Sprintf("%s=%s", forceBasicAuthHeaderEnv, creds.BasicAuthHeader()))
|
||||
} else if creds.bearerToken != "" {
|
||||
// If bearer token is set, we will set ARGOCD_BEARER_AUTH_HEADER to hold the HTTP authorization header
|
||||
env = append(env, fmt.Sprintf("%s=%s", bearerAuthHeaderEnv, creds.BearerAuthHeader()))
|
||||
}
|
||||
nonce := creds.store.Add(text.FirstNonEmpty(creds.username, githubAccessTokenUsername), creds.password)
|
||||
env = append(env, creds.store.Environ(nonce)...)
|
||||
|
||||
@@ -52,7 +52,7 @@ func (s *memoryCredsStore) Environ(_ string) []string {
|
||||
|
||||
func TestHTTPSCreds_Environ_no_cert_cleanup(t *testing.T) {
|
||||
store := &memoryCredsStore{creds: make(map[string]cred)}
|
||||
creds := NewHTTPSCreds("", "", "", "", true, "", "", store, false)
|
||||
creds := NewHTTPSCreds("", "", "", "", "", true, "", "", store, false)
|
||||
closer, _, err := creds.Environ()
|
||||
require.NoError(t, err)
|
||||
credsLenBefore := len(store.creds)
|
||||
@@ -61,7 +61,7 @@ func TestHTTPSCreds_Environ_no_cert_cleanup(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHTTPSCreds_Environ_insecure_true(t *testing.T) {
|
||||
creds := NewHTTPSCreds("", "", "", "", true, "", "", &NoopCredsStore{}, false)
|
||||
creds := NewHTTPSCreds("", "", "", "", "", true, "", "", &NoopCredsStore{}, false)
|
||||
closer, env, err := creds.Environ()
|
||||
t.Cleanup(func() {
|
||||
io.Close(closer)
|
||||
@@ -78,7 +78,7 @@ func TestHTTPSCreds_Environ_insecure_true(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHTTPSCreds_Environ_insecure_false(t *testing.T) {
|
||||
creds := NewHTTPSCreds("", "", "", "", false, "", "", &NoopCredsStore{}, false)
|
||||
creds := NewHTTPSCreds("", "", "", "", "", false, "", "", &NoopCredsStore{}, false)
|
||||
closer, env, err := creds.Environ()
|
||||
t.Cleanup(func() {
|
||||
io.Close(closer)
|
||||
@@ -97,7 +97,7 @@ func TestHTTPSCreds_Environ_insecure_false(t *testing.T) {
|
||||
func TestHTTPSCreds_Environ_forceBasicAuth(t *testing.T) {
|
||||
t.Run("Enabled and credentials set", func(t *testing.T) {
|
||||
store := &memoryCredsStore{creds: make(map[string]cred)}
|
||||
creds := NewHTTPSCreds("username", "password", "", "", false, "", "", store, true)
|
||||
creds := NewHTTPSCreds("username", "password", "", "", "", false, "", "", store, true)
|
||||
closer, env, err := creds.Environ()
|
||||
require.NoError(t, err)
|
||||
defer closer.Close()
|
||||
@@ -115,7 +115,7 @@ func TestHTTPSCreds_Environ_forceBasicAuth(t *testing.T) {
|
||||
})
|
||||
t.Run("Enabled but credentials not set", func(t *testing.T) {
|
||||
store := &memoryCredsStore{creds: make(map[string]cred)}
|
||||
creds := NewHTTPSCreds("", "", "", "", false, "", "", store, true)
|
||||
creds := NewHTTPSCreds("", "", "", "", "", false, "", "", store, true)
|
||||
closer, env, err := creds.Environ()
|
||||
require.NoError(t, err)
|
||||
defer closer.Close()
|
||||
@@ -132,7 +132,7 @@ func TestHTTPSCreds_Environ_forceBasicAuth(t *testing.T) {
|
||||
})
|
||||
t.Run("Disabled with credentials set", func(t *testing.T) {
|
||||
store := &memoryCredsStore{creds: make(map[string]cred)}
|
||||
creds := NewHTTPSCreds("username", "password", "", "", false, "", "", store, false)
|
||||
creds := NewHTTPSCreds("username", "password", "", "", "", false, "", "", store, false)
|
||||
closer, env, err := creds.Environ()
|
||||
require.NoError(t, err)
|
||||
defer closer.Close()
|
||||
@@ -150,7 +150,7 @@ func TestHTTPSCreds_Environ_forceBasicAuth(t *testing.T) {
|
||||
|
||||
t.Run("Disabled with credentials not set", func(t *testing.T) {
|
||||
store := &memoryCredsStore{creds: make(map[string]cred)}
|
||||
creds := NewHTTPSCreds("", "", "", "", false, "", "", store, false)
|
||||
creds := NewHTTPSCreds("", "", "", "", "", false, "", "", store, false)
|
||||
closer, env, err := creds.Environ()
|
||||
require.NoError(t, err)
|
||||
defer closer.Close()
|
||||
@@ -167,9 +167,29 @@ func TestHTTPSCreds_Environ_forceBasicAuth(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestHTTPSCreds_Environ_bearerTokenAuth(t *testing.T) {
|
||||
t.Run("Enabled and credentials set", func(t *testing.T) {
|
||||
store := &memoryCredsStore{creds: make(map[string]cred)}
|
||||
creds := NewHTTPSCreds("", "", "token", "", "", false, "", "", store, false)
|
||||
closer, env, err := creds.Environ()
|
||||
require.NoError(t, err)
|
||||
defer closer.Close()
|
||||
var header string
|
||||
for _, envVar := range env {
|
||||
if strings.HasPrefix(envVar, bearerAuthHeaderEnv+"=") {
|
||||
header = envVar[len(bearerAuthHeaderEnv)+1:]
|
||||
}
|
||||
if header != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.Equal(t, "Authorization: Bearer token", header)
|
||||
})
|
||||
}
|
||||
|
||||
func TestHTTPSCreds_Environ_clientCert(t *testing.T) {
|
||||
store := &memoryCredsStore{creds: make(map[string]cred)}
|
||||
creds := NewHTTPSCreds("", "", "clientCertData", "clientCertKey", false, "", "", store, false)
|
||||
creds := NewHTTPSCreds("", "", "", "clientCertData", "clientCertKey", false, "", "", store, false)
|
||||
closer, env, err := creds.Environ()
|
||||
require.NoError(t, err)
|
||||
var cert, key string
|
||||
|
||||
@@ -134,7 +134,7 @@ func TestCustomHTTPClient(t *testing.T) {
|
||||
assert.NotEqual(t, "", string(keyData))
|
||||
|
||||
// Get HTTPSCreds with client cert creds specified, and insecure connection
|
||||
creds := NewHTTPSCreds("test", "test", string(certData), string(keyData), false, "http://proxy:5000", "", &NoopCredsStore{}, false)
|
||||
creds := NewHTTPSCreds("test", "test", "", string(certData), string(keyData), false, "http://proxy:5000", "", &NoopCredsStore{}, false)
|
||||
client := GetRepoHTTPClient("https://localhost:9443/foo/bar", false, creds, "http://proxy:5000", "")
|
||||
assert.NotNil(t, client)
|
||||
assert.NotNil(t, client.Transport)
|
||||
@@ -163,7 +163,7 @@ func TestCustomHTTPClient(t *testing.T) {
|
||||
t.Setenv("http_proxy", "http://proxy-from-env:7878")
|
||||
|
||||
// Get HTTPSCreds without client cert creds, but insecure connection
|
||||
creds = NewHTTPSCreds("test", "test", "", "", true, "", "", &NoopCredsStore{}, false)
|
||||
creds = NewHTTPSCreds("test", "test", "", "", "", true, "", "", &NoopCredsStore{}, false)
|
||||
client = GetRepoHTTPClient("https://localhost:9443/foo/bar", true, creds, "", "")
|
||||
assert.NotNil(t, client)
|
||||
assert.NotNil(t, client.Transport)
|
||||
|
||||
Reference in New Issue
Block a user